using FastEndpoints;
using TaxBaik.Application.Services;

namespace TaxBaik.Web.Endpoints.TaxProfile;

// DTOs
public class CreateTaxProfileRequest
{
    public int ClientId { get; set; }
    public string? BusinessType { get; set; }
    public string? BusinessRegistration { get; set; }
    public string? AccountingMethod { get; set; }
    public DateTime? EstablishmentDate { get; set; }
}

public class UpdateTaxProfileRequest
{
    public string? BusinessType { get; set; }
    public string? AccountingMethod { get; set; }
    public DateTime? NextFilingDueDate { get; set; }
    public string? TaxRiskLevel { get; set; }
}

public class TaxProfileListResponse
{
    public List<object> Data { get; set; } = [];
}

public class TaxProfileCreateResponse
{
    public int Id { get; set; }
}

public class TaxProfileUpdateResponse
{
    public string Message { get; set; } = string.Empty;
}

public class DaysAheadQuery
{
    public int DaysAhead { get; set; } = 30;
}

// Endpoints
public class CreateEndpoint : Endpoint<CreateTaxProfileRequest, TaxProfileCreateResponse>
{
    private readonly TaxProfileService _service;
    public CreateEndpoint(TaxProfileService service) => _service = service;

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

    public override async Task HandleAsync(CreateTaxProfileRequest request, CancellationToken ct)
    {
        try
        {
            var id = await _service.CreateAsync(request.ClientId, request.BusinessType,
                request.BusinessRegistration, request.AccountingMethod, request.EstablishmentDate);
            await SendAsync(new TaxProfileCreateResponse { Id = id }, 201, cancellation: ct);
        }
        catch (ValidationException ex)
        {
            ThrowError(ex.Message);
        }
    }
}

public class GetAllEndpoint : Endpoint<EmptyRequest, TaxProfileListResponse>
{
    private readonly TaxProfileService _service;
    public GetAllEndpoint(TaxProfileService service) => _service = service;

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

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        try
        {
            var profiles = await _service.GetAllAsync();
            await SendAsync(new TaxProfileListResponse { Data = profiles.Cast<object>().ToList() }, 200, cancellation: ct);
        }
        catch
        {
            ThrowError("세무 프로필 조회 실패", statusCode: 500);
        }
    }
}

public class GetByClientIdEndpoint : Endpoint<EmptyRequest, object>
{
    private readonly TaxProfileService _service;
    public GetByClientIdEndpoint(TaxProfileService service) => _service = service;

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

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var clientId = Route<int>("clientId");
        try
        {
            var profile = await _service.GetByClientIdAsync(clientId);
            if (profile == null)
                ThrowError("세무 프로필을 찾을 수 없습니다.", statusCode: 404);
            await SendAsync(profile, 200, cancellation: ct);
        }
        catch
        {
            ThrowError("세무 프로필 조회 실패", statusCode: 500);
        }
    }
}

public class GetHighRiskEndpoint : Endpoint<EmptyRequest, TaxProfileListResponse>
{
    private readonly TaxProfileService _service;
    public GetHighRiskEndpoint(TaxProfileService service) => _service = service;

    public override void Configure()
    {
        Get("/api/taxprofile/high-risk");
        Policies("Bearer");
    }

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        try
        {
            var profiles = await _service.GetHighRiskProfilesAsync();
            await SendAsync(new TaxProfileListResponse { Data = profiles.Cast<object>().ToList() }, 200, cancellation: ct);
        }
        catch
        {
            ThrowError("고위험 세무 프로필 조회 실패", statusCode: 500);
        }
    }
}

public class GetUpcomingFilingsEndpoint : Endpoint<DaysAheadQuery, object>
{
    private readonly TaxProfileService _service;
    public GetUpcomingFilingsEndpoint(TaxProfileService service) => _service = service;

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

    public override async Task HandleAsync(DaysAheadQuery request, CancellationToken ct)
    {
        try
        {
            var profiles = await _service.GetUpcomingFilingDuesAsync(request.DaysAhead);
            await SendAsync(new { data = profiles, daysAhead = request.DaysAhead }, 200, cancellation: ct);
        }
        catch
        {
            ThrowError("예정 신고 조회 실패", statusCode: 500);
        }
    }
}

public class UpdateEndpoint : Endpoint<UpdateTaxProfileRequest, TaxProfileUpdateResponse>
{
    private readonly TaxProfileService _service;
    public UpdateEndpoint(TaxProfileService service) => _service = service;

    public override void Configure()
    {
        Put("/api/taxprofile/{id}");
        Policies("Bearer");
    }

    public override async Task HandleAsync(UpdateTaxProfileRequest request, CancellationToken ct)
    {
        var id = Route<int>("id");
        try
        {
            if (request.TaxRiskLevel is null)
                request.TaxRiskLevel = "normal";
            await _service.UpdateAsync(id, request.BusinessType, request.AccountingMethod,
                request.NextFilingDueDate, request.TaxRiskLevel);
            await SendAsync(new TaxProfileUpdateResponse { Message = "세무 프로필이 수정되었습니다." }, 200, cancellation: ct);
        }
        catch (ValidationException ex)
        {
            ThrowError(ex.Message);
        }
        catch
        {
            ThrowError("세무 프로필 수정 실패", statusCode: 500);
        }
    }
}
