package native_test

import (
	"encoding/json"
	"fmt"
	"testing"

	"git.marketally.com/tutus-one/tutus-chain/pkg/config"
	"git.marketally.com/tutus-one/tutus-chain/pkg/core/state"
	"git.marketally.com/tutus-one/tutus-chain/pkg/tutustest"
	"git.marketally.com/tutus-one/tutus-chain/pkg/tutustest/chain"
)

// TestGenerateExpectedContractStates outputs the current contract states as JSON
// for updating the defaultCSS, cockatriceCSS, echidnaCSS, and faunCSS maps.
// Run with: go test -v -run TestGenerateExpectedContractStates
func TestGenerateExpectedContractStates(t *testing.T) {
	const (
		cockatriceHeight = 3
		domovoiHeight    = 5
		echidnaHeight    = 6
		faunHeight       = 7
	)
	bc, acc := chain.NewSingleWithCustomConfig(t, func(cfg *config.Blockchain) {
		cfg.Hardforks = map[string]uint32{
			config.HFAspidochelone.String(): 0,
			config.HFBasilisk.String():      0,
			config.HFCockatrice.String():    cockatriceHeight,
			config.HFDomovoi.String():       domovoiHeight,
			config.HFEchidna.String():       echidnaHeight,
			config.HFFaun.String():          faunHeight,
		}
	})
	e := tutustest.NewExecutor(t, bc, acc, acc)

	// Generate defaultCSS (genesis state)
	fmt.Println("\n=== defaultCSS (genesis) ===")
	fmt.Println("defaultCSS = map[string]string{")
	natives := bc.GetNatives()
	for _, cs := range natives {
		csFull := state.Contract{
			ContractBase:  cs.ContractBase,
			UpdateCounter: 0,
		}
		jBytes, err := json.Marshal(csFull)
		if err != nil {
			t.Fatal(err)
		}
		fmt.Printf("\tnativenames.%s: `%s`,\n", getConstName(cs.Manifest.Name), string(jBytes))
	}
	fmt.Println("}")

	// Generate cockatriceCSS
	e.GenerateNewBlocks(t, cockatriceHeight)
	fmt.Println("\n=== cockatriceCSS ===")
	fmt.Println("cockatriceCSS = map[string]string{")
	natives = bc.GetNatives()
	for _, cs := range natives {
		csFull := state.Contract{
			ContractBase:  cs.ContractBase,
			UpdateCounter: 0,
		}
		jBytes, err := json.Marshal(csFull)
		if err != nil {
			t.Fatal(err)
		}
		fmt.Printf("\tnativenames.%s: `%s`,\n", getConstName(cs.Manifest.Name), string(jBytes))
	}
	fmt.Println("}")

	// Generate echidnaCSS
	e.GenerateNewBlocks(t, echidnaHeight-cockatriceHeight)
	fmt.Println("\n=== echidnaCSS ===")
	fmt.Println("echidnaCSS = map[string]string{")
	natives = bc.GetNatives()
	for _, cs := range natives {
		csFull := state.Contract{
			ContractBase:  cs.ContractBase,
			UpdateCounter: 0,
		}
		jBytes, err := json.Marshal(csFull)
		if err != nil {
			t.Fatal(err)
		}
		fmt.Printf("\tnativenames.%s: `%s`,\n", getConstName(cs.Manifest.Name), string(jBytes))
	}
	fmt.Println("}")

	// Generate faunCSS
	e.GenerateNewBlocks(t, faunHeight-echidnaHeight)
	fmt.Println("\n=== faunCSS ===")
	fmt.Println("faunCSS = map[string]string{")
	natives = bc.GetNatives()
	for _, cs := range natives {
		csFull := state.Contract{
			ContractBase:  cs.ContractBase,
			UpdateCounter: 0,
		}
		jBytes, err := json.Marshal(csFull)
		if err != nil {
			t.Fatal(err)
		}
		fmt.Printf("\tnativenames.%s: `%s`,\n", getConstName(cs.Manifest.Name), string(jBytes))
	}
	fmt.Println("}")
}

func getConstName(name string) string {
	switch name {
	case "ContractManagement":
		return "Management"
	case "StdLib":
		return "StdLib"
	case "CryptoLib":
		return "CryptoLib"
	case "LedgerContract":
		return "Ledger"
	case "Tutus":
		return "Tutus"
	case "Lub":
		return "Lub"
	case "PolicyContract":
		return "Policy"
	case "OracleContract":
		return "Oracle"
	case "RoleManagement":
		return "Designation"
	case "Notary":
		return "Notary"
	case "VitaToken":
		return "Vita"
	case "VtsToken":
		return "Vts"
	case "LexContract":
		return "Lex"
	case "ScireContract":
		return "Scire"
	case "SalusContract":
		return "Salus"
	case "SeseContract":
		return "Sese"
	case "TributeContract":
		return "Tribute"
	case "EligereContract":
		return "Eligere"
	case "OpusContract":
		return "Opus"
	case "PalamContract":
		return "Palam"
	case "PonsContract":
		return "Pons"
	case "CollocatioContract":
		return "Collocatio"
	case "AnnosContract":
		return "Annos"
	case "RoleRegistry":
		return "RoleRegistry"
	case "Treasury":
		return "Treasury"
	case "Federation":
		return "Federation"
	default:
		return name
	}
}
