// Package datacheck provides a credential-free smoke surface for the Korea
// daily data foundation: it feeds an embedded KIS daily-chart fixture through
// the real decode/normalize and import pipeline into an in-memory store, then
// queries the stored bars back and prints a stable one-line summary. It proves
// normalized daily bars are queryable in the shape the backtest milestone will
// consume, without any live KIS credential, secret store, or PostgreSQL.
package datacheck

import (
	"context"
	_ "embed"
	"fmt"
	"io"
	"sort"
	"time"

	"git.toki-labs.com/toki/alt/packages/domain/market"
	"git.toki-labs.com/toki/alt/services/worker/internal/marketdata/importer"
	"git.toki-labs.com/toki/alt/services/worker/internal/providers/kis"
)

// dailyChartResponseFixture is a self-contained copy of the KIS daily chart
// response fixture. It is embedded here (rather than read from the module's
// testdata tree) so the smoke command builds and runs as a normal binary: Go
// build tooling ignores testdata, and go:embed cannot reach across module
// directories with "..".
//
//go:embed fixtures/daily_itemchartprice_response.sample.json
var dailyChartResponseFixture []byte

// fixtureProvider implements importer.DailyBarProvider by normalizing the
// embedded KIS fixture. It exercises the real kis decode/normalize path instead
// of fabricating domain bars, so the smoke covers provider normalization too.
type fixtureProvider struct{}

func (fixtureProvider) FetchDailyBars(_ context.Context, _ importer.DailyBarRequest) ([]importer.InstrumentBars, error) {
	resp, err := kis.DecodeDailyItemChartPriceResponse(dailyChartResponseFixture)
	if err != nil {
		return nil, fmt.Errorf("datacheck: decode fixture: %w", err)
	}
	inst := market.Instrument{
		ID:              market.InstrumentID("KRX:" + resp.Output1.ShortCode),
		Market:          market.MarketKR,
		Venue:           market.VenueKRX,
		Symbol:          resp.Output1.ShortCode,
		Name:            resp.Output1.Name,
		Currency:        market.CurrencyKRW,
		ProviderSymbols: map[string]string{string(market.ProviderKIS): resp.Output1.ShortCode},
	}
	bars, err := kis.NormalizeDailyBars(resp, inst)
	if err != nil {
		return nil, fmt.Errorf("datacheck: normalize bars: %w", err)
	}
	return []importer.InstrumentBars{{Instrument: inst, Bars: bars}}, nil
}

// request mirrors the watchlist daily bar request a real import job would carry.
func request() importer.DailyBarRequest {
	return importer.DailyBarRequest{
		Provider: market.ProviderKIS,
		Selector: market.UniverseSelector{
			Kind:    market.UniverseSelectorWatchlist,
			Venue:   market.VenueKRX,
			Symbols: []string{"005930"},
		},
	}
}

// Run executes the mock data check and writes a stable summary line to w. The
// summary reports the instrument count, total daily bar count, and the first
// and last bar dates (YYYY-MM-DD) queried back from the store.
func Run(ctx context.Context, w io.Writer) error {
	store := newMemStore()
	imp := importer.New(fixtureProvider{}, store)

	if _, err := imp.ImportDailyBars(ctx, request()); err != nil {
		return fmt.Errorf("datacheck: import: %w", err)
	}

	instruments, err := store.ListInstruments(ctx)
	if err != nil {
		return fmt.Errorf("datacheck: list instruments: %w", err)
	}

	// Query daily bars back over an unbounded range so the summary reflects what
	// a backtest consumer would read, not just what the importer reported.
	var bars []market.Bar
	for _, inst := range instruments {
		got, err := store.GetBars(ctx, inst.ID, market.TimeframeDaily, time.Time{}, time.Unix(1<<62, 0))
		if err != nil {
			return fmt.Errorf("datacheck: get bars for %q: %w", inst.ID, err)
		}
		bars = append(bars, got...)
	}
	sort.Slice(bars, func(i, j int) bool { return bars[i].Timestamp.Before(bars[j].Timestamp) })

	first, last := "none", "none"
	if len(bars) > 0 {
		first = bars[0].Timestamp.Format("2006-01-02")
		last = bars[len(bars)-1].Timestamp.Format("2006-01-02")
	}

	if _, err := fmt.Fprintf(w, "instrument_count=%d bar_count=%d first=%s last=%s\n",
		len(instruments), len(bars), first, last); err != nil {
		return fmt.Errorf("datacheck: write summary: %w", err)
	}
	return nil
}
