using Dapper;
using KArtSell.BuildingBlocks.Data;
using KArtSell.BuildingBlocks.Versioning;
using KArtSell.Modules.ModelOperations.Application;

namespace KArtSell.Modules.ModelOperations.Infrastructure;

public sealed class DapperApprovedModelContextReader(IDbConnectionFactory connectionFactory) : IApprovedModelContextReader
{
    private const string Sql = """
        select mv.scope_key as ScopeKey,
               mv.model_version as ModelVersion,
               mv.config_version as ConfigVersion,
               mv.code_sha as CodeSha,
               mv.contract_version as ContractVersion,
               mv.lifecycle_state as LifecycleState,
               mv.effective_at as EffectiveAt,
               dm.dataset_id as DatasetId,
               dm.content_hash as DataHash
        from governance.model_version_registry mv
        join lateral (
            select dataset_id, content_hash
            from evaluation.dataset_manifest
            where scope_key = mv.scope_key
              and status = 'APPROVED'
              and frozen_at <= @AsOf
            order by frozen_at desc
            limit 1
        ) dm on true
        where mv.scope_key = @ScopeKey
          and mv.lifecycle_state in ('RESEARCH', 'CHALLENGER', 'SHADOW', 'CANDIDATE', 'APPROVED')
          and mv.effective_at <= @AsOf
        order by mv.effective_at desc
        limit 1;
        """;

    public async Task<ApprovedModelContext?> ReadAsync(
        string scopeKey,
        DateTimeOffset asOf,
        CancellationToken cancellationToken)
    {
        await using var connection = await connectionFactory.OpenAsync(cancellationToken);
        var row = await connection.QuerySingleOrDefaultAsync<Row>(new CommandDefinition(
            Sql,
            new { ScopeKey = scopeKey, AsOf = asOf },
            cancellationToken: cancellationToken));

        if (row is null)
            return null;

        return new ApprovedModelContext(
            row.ScopeKey,
            new VersionSet(row.DatasetId, row.DataHash, row.ModelVersion, row.ConfigVersion, row.CodeSha, row.ContractVersion),
            row.LifecycleState,
            row.EffectiveAt);
    }

    private sealed record Row(
        string ScopeKey,
        string DatasetId,
        string DataHash,
        string ModelVersion,
        string ConfigVersion,
        string CodeSha,
        string ContractVersion,
        string LifecycleState,
        DateTimeOffset EffectiveAt);
}
