package backtest

import (
	"context"
	"fmt"

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

// BuiltInStrategyID is the identifier of the worker's default bundled strategy.
// Command workflows and YAML scenarios reference it so a backtest can run
// end-to-end on imported bars without an operator authoring a custom strategy.
const BuiltInStrategyID backtest.StrategyID = "strategy-v1"

// BuiltInStrategyPort resolves the worker's bundled strategies. It is the
// production StrategyPort wired in cmd/alt-worker. Unknown ids return an error
// so a misconfigured run fails fast instead of silently producing an empty
// result.
type BuiltInStrategyPort struct{}

func NewBuiltInStrategyPort() *BuiltInStrategyPort {
	return &BuiltInStrategyPort{}
}

func (p *BuiltInStrategyPort) GetStrategy(ctx context.Context, id backtest.StrategyID) (backtest.Strategy, error) {
	switch id {
	case BuiltInStrategyID:
		return buyAndHoldStrategy{id: id}, nil
	default:
		return nil, fmt.Errorf("unknown strategy %q", id)
	}
}

// buyAndHoldStrategy buys a single unit of each instrument the first time it is
// seen and then holds. It is intentionally minimal and deterministic so command
// validation can assert a stable terminal result from imported daily bars.
type buyAndHoldStrategy struct {
	id backtest.StrategyID
}

func (s buyAndHoldStrategy) ID() backtest.StrategyID { return s.id }

func (s buyAndHoldStrategy) Decide(input backtest.StrategyInput) ([]backtest.OrderIntent, error) {
	// Hold once a position exists. The engine passes the pre-trade portfolio for
	// the current bar, so an existing position means this instrument was already
	// bought on an earlier bar.
	if _, held := input.Portfolio.Position(input.Bar.InstrumentID); held {
		return nil, nil
	}
	return []backtest.OrderIntent{
		{
			InstrumentID: input.Bar.InstrumentID,
			Side:         backtest.OrderSideBuy,
			Quantity:     market.Quantity{Amount: market.Decimal{Value: "1"}},
		},
	}, nil
}
