using Dapper;
using FastEndpoints;
using KBX.Shared.Experience;
using Npgsql;
using System.Diagnostics;

namespace KBX.Modules.Common.Ai.Ask;

public sealed record Request(string Question, AiScreenContext Context);

public sealed class Endpoint(IKbxAiAssistantProvider assistant, NpgsqlDataSource dataSource) : Endpoint<Request, AiAnswer>
{
    public override void Configure()
    {
        Post("/api/common/ai/ask");
        Permissions("common.ai.use");
    }

    public override async Task HandleAsync(Request req, CancellationToken ct)
    {
        if (string.IsNullOrWhiteSpace(req.Question) || req.Question.Length > 2000)
        {
            AddError(r => r.Question, "질문을 1~2000자로 입력하세요.");
            await Send.ErrorsAsync(cancellation: ct);
            return;
        }

        // Host application replaces this with authenticated claims resolution.
        var tenantId = Guid.Empty;
        var userId = Guid.Empty;
        var sw = Stopwatch.StartNew();
        var answer = await assistant.AskAsync(tenantId, userId, new AiAskCommand(req.Question.Trim(), req.Context), ct);
        sw.Stop();

        await using var connection = await dataSource.OpenConnectionAsync(ct);
        await connection.ExecuteAsync(new CommandDefinition("""
            insert into kbx.ai_interactions
                (id, tenant_id, user_id, screen_id, screen_version, capability, result_kind, provider, duration_ms)
            values
                (@Id, @TenantId, @UserId, @ScreenId, @ScreenVersion, 'explain', @ResultKind, @Provider, @DurationMs)
            """, new
        {
            Id = Guid.NewGuid(),
            TenantId = tenantId,
            UserId = userId,
            req.Context.ScreenId,
            req.Context.ScreenVersion,
            ResultKind = answer.Proposal is null ? "answer" : "proposal",
            Provider = assistant.GetType().Name,
            DurationMs = (int)sw.ElapsedMilliseconds,
        }, cancellationToken: ct));

        await Send.OkAsync(answer, ct);
    }
}
