namespace KArtSell.Modules.ModelOperations.SellDecision;

using FastEndpoints;
using System.Data;
using KArtSell.BuildingBlocks.Time;
using Npgsql;

public class CreateSellDecisionEndpoint : Endpoint<CreateSellDecisionRequest, CreateSellDecisionResponse>
{
    private readonly IGenerateSellDecisionHandler _handler;

    public CreateSellDecisionEndpoint(IGenerateSellDecisionHandler handler)
    {
        _handler = handler;
    }

    public override void Configure()
    {
        Post("/sell-decisions");
        Roles("Maker");
    }

    public override async Task HandleAsync(CreateSellDecisionRequest req, CancellationToken ct)
    {
        var userId = HttpContext.User?.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value ?? "anonymous";
        var correlationId = Guid.NewGuid();

        var response = await _handler.HandleAsync(req, correlationId, userId, ct);

        await Send.ResponseAsync(response, 202, ct);
    }
}

public class ListSellDecisionsEndpoint : EndpointWithoutRequest<ListSellDecisionsResponse>
{
    private readonly ISellDecisionSql _sql;

    public ListSellDecisionsEndpoint(ISellDecisionSql sql)
    {
        _sql = sql;
    }

    public override void Configure()
    {
        Get("/sell-decisions");
        Roles("Quant", "Maker", "Checker");
    }

    public override async Task HandleAsync(CancellationToken ct)
    {
        var status = Query<string>("status");
        var modelId = Query<Guid?>("modelId");
        var limit = Query<int?>("limit") ?? 50;
        var offset = Query<int?>("offset") ?? 0;

        using var conn = new NpgsqlConnection(Environment.GetEnvironmentVariable("KARTSELL_POSTGRES"));
        await conn.OpenAsync(ct);

        List<SellDecisionEntity> decisions = new();

        if (!string.IsNullOrEmpty(status))
        {
            decisions = await _sql.GetDecisionsByStatusAsync(status, limit, offset, conn);
        }
        else if (modelId.HasValue)
        {
            decisions = await _sql.GetDecisionsByModelIdAsync(modelId.Value, limit, offset, conn);
        }

        var dtos = decisions.Select(d => new SellDecisionDto
        {
            DecisionId = d.Id,
            ModelId = d.ModelId,
            Status = d.Status,
            PboScore = d.PboScore,
            DsrMetric = d.DsrMetric,
            SellPriority = d.SellPriority,
            TargetQuantity = d.TargetQuantity,
            TargetPrice = d.TargetPrice,
            ApprovalId = d.ApprovalId,
            ExecutionId = d.ExecutionId,
            CreatedAt = d.CreatedAt,
            CorrelationId = d.CorrelationId
        }).ToList();

        var response = new ListSellDecisionsResponse
        {
            Decisions = dtos,
            Total = dtos.Count,
            Limit = limit,
            Offset = offset
        };

        await Send.ResponseAsync(response, 200, ct);
    }
}

public class ExecuteSellDecisionEndpoint : Endpoint<ExecuteSellDecisionRequest, ExecuteSellDecisionResponse>
{
    private readonly ISellDecisionSql _sql;
    private readonly IClock _clock;

    public ExecuteSellDecisionEndpoint(ISellDecisionSql sql, IClock clock)
    {
        _sql = sql;
        _clock = clock;
    }

    public override void Configure()
    {
        Post("/sell-decisions/{id}/execute");
        Roles("Maker", "Checker");
    }

    public override async Task HandleAsync(ExecuteSellDecisionRequest req, CancellationToken ct)
    {
        var decisionId = Route<Guid>("id");

        using var conn = new NpgsqlConnection(Environment.GetEnvironmentVariable("KARTSELL_POSTGRES"));
        await conn.OpenAsync(ct);

        // Stub: Fetch decision, verify status, update to EXECUTED
        var executionId = Guid.NewGuid();
        var now = _clock.UtcNow;
        var kisOrderId = now.ToString("yyyyMMddHHmm") + "001";

        var response = new ExecuteSellDecisionResponse
        {
            DecisionId = decisionId,
            ExecutionId = executionId,
            Status = SellDecisionStatus.Executed.ToString(),
            KisOrderId = kisOrderId,
            SubmittedAt = now.UtcDateTime,
            CorrelationId = Guid.NewGuid()
        };

        await Send.ResponseAsync(response, 202, ct);
    }
}
