using Dapper;
using Femto.Common.Domain;
using Femto.Common.Infrastructure.DbConnection;
using Femto.Modules.Auth.Application.Dto;

namespace Femto.Modules.Auth.Application.Interface.GetSignupCodesQuery;

public class GetSignupCodesQueryHandler(IDbConnectionFactory connectionFactory)
    : IQueryHandler<GetSignupCodesQuery, ICollection<SignupCodeDto>>
{
    public async Task<ICollection<SignupCodeDto>> Handle(
        GetSignupCodesQuery request,
        CancellationToken cancellationToken
    )
    {
        using var conn = connectionFactory.GetConnection();

        // lang=sql
        const string sql = """
            SELECT 
                sc.code as Code,
                sc.recipient_email as Email,
                sc.recipient_name as Name,
                sc.redeeming_user_id as RedeemedByUserId,
                u.username as RedeemedByUsername,
                sc.expires_at as ExpiresOn
            FROM authn.signup_code sc
            LEFT JOIN authn.user_identity u ON u.id = sc.redeeming_user_id
            ORDER BY sc.created_at DESC
            """;

        var result = await conn.QueryAsync<QueryResultRow>(sql);

        return result
            .Select(row => new SignupCodeDto(
                row.Code,
                row.Email,
                row.Name,
                row.RedeemedByUserId,
                row.RedeemedByUsername,
                row.ExpiresOn
            ))
            .ToList();
    }

    private class QueryResultRow
    {
        public string Code { get; set; }
        public string Email { get; set; }
        public string Name { get; set; }
        public Guid? RedeemedByUserId { get; set; }
        public string? RedeemedByUsername { get; set; }
        public DateTimeOffset? ExpiresOn { get; set; }
    }
}
