using Dapper;
using Npgsql;
using Shared.Operations;

namespace Kbx.Shared.Integrations;

public sealed class KbxIntegrationRetryActionHandler(NpgsqlDataSource dataSource) : IWorkItemActionHandler
{
    public string Key => "integration.retry";

    public async Task ExecuteAsync(string tenantId, string actorId, Guid workItemId, CancellationToken ct)
    {
        await using var connection = await dataSource.OpenConnectionAsync(ct);
        await using var tx = await connection.BeginTransactionAsync(ct);
        var messageId = await connection.QuerySingleOrDefaultAsync<Guid?>(new CommandDefinition("""
            select source_id::uuid
              from kbx.work_items
             where id=@WorkItemId and tenant_id=@TenantId and retry_action_key='integration.retry'
             for update;
        """, new { WorkItemId = workItemId, TenantId = tenantId }, tx, cancellationToken: ct));
        if (messageId is null) { await tx.RollbackAsync(ct); return; }

        var changed = await connection.ExecuteAsync(new CommandDefinition("""
            update kbx.integration_attempts
               set state='retrying', next_retry_at=now()
             where id = (
                 select id from kbx.integration_attempts
                  where message_id=@MessageId and state='failed'
                  order by attempt_no desc limit 1
             );
        """, new { MessageId = messageId.Value }, tx, cancellationToken: ct));

        if (changed == 1)
        {
            await connection.ExecuteAsync(new CommandDefinition("""
                insert into kbx.work_item_audit(id,work_item_id,tenant_id,action,actor_id,actor_name,reason,before_status,after_status)
                values(gen_random_uuid(),@WorkItemId,@TenantId,'integration-retry',@ActorId,@ActorId,'안전한 연계 재처리 예약','open','open');
            """, new { WorkItemId = workItemId, TenantId = tenantId, ActorId = actorId }, tx, cancellationToken: ct));
        }
        await tx.CommitAsync(ct);
    }
}
