using FastEndpoints;
using TaxBaik.Application.Services;

namespace TaxBaik.Web.Endpoints.Contract;

public class CreateRequest { public int ClientId { get; set; } public string? ContractNumber { get; set; } public string? ServiceType { get; set; } public DateTime StartDate { get; set; } public decimal? MonthlyFee { get; set; } public decimal? TotalAmount { get; set; } }
public class ListResp { public List<object> Data { get; set; } = []; }
public class IdResp { public int Id { get; set; } }
public class MRRResp { public decimal MRR { get; set; } }
public class DaysQry { public int DaysAhead { get; set; } = 30; }

public class CreateEp : Endpoint<CreateRequest, IdResp>
{
    readonly ContractService _svc;
    public CreateEp(ContractService svc) => _svc = svc;
    public override void Configure() { Post("/api/contract"); Policies("Bearer"); }
    public override async Task HandleAsync(CreateRequest r, CancellationToken ct)
    {
        if (string.IsNullOrWhiteSpace(r.ContractNumber) || string.IsNullOrWhiteSpace(r.ServiceType))
            ThrowError("계약번호와 서비스 유형이 필요합니다.", statusCode: 400);
        var id = await _svc.CreateAsync(r.ClientId, r.ContractNumber, r.ServiceType, r.StartDate, r.MonthlyFee, r.TotalAmount);
        await SendAsync(new IdResp { Id = id }, 201, cancellation: ct);
    }
}

public class GetByIdEp : Endpoint<EmptyRequest, object>
{
    readonly ContractService _svc;
    public GetByIdEp(ContractService svc) => _svc = svc;
    public override void Configure() { Get("/api/contract/{id}"); Policies("Bearer"); }
    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var id = Route<int>("id");
        var c = await _svc.GetByIdAsync(id);
        if (c == null) ThrowError("계약을 찾을 수 없습니다.", statusCode: 404);
        await SendAsync(c, 200, cancellation: ct);
    }
}

public class GetAllEp : Endpoint<EmptyRequest, ListResp>
{
    readonly ContractService _svc;
    public GetAllEp(ContractService svc) => _svc = svc;
    public override void Configure() { Get("/api/contract"); Policies("Bearer"); }
    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var cs = await _svc.GetAllAsync();
        await SendAsync(new ListResp { Data = cs.Cast<object>().ToList() }, 200, cancellation: ct);
    }
}

public class GetByClientEp : Endpoint<EmptyRequest, ListResp>
{
    readonly ContractService _svc;
    public GetByClientEp(ContractService svc) => _svc = svc;
    public override void Configure() { Get("/api/contract/client/{clientId}"); Policies("Bearer"); }
    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var id = Route<int>("clientId");
        var cs = await _svc.GetByClientIdAsync(id);
        await SendAsync(new ListResp { Data = cs.Cast<object>().ToList() }, 200, cancellation: ct);
    }
}

public class GetActiveEp : Endpoint<EmptyRequest, ListResp>
{
    readonly ContractService _svc;
    public GetActiveEp(ContractService svc) => _svc = svc;
    public override void Configure() { Get("/api/contract/active"); Policies("Bearer"); }
    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var cs = await _svc.GetActiveContractsAsync();
        await SendAsync(new ListResp { Data = cs.Cast<object>().ToList() }, 200, cancellation: ct);
    }
}

public class GetExpiringEp : Endpoint<DaysQry, object>
{
    readonly ContractService _svc;
    public GetExpiringEp(ContractService svc) => _svc = svc;
    public override void Configure() { Get("/api/contract/expiring"); Policies("Bearer"); }
    public override async Task HandleAsync(DaysQry r, CancellationToken ct)
    {
        var cs = await _svc.GetExpiringContractsAsync(r.DaysAhead);
        await SendAsync(new { data = cs, daysAhead = r.DaysAhead }, 200, cancellation: ct);
    }
}

public class GetMRREp : Endpoint<EmptyRequest, MRRResp>
{
    readonly ContractService _svc;
    public GetMRREp(ContractService svc) => _svc = svc;
    public override void Configure() { Get("/api/contract/mrr"); Policies("Bearer"); }
    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var mrr = await _svc.GetMonthlyRecurringRevenueAsync();
        await SendAsync(new MRRResp { MRR = mrr }, 200, cancellation: ct);
    }
}
