namespace TaxBaik.Infrastructure.Repositories;

using Dapper;
using TaxBaik.Domain.Entities;
using TaxBaik.Domain.Interfaces;

public class TaxFilingRepository(IDbConnectionFactory connectionFactory) : BaseRepository(connectionFactory), ITaxFilingRepository
{
    private const string SelectColumns = @"
        tf.id, tf.client_id, c.name AS client_name, tf.filing_type, tf.due_date,
        tf.status, tf.memo, tf.created_at, tf.updated_at";

    public async Task<IEnumerable<TaxFiling>> GetByClientIdAsync(int clientId, CancellationToken ct = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<TaxFiling>(
            $@"SELECT {SelectColumns}
               FROM tax_filings tf
               JOIN clients c ON c.id = tf.client_id
               WHERE tf.client_id = @ClientId
               ORDER BY tf.due_date ASC",
            new { ClientId = clientId });
    }

    public async Task<IEnumerable<TaxFiling>> GetUpcomingAsync(int daysAhead, CancellationToken ct = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<TaxFiling>(
            $@"SELECT {SelectColumns}
               FROM tax_filings tf
               JOIN clients c ON c.id = tf.client_id
               WHERE tf.status = 'pending'
                 AND tf.due_date <= CURRENT_DATE + @DaysAhead::int
                 AND tf.due_date >= CURRENT_DATE
               ORDER BY tf.due_date ASC",
            new { DaysAhead = daysAhead });
    }

    public async Task<TaxFiling?> GetByIdAsync(int id, CancellationToken ct = default)
    {
        using var conn = Conn();
        return await conn.QueryFirstOrDefaultAsync<TaxFiling>(
            $@"SELECT {SelectColumns}
               FROM tax_filings tf
               JOIN clients c ON c.id = tf.client_id
               WHERE tf.id = @Id",
            new { Id = id });
    }

    public async Task<int> CreateAsync(TaxFiling filing, CancellationToken ct = default)
    {
        using var conn = Conn();
        return await conn.QueryFirstAsync<int>(
            @"INSERT INTO tax_filings (client_id, filing_type, due_date, status, memo, created_at, updated_at)
              VALUES (@ClientId, @FilingType, @DueDate, @Status, @Memo, NOW(), NOW())
              RETURNING id",
            filing);
    }

    public async Task UpdateAsync(TaxFiling filing, CancellationToken ct = default)
    {
        using var conn = Conn();
        await conn.ExecuteAsync(
            @"UPDATE tax_filings
              SET filing_type = @FilingType, due_date = @DueDate, status = @Status,
                  memo = @Memo, updated_at = NOW()
              WHERE id = @Id",
            filing);
    }

    public async Task DeleteAsync(int id, CancellationToken ct = default)
    {
        using var conn = Conn();
        await conn.ExecuteAsync("DELETE FROM tax_filings WHERE id = @Id", new { Id = id });
    }
}
