package bscusdt

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"

	"hyapp/services/wallet-service/internal/config"
)

func TestVerifyUSDTTransferMatchesBEP20ReceiptLog(t *testing.T) {
	txHash := "0x" + strings.Repeat("1", 64)
	contract := "0x55d398326f99059fF775485246999027B3197955"
	toAddress := "0x1111111111111111111111111111111111111111"
	valueData := fmt.Sprintf("0x%064x", int64(150*10_000))
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Fatalf("expected JSON-RPC POST, got %s", r.Method)
		}
		_, _ = w.Write([]byte(fmt.Sprintf(`{
			"jsonrpc":"2.0",
			"id":1,
			"result":{
				"status":"0x1",
				"logs":[{
					"address":%q,
					"topics":[%q,"0x0000000000000000000000002222222222222222222222222222222222222222",%q],
					"data":%q
				}]
			}
		}`, contract, transferEventTopic, addressTopic(toAddress), valueData)))
	}))
	defer server.Close()
	client := New(config.BSCUSDTConfig{
		RPCURL:              server.URL,
		USDTContractAddress: contract,
		HTTPTimeout:         time.Second,
	})
	rawJSON, err := client.VerifyUSDTTransfer(context.Background(), txHash, toAddress, 150)
	if err != nil {
		t.Fatalf("VerifyUSDTTransfer failed: %v", err)
	}
	if !strings.Contains(rawJSON, `"status":"0x1"`) {
		t.Fatalf("raw json should preserve provider response, got %s", rawJSON)
	}
}

func TestVerifyUSDTTransferRejectsReceiptAmountMismatch(t *testing.T) {
	txHash := "0x" + strings.Repeat("2", 64)
	contract := "0x55d398326f99059fF775485246999027B3197955"
	toAddress := "0x1111111111111111111111111111111111111111"
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, _ = w.Write([]byte(fmt.Sprintf(`{
			"jsonrpc":"2.0",
			"id":1,
			"result":{
				"status":"0x1",
				"logs":[{
					"address":%q,
					"topics":[%q,"0x0000000000000000000000002222222222222222222222222222222222222222",%q],
					"data":"0x1"
				}]
			}
		}`, contract, transferEventTopic, addressTopic(toAddress))))
	}))
	defer server.Close()
	client := New(config.BSCUSDTConfig{
		RPCURL:              server.URL,
		USDTContractAddress: contract,
		HTTPTimeout:         time.Second,
	})
	rawJSON, err := client.VerifyUSDTTransfer(context.Background(), txHash, toAddress, 150)
	if err == nil {
		t.Fatalf("expected amount mismatch to be rejected")
	}
	if !strings.Contains(rawJSON, `"logs"`) {
		t.Fatalf("raw json should still be returned on semantic mismatch, got %s", rawJSON)
	}
}

func addressTopic(address string) string {
	return "0x000000000000000000000000" + strings.TrimPrefix(strings.ToLower(address), "0x")
}
