namespace TaxBaik.Infrastructure.Repositories;

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

public class TaxFilingScheduleRepository(IDbConnectionFactory connectionFactory) : BaseRepository(connectionFactory), ITaxFilingScheduleRepository
{
    public async Task<int> CreateAsync(TaxFilingSchedule schedule, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryFirstAsync<int>(
            @"INSERT INTO tax_filing_schedules (client_id, filing_type, due_date, filing_year, status, assigned_to, notes, created_at, updated_at)
              VALUES (@ClientId, @FilingType, @DueDate, @FilingYear, @Status, @AssignedToId, @Notes, NOW(), NOW())
              RETURNING id",
            schedule);
    }

    public async Task<IEnumerable<TaxFilingSchedule>> GetAllAsync(CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<TaxFilingSchedule>(
            @"SELECT id, client_id, filing_type, due_date, filing_year, status, assigned_to, completed_date, notes, created_at, updated_at
              FROM tax_filing_schedules ORDER BY due_date DESC");
    }

    public async Task<TaxFilingSchedule?> GetByIdAsync(int id, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryFirstOrDefaultAsync<TaxFilingSchedule>(
            @"SELECT id, client_id, filing_type, due_date, filing_year, status, assigned_to, completed_date, notes, created_at, updated_at
              FROM tax_filing_schedules WHERE id = @Id",
            new { Id = id });
    }

    public async Task<IEnumerable<TaxFilingSchedule>> GetByClientIdAsync(int clientId, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<TaxFilingSchedule>(
            @"SELECT id, client_id, filing_type, due_date, filing_year, status, assigned_to, completed_date, notes, created_at, updated_at
              FROM tax_filing_schedules WHERE client_id = @ClientId ORDER BY due_date DESC",
            new { ClientId = clientId });
    }

    public async Task<IEnumerable<TaxFilingSchedule>> GetUpcomingDuesAsync(int daysAhead = 30, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<TaxFilingSchedule>(
            @"SELECT id, client_id, filing_type, due_date, filing_year, status, assigned_to, completed_date, notes, created_at, updated_at
              FROM tax_filing_schedules
              WHERE status = 'pending' AND due_date BETWEEN CURRENT_DATE AND CURRENT_DATE + INTERVAL '1 day' * @DaysAhead
              ORDER BY due_date ASC",
            new { DaysAhead = daysAhead });
    }

    public async Task<IEnumerable<TaxFilingSchedule>> GetByStatusAsync(string status, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<TaxFilingSchedule>(
            @"SELECT id, client_id, filing_type, due_date, filing_year, status, assigned_to, completed_date, notes, created_at, updated_at
              FROM tax_filing_schedules WHERE status = @Status ORDER BY due_date",
            new { Status = status });
    }

    public async Task UpdateAsync(TaxFilingSchedule schedule, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        await conn.ExecuteAsync(
            @"UPDATE tax_filing_schedules SET filing_type = @FilingType, due_date = @DueDate, status = @Status,
              assigned_to = @AssignedToId, notes = @Notes, updated_at = NOW() WHERE id = @Id",
            schedule);
    }

    public async Task MarkCompletedAsync(int id, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        await conn.ExecuteAsync(
            @"UPDATE tax_filing_schedules SET status = 'completed', completed_date = NOW(), updated_at = NOW() WHERE id = @Id",
            new { Id = id });
    }
}
