package rest

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestEnrichNativeCoinMarketFromBlockscout(t *testing.T) {
	tokenAgg := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusNotFound)
	}))
	defer tokenAgg.Close()
	t.Setenv("TOKEN_AGGREGATION_BASE_URL", tokenAgg.URL)

	blockscout := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		require.NoError(t, json.NewEncoder(w).Encode(map[string]any{
			"coin_price": "1701.77",
			"coin_image": "https://example.com/eth.png",
		}))
	}))
	defer blockscout.Close()

	t.Setenv("BLOCKSCOUT_STATS_URL", blockscout.URL)
	stats := explorerStats{}
	enrichNativeCoinMarket(context.Background(), &stats)

	require.NotNil(t, stats.CoinPrice)
	require.Equal(t, "1701.77", *stats.CoinPrice)
	require.NotNil(t, stats.CoinImage)
	require.Equal(t, "https://example.com/eth.png", *stats.CoinImage)
}

func TestEnrichNativeCoinMarketFallsBackToTokenAggregation(t *testing.T) {
	blockscout := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		require.NoError(t, json.NewEncoder(w).Encode(map[string]any{
			"coin_price": nil,
		}))
	}))
	defer blockscout.Close()

	tokenAgg := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Contains(t, r.URL.Path, chain138WETHAddress)
		w.Header().Set("Content-Type", "application/json")
		require.NoError(t, json.NewEncoder(w).Encode(map[string]any{
			"token": map[string]any{
				"market": map[string]any{
					"priceUsd": 1678.67,
				},
			},
		}))
	}))
	defer tokenAgg.Close()

	t.Setenv("BLOCKSCOUT_STATS_URL", blockscout.URL)
	t.Setenv("TOKEN_AGGREGATION_BASE_URL", tokenAgg.URL)
	stats := explorerStats{}
	enrichNativeCoinMarket(context.Background(), &stats)

	require.NotNil(t, stats.CoinPrice)
	require.Equal(t, "1678.67", *stats.CoinPrice)
}

func TestEnrichNativeCoinMarketPrefersTokenAggregationWithHostOnlyBaseURL(t *testing.T) {
	blockscout := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		require.NoError(t, json.NewEncoder(w).Encode(map[string]any{
			"coin_price": "1740.00",
		}))
	}))
	defer blockscout.Close()

	tokenAgg := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "/api/v1/tokens/"+chain138WETHAddress, r.URL.Path)
		w.Header().Set("Content-Type", "application/json")
		require.NoError(t, json.NewEncoder(w).Encode(map[string]any{
			"token": map[string]any{
				"market": map[string]any{
					"priceUsd": 1732.18,
				},
			},
		}))
	}))
	defer tokenAgg.Close()

	t.Setenv("BLOCKSCOUT_STATS_URL", blockscout.URL)
	t.Setenv("TOKEN_AGGREGATION_BASE_URL", tokenAgg.URL)
	stats := explorerStats{}
	enrichNativeCoinMarket(context.Background(), &stats)

	require.NotNil(t, stats.CoinPrice)
	require.Equal(t, "1732.18", *stats.CoinPrice)
}

func TestEnrichNativeCoinMarketPrefersTokenAggregationOverBlockscout(t *testing.T) {
	blockscout := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		require.NoError(t, json.NewEncoder(w).Encode(map[string]any{
			"coin_price": "1740.00",
			"coin_image": "https://example.com/eth.png",
		}))
	}))
	defer blockscout.Close()

	tokenAgg := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Contains(t, r.URL.Path, chain138WETHAddress)
		w.Header().Set("Content-Type", "application/json")
		require.NoError(t, json.NewEncoder(w).Encode(map[string]any{
			"token": map[string]any{
				"market": map[string]any{
					"priceUsd": 1732.18,
				},
			},
		}))
	}))
	defer tokenAgg.Close()

	t.Setenv("BLOCKSCOUT_STATS_URL", blockscout.URL)
	t.Setenv("TOKEN_AGGREGATION_BASE_URL", tokenAgg.URL)
	stats := explorerStats{}
	enrichNativeCoinMarket(context.Background(), &stats)

	require.NotNil(t, stats.CoinPrice)
	require.Equal(t, "1732.18", *stats.CoinPrice)
	require.NotNil(t, stats.CoinImage)
	require.Equal(t, "https://example.com/eth.png", *stats.CoinImage)
}
