namespace TaxBaik.Infrastructure.Repositories;

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

public class ConsultingActivityRepository(IDbConnectionFactory connectionFactory) : BaseRepository(connectionFactory), IConsultingActivityRepository
{
    public async Task<int> CreateAsync(ConsultingActivity activity, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryFirstAsync<int>(
            @"INSERT INTO consulting_activities (client_id, activity_type, activity_date, activity_time, assigned_consultant, description, outcome, next_followup_date, notes, created_at, updated_at)
              VALUES (@ClientId, @ActivityType, @ActivityDate, @ActivityTime, @AssignedConsultantId, @Description, @Outcome, @NextFollowupDate, @Notes, NOW(), NOW())
              RETURNING id",
            activity);
    }

    public async Task<IEnumerable<ConsultingActivity>> GetAllAsync(CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<ConsultingActivity>(
            @"SELECT id, client_id, activity_type, activity_date, activity_time, assigned_consultant, description, outcome, next_followup_date, notes, created_at, updated_at
              FROM consulting_activities ORDER BY activity_date DESC");
    }

    public async Task<IEnumerable<ConsultingActivity>> GetByClientIdAsync(int clientId, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<ConsultingActivity>(
            @"SELECT id, client_id, activity_type, activity_date, activity_time, assigned_consultant, description, outcome, next_followup_date, notes, created_at, updated_at
              FROM consulting_activities WHERE client_id = @ClientId ORDER BY activity_date DESC",
            new { ClientId = clientId });
    }

    public async Task<IEnumerable<ConsultingActivity>> GetPendingFollowupsAsync(CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<ConsultingActivity>(
            @"SELECT id, client_id, activity_type, activity_date, activity_time, assigned_consultant, description, outcome, next_followup_date, notes, created_at, updated_at
              FROM consulting_activities WHERE next_followup_date IS NOT NULL AND next_followup_date <= CURRENT_DATE
              ORDER BY next_followup_date ASC");
    }

    public async Task<IEnumerable<ConsultingActivity>> GetByConsultantAsync(int consultantId, DateTime fromDate, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        return await conn.QueryAsync<ConsultingActivity>(
            @"SELECT id, client_id, activity_type, activity_date, activity_time, assigned_consultant, description, outcome, next_followup_date, notes, created_at, updated_at
              FROM consulting_activities WHERE assigned_consultant = @ConsultantId AND activity_date >= @FromDate
              ORDER BY activity_date DESC",
            new { ConsultantId = consultantId, FromDate = fromDate });
    }

    public async Task UpdateAsync(ConsultingActivity activity, CancellationToken cancellationToken = default)
    {
        using var conn = Conn();
        await conn.ExecuteAsync(
            @"UPDATE consulting_activities SET activity_type = @ActivityType, activity_date = @ActivityDate,
              activity_time = @ActivityTime, assigned_consultant = @AssignedConsultantId, description = @Description,
              outcome = @Outcome, next_followup_date = @NextFollowupDate, notes = @Notes, updated_at = NOW()
              WHERE id = @Id",
            activity);
    }
}
