package datacheck

import (
	"context"
	"time"

	"git.toki-labs.com/toki/alt/packages/domain/market"
)

// barKey mirrors the bars primary key (instrument_id, timeframe, timestamp) so
// the in-memory store replaces rows the same way the PostgreSQL UpsertBar does,
// keeping the smoke's idempotency behavior aligned with real storage.
type barKey struct {
	instrumentID market.InstrumentID
	timeframe    market.Timeframe
	timestamp    time.Time
}

// memStore is an in-memory InstrumentStore + BarStore for the smoke command. It
// satisfies importer.Stores without any external dependency so the data check
// runs with no PostgreSQL or credential.
type memStore struct {
	instruments map[market.InstrumentID]market.Instrument
	bars        map[barKey]market.Bar
}

func newMemStore() *memStore {
	return &memStore{
		instruments: make(map[market.InstrumentID]market.Instrument),
		bars:        make(map[barKey]market.Bar),
	}
}

func (s *memStore) UpsertInstrument(_ context.Context, inst market.Instrument) error {
	s.instruments[inst.ID] = inst
	return nil
}

func (s *memStore) GetInstrument(_ context.Context, id market.InstrumentID) (market.Instrument, error) {
	return s.instruments[id], nil
}

func (s *memStore) ListInstruments(_ context.Context) ([]market.Instrument, error) {
	out := make([]market.Instrument, 0, len(s.instruments))
	for _, inst := range s.instruments {
		out = append(out, inst)
	}
	return out, nil
}

func (s *memStore) UpsertBar(_ context.Context, bar market.Bar) error {
	s.bars[barKey{bar.InstrumentID, bar.Timeframe, bar.Timestamp}] = bar
	return nil
}

func (s *memStore) GetBars(_ context.Context, id market.InstrumentID, timeframe market.Timeframe, from, to time.Time) ([]market.Bar, error) {
	out := make([]market.Bar, 0)
	for k, bar := range s.bars {
		if k.instrumentID != id || k.timeframe != timeframe {
			continue
		}
		if k.timestamp.Before(from) || k.timestamp.After(to) {
			continue
		}
		out = append(out, bar)
	}
	return out, nil
}
