package socket

import (
	"testing"
	"time"

	altv1 "git.toki-labs.com/toki/alt/packages/contracts/gen/go/alt/v1"
	"git.toki-labs.com/toki/alt/packages/domain/market"
)

func TestInstrumentToProto(t *testing.T) {
	got := instrumentToProto(market.Instrument{
		ID:        "KRX:005930",
		Market:    market.MarketKR,
		Venue:     market.VenueKRX,
		Symbol:    "005930",
		Name:      "Samsung Electronics",
		Currency:  market.CurrencyKRW,
		AssetType: market.AssetTypeEquity,
		ProviderSymbols: map[string]string{
			"kis": "005930",
		},
	})

	if got.GetId() != "KRX:005930" {
		t.Errorf("id mismatch: %q", got.GetId())
	}
	if got.GetMarket() != altv1.Market_MARKET_KR {
		t.Errorf("market mismatch: %v", got.GetMarket())
	}
	if got.GetVenue() != altv1.Venue_VENUE_KRX {
		t.Errorf("venue mismatch: %v", got.GetVenue())
	}
	if got.GetCurrency() != altv1.Currency_CURRENCY_KRW {
		t.Errorf("currency mismatch: %v", got.GetCurrency())
	}
	if got.GetAssetType() != altv1.AssetType_ASSET_TYPE_EQUITY {
		t.Errorf("asset type mismatch: %v", got.GetAssetType())
	}
	if got.GetProviderSymbols()["kis"] != "005930" {
		t.Errorf("provider symbols mismatch: %+v", got.GetProviderSymbols())
	}
}

func TestAssetTypeMapping(t *testing.T) {
	cases := []struct {
		domain market.AssetType
		proto  altv1.AssetType
	}{
		{market.AssetTypeEquity, altv1.AssetType_ASSET_TYPE_EQUITY},
		{market.AssetTypeETF, altv1.AssetType_ASSET_TYPE_ETF},
		{market.AssetType(""), altv1.AssetType_ASSET_TYPE_UNSPECIFIED},
	}
	for _, c := range cases {
		gotProto := assetTypeToProto(c.domain)
		if gotProto != c.proto {
			t.Errorf("assetTypeToProto(%q): got %v, want %v", c.domain, gotProto, c.proto)
		}
		gotDomain, err := assetTypeFromProto(c.proto)
		if err != nil {
			t.Errorf("assetTypeFromProto(%v) error: %v", c.proto, err)
		}
		if gotDomain != c.domain {
			t.Errorf("assetTypeFromProto(%v): got %q, want %q", c.proto, gotDomain, c.domain)
		}
	}
}

func TestInstrumentToProtoClonesProviderSymbols(t *testing.T) {
	symbols := map[string]string{"kis": "005930"}
	got := instrumentToProto(market.Instrument{ProviderSymbols: symbols})
	symbols["kis"] = "changed"

	if got.GetProviderSymbols()["kis"] != "005930" {
		t.Errorf("provider symbols should be cloned, got %+v", got.GetProviderSymbols())
	}
}

func TestBarToProto(t *testing.T) {
	ts := time.Date(2026, 5, 29, 0, 0, 0, 0, time.UTC)
	got := barToProto(market.Bar{
		InstrumentID: "KRX:005930",
		Timeframe:    market.TimeframeDaily,
		Timestamp:    ts,
		Open:         market.Price{Currency: market.CurrencyKRW, Amount: market.Decimal{Value: "70000"}},
		High:         market.Price{Currency: market.CurrencyKRW, Amount: market.Decimal{Value: "71000"}},
		Low:          market.Price{Currency: market.CurrencyKRW, Amount: market.Decimal{Value: "69000"}},
		Close:        market.Price{Currency: market.CurrencyKRW, Amount: market.Decimal{Value: "70500"}},
		Volume:       market.Quantity{Amount: market.Decimal{Value: "1000000"}},
	})

	if got.GetInstrumentId() != "KRX:005930" {
		t.Errorf("instrument mismatch: %q", got.GetInstrumentId())
	}
	if got.GetTimeframe() != altv1.Timeframe_TIMEFRAME_DAILY {
		t.Errorf("timeframe mismatch: %v", got.GetTimeframe())
	}
	if got.GetTimestampUnixMs() != ts.UnixMilli() {
		t.Errorf("timestamp mismatch: %d", got.GetTimestampUnixMs())
	}
	if got.GetOpen().GetAmount().GetValue() != "70000" || got.GetOpen().GetCurrency() != altv1.Currency_CURRENCY_KRW {
		t.Errorf("open price mismatch: %+v", got.GetOpen())
	}
	if got.GetVolume().GetAmount().GetValue() != "1000000" {
		t.Errorf("volume mismatch: %+v", got.GetVolume())
	}
}

func TestInstrumentToProtoUS(t *testing.T) {
	got := instrumentToProto(market.Instrument{
		ID:        "NASDAQ:AAPL",
		Market:    market.MarketUS,
		Venue:     market.VenueNASDAQ,
		Symbol:    "AAPL",
		Name:      "Apple Inc",
		Currency:  market.CurrencyUSD,
		AssetType: market.AssetTypeETF,
		ProviderSymbols: map[string]string{
			"kis": "AAPL",
		},
	})

	if got.GetId() != "NASDAQ:AAPL" {
		t.Errorf("id mismatch: %q", got.GetId())
	}
	if got.GetMarket() != altv1.Market_MARKET_US {
		t.Errorf("market mismatch: %v", got.GetMarket())
	}
	if got.GetVenue() != altv1.Venue_VENUE_NASDAQ {
		t.Errorf("venue mismatch: %v", got.GetVenue())
	}
	if got.GetCurrency() != altv1.Currency_CURRENCY_USD {
		t.Errorf("currency mismatch: %v", got.GetCurrency())
	}
	if got.GetAssetType() != altv1.AssetType_ASSET_TYPE_ETF {
		t.Errorf("asset type mismatch: %v", got.GetAssetType())
	}
	if got.GetProviderSymbols()["kis"] != "AAPL" {
		t.Errorf("provider symbols mismatch: %+v", got.GetProviderSymbols())
	}
}
