using FastEndpoints;
using TaxBaik.Application.Services;

namespace TaxBaik.Web.Endpoints.TaxFilingSchedule;

public class CreateRequest
{
    public int ClientId { get; set; }
    public string? FilingType { get; set; }
    public DateTime DueDate { get; set; }
    public int FilingYear { get; set; }
    public int? AssignedToId { get; set; }
}

public class IdResponse { public int Id { get; set; } }
public class MessageResponse { public string Message { get; set; } = string.Empty; }
public class ListResponse { public List<object> Data { get; set; } = []; }
public class CountResponse { public int Count { get; set; } }
public class DaysQuery { public int DaysAhead { get; set; } = 30; }

public class CreateEndpoint : Endpoint<CreateRequest, IdResponse>
{
    private readonly TaxFilingScheduleService _svc;
    public CreateEndpoint(TaxFilingScheduleService svc) => _svc = svc;

    public override void Configure()
    {
        Post("/api/taxfilingschedule");
        Policies("Bearer");
    }

    public override async Task HandleAsync(CreateRequest req, CancellationToken ct)
    {
        if (string.IsNullOrWhiteSpace(req.FilingType))
            ThrowError("신고 유형이 필요합니다.", statusCode: 400);
        var id = await _svc.CreateAsync(req.ClientId, req.FilingType, req.DueDate, req.FilingYear, req.AssignedToId);
        await SendAsync(new IdResponse { Id = id }, 201, cancellation: ct);
    }
}

public class GetByIdEndpoint : Endpoint<EmptyRequest, object>
{
    private readonly TaxFilingScheduleService _svc;
    public GetByIdEndpoint(TaxFilingScheduleService svc) => _svc = svc;

    public override void Configure()
    {
        Get("/api/taxfilingschedule/{id}");
        Policies("Bearer");
    }

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var id = Route<int>("id");
        var schedule = await _svc.GetByIdAsync(id);
        if (schedule == null) ThrowError("일정을 찾을 수 없습니다.", statusCode: 404);
        await SendAsync(schedule, 200, cancellation: ct);
    }
}

public class GetAllEndpoint : Endpoint<EmptyRequest, ListResponse>
{
    private readonly TaxFilingScheduleService _svc;
    public GetAllEndpoint(TaxFilingScheduleService svc) => _svc = svc;

    public override void Configure()
    {
        Get("/api/taxfilingschedule");
        Policies("Bearer");
    }

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var schedules = await _svc.GetAllAsync();
        await SendAsync(new ListResponse { Data = schedules.Cast<object>().ToList() }, 200, cancellation: ct);
    }
}

public class GetByClientIdEndpoint : Endpoint<EmptyRequest, ListResponse>
{
    private readonly TaxFilingScheduleService _svc;
    public GetByClientIdEndpoint(TaxFilingScheduleService svc) => _svc = svc;

    public override void Configure()
    {
        Get("/api/taxfilingschedule/client/{clientId}");
        Policies("Bearer");
    }

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var clientId = Route<int>("clientId");
        var schedules = await _svc.GetByClientIdAsync(clientId);
        await SendAsync(new ListResponse { Data = schedules.Cast<object>().ToList() }, 200, cancellation: ct);
    }
}

public class GetUpcomingEndpoint : Endpoint<DaysQuery, object>
{
    private readonly TaxFilingScheduleService _svc;
    public GetUpcomingEndpoint(TaxFilingScheduleService svc) => _svc = svc;

    public override void Configure()
    {
        Get("/api/taxfilingschedule/upcoming");
        Policies("Bearer");
    }

    public override async Task HandleAsync(DaysQuery req, CancellationToken ct)
    {
        var schedules = await _svc.GetUpcomingDuesAsync(req.DaysAhead);
        await SendAsync(new { data = schedules, daysAhead = req.DaysAhead }, 200, cancellation: ct);
    }
}

public class MarkCompletedEndpoint : Endpoint<EmptyRequest, MessageResponse>
{
    private readonly TaxFilingScheduleService _svc;
    public MarkCompletedEndpoint(TaxFilingScheduleService svc) => _svc = svc;

    public override void Configure()
    {
        Post("/api/taxfilingschedule/{id}/completed");
        Policies("Bearer");
    }

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var id = Route<int>("id");
        await _svc.MarkCompletedAsync(id);
        await SendAsync(new MessageResponse { Message = "완료 처리되었습니다." }, 200, cancellation: ct);
    }
}

public class GetPendingCountEndpoint : Endpoint<EmptyRequest, CountResponse>
{
    private readonly TaxFilingScheduleService _svc;
    public GetPendingCountEndpoint(TaxFilingScheduleService svc) => _svc = svc;

    public override void Configure()
    {
        Get("/api/taxfilingschedule/pending/count");
        Policies("Bearer");
    }

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var count = await _svc.GetPendingCountAsync();
        await SendAsync(new CountResponse { Count = count }, 200, cancellation: ct);
    }
}
