package main

import (
	"flag"
	"fmt"
	"sync"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/rlp"
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/cors"
	"github.com/gofiber/fiber/v2/middleware/proxy"

	// "github.com/gofiber/swagger"
	"golang.org/x/crypto/sha3"

	"github.com/ethereum/go-ethereum/accounts"
)

func main() {

	var listenPort int
	flag.IntVar(&listenPort, "listenPort", 6000, "proxy listen the port")
	var upstreamPort int
	flag.IntVar(&upstreamPort, "upstreamPort", 5000, "forwar the request to the upstream port with localhost")
	flag.Parse()

	app := fiber.New()
	app.Use(cors.New())

	// app.Static("/swagger/docs", "./docs")
	// app.Get("/swagger/*", swagger.New(swagger.Config{ // custom
	// 	URL:         "http://124.193.167.71:5001/swagger/docs/swagger.yaml", //http://124.193.167.71:8000/
	// 	DeepLinking: false,
	// 	// Expand ("list") or Collapse ("none") tag groups by default
	// 	DocExpansion: "none",
	// }))

	app.All("/*", func(c *fiber.Ctx) error {

		path := c.Path()

		fmt.Println("path", path)
		url := "http://127.0.0.1:" + fmt.Sprintf("%d", upstreamPort) + path
		if err := proxy.Do(c, url); err != nil {
			return err
		}
		// Remove Server header from response
		//c.Response().Header.Del(fiber.HeaderServer)

		h := accounts.TextHash([]byte(string(c.Response().Body())))

		fmt.Printf("%x\n", h)

		fmt.Println("c.Response().Body():", string(c.Response().Body()))

		local, _ := crypto.HexToECDSA("4df7e0d1c1329d03c72ed0cec631adc048ae85178d3528e7f55368da0901ed5b")

		sig, err := crypto.Sign(h[:], local)
		if err != nil {

			fmt.Println("error", err.Error(), "hash", fmt.Sprintf("%x", h), "body", string(c.Response().Body()))
			//return nil, err
			c.Response().Header.Add("X-ProxyBodyHash-SignatureCode", "500")
			c.Response().Header.Add("X-ProxyBodyHash-SignatureErr", err.Error())
		} else {
			c.Response().Header.Add("X-ProxyBodyHash-SignatureCode", "200")
		}
		//return tx.WithSignature(s, sig)
		c.Response().Header.Add("X-ProxyBodyHash", fmt.Sprintf("%x", h))
		c.Response().Header.Add("X-ProxyBodyHash-Signature", fmt.Sprintf("%x", sig))

		return nil
	})

	if err := app.Listen(fmt.Sprintf(":%d", listenPort)); err != nil {
		fmt.Println(" app.Listen", err.Error())
	}

}

// rlpHash encodes x and hashes the encoded bytes.
func rlpHash(x interface{}) (h common.Hash) {
	sha := hasherPool.Get().(crypto.KeccakState)
	defer hasherPool.Put(sha)
	sha.Reset()
	rlp.Encode(sha, x)
	sha.Read(h[:])
	return h
}

// hasherPool holds LegacyKeccak256 hashers for rlpHash.
var hasherPool = sync.Pool{
	New: func() interface{} { return sha3.NewLegacyKeccak256() },
}
