using Dapper;
using KArtSell.BuildingBlocks.Data;
using KArtSell.Modules.SignalEngine.Application;

namespace KArtSell.Modules.SignalEngine.Infrastructure;

public sealed class DapperSellDecisionContextReader(IDbConnectionFactory connectionFactory)
    : ISellDecisionContextReader
{
    private const string Sql = """
        select
            context_id as ContextId,
            position_lot_id as PositionLotId,
            cycle_id as CycleId,
            evidence_id as EvidenceId,
            dataset_id as DatasetId,
            model_version as ModelVersion,
            config_version as ConfigVersion,
            code_sha as CodeSha,
            as_of as AsOf,
            published_at_cutoff as PublishedAtCutoff,
            current_security_portfolio_weight as CurrentSecurityPortfolioWeight,
            current_lot_portfolio_weight as CurrentLotPortfolioWeight,
            strategic_core_floor_weight as StrategicCoreFloorWeight,
            hard_impairment_approved as HardImpairmentApproved,
            capital_floor_breached as CapitalFloorBreached,
            survival_sell_ratio_of_lot as SurvivalSellRatioOfLot,
            gap_below_floor_atr as GapBelowFloorAtr,
            consecutive_close_breaches as ConsecutiveCloseBreaches,
            cooldown_satisfied as CooldownSatisfied,
            concentration_sell_ratio_of_lot as ConcentrationSellRatioOfLot,
            opportunity_edge_lower_bound as OpportunityEdgeLowerBound,
            opportunity_sell_ratio_of_lot as OpportunitySellRatioOfLot,
            quality_status as QualityStatus,
            content_hash as ContentHash
        from signal_engine.sell_decision_context
        where position_lot_id = @PositionLotId
          and as_of <= @AsOf
          and published_at_cutoff <= @AsOf
          and quality_status = 'PASS'
          and weight_semantics_version = 2
        order by as_of desc, context_id desc
        limit 1;
        """;

    public async Task<SellDecisionContext?> GetApprovedAsync(
        Guid positionLotId,
        DateTimeOffset asOf,
        CancellationToken cancellationToken)
    {
        await using var connection = await connectionFactory.OpenAsync(cancellationToken);
        return await connection.QuerySingleOrDefaultAsync<SellDecisionContext>(
            new CommandDefinition(
                Sql,
                new { PositionLotId = positionLotId, AsOf = asOf },
                cancellationToken: cancellationToken));
    }
}
