package bitsongworkflow

import (
	"context"
	"encoding/json"
	"testing"

	"github.com/bitsongofficial/go-bitsong/tests/e2e/helpers"
	"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"
	"github.com/strangelove-ventures/interchaintest/v8/ibc"
	"github.com/stretchr/testify/require"
)

// ConformanceCosmWasm validates that store, instantiate, execute, and query work on a CosmWasm contract.
func WorkflowCosmwasm(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet) {
	StdExecute(t, ctx, chain, user)
	subMsg(t, ctx, chain, user)
}

func StdExecute(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet) (contractAddr string) {
	_, contractAddr = helpers.SetupContract(t, ctx, chain, user.KeyName(), "contracts/cw_template.wasm", `{"count":0}`)
	helpers.ExecuteMsgWithFee(t, ctx, chain, user, contractAddr, "", "10000"+chain.Config().Denom, `{"increment":{}}`)

	var res helpers.GetCountResponse
	err := helpers.SmartQueryString(t, ctx, chain, contractAddr, `{"get_count":{}}`, &res)
	require.NoError(t, err)
	require.Equal(t, int64(1), res.Data.Count)

	return contractAddr
}

func subMsg(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet) {
	// ref: https://github.com/CosmWasm/wasmd/issues/1735

	// // === execute a contract sub message ===
	// _, senderContractAddr := helpers.SetupContract(t, ctx, chain, user.KeyName(), "contracts/cw721_base.wasm.gz", fmt.Sprintf(`{"name":"Reece #00001", "symbol":"bitsong-reece-test-#00001", "minter":"%s"}`, user.FormattedAddress()))
	// _, receiverContractAddr := helpers.SetupContract(t, ctx, chain, user.KeyName(), "contracts/cw721_receiver.wasm.gz", `{}`)

	// // mint a token
	// res, err := helpers.ExecuteMsgWithFeeReturn(t, ctx, chain, user, senderContractAddr, "", "10000"+chain.Config().Denom, fmt.Sprintf(`{"mint":{"token_id":"00000", "owner":"%s"}}`, user.FormattedAddress()))
	// fmt.Println("First", res)
	// require.NoError(t, err)

	// // this purposely will fail with the current, we are just validating the messsage is not unknown.
	// // sub message of unknown means the `wasmkeeper.WithMessageHandlerDecorator` is not setup properly.
	// fail := "ImZhaWwi"
	// res2, err := helpers.ExecuteMsgWithFeeReturn(t, ctx, chain, user, senderContractAddr, "", "10000"+chain.Config().Denom, fmt.Sprintf(`{"send_nft": { "contract": "%s", "token_id": "00000", "msg": "%s" }}`, receiverContractAddr, fail))
	// require.NoError(t, err)
	// fmt.Println("Second", res2)
	// require.NotEqualValues(t, wasmtypes.ErrUnknownMsg.ABCICode(), res2.Code)
	// require.NotContains(t, res2.RawLog, "unknown message from the contract")

	// success := "InN1Y2NlZWQi"
	// res3, err := helpers.ExecuteMsgWithFeeReturn(t, ctx, chain, user, senderContractAddr, "", "10000"+chain.Config().Denom, fmt.Sprintf(`{"send_nft": { "contract": "%s", "token_id": "00000", "msg": "%s" }}`, receiverContractAddr, success))
	// require.NoError(t, err)
	// fmt.Println("Third", res3)
	// require.EqualValues(t, 0, res3.Code)
	// require.NotContains(t, res3.RawLog, "unknown message from the contract")
}

func SmartQueryString(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, contractAddr, queryMsg string, res interface{}) error {
	var jsonMap map[string]interface{}
	if err := json.Unmarshal([]byte(queryMsg), &jsonMap); err != nil {
		t.Fatal(err)
	}
	err := chain.QueryContract(ctx, contractAddr, jsonMap, &res)
	return err
}
