using FastEndpoints;
using TaxBaik.Application.Services;

namespace TaxBaik.Web.Endpoints.Company;

// DTOs
public class CreateCompanyRequest
{
    public string CompanyCode { get; set; } = string.Empty;
    public string CompanyName { get; set; } = string.Empty;
    public string? ContactPerson { get; set; }
    public string? Phone { get; set; }
    public string? Email { get; set; }
    public string? Memo { get; set; }
}

public class UpdateCompanyRequest
{
    public string CompanyCode { get; set; } = string.Empty;
    public string CompanyName { get; set; } = string.Empty;
    public string? ContactPerson { get; set; }
    public string? Phone { get; set; }
    public string? Email { get; set; }
    public string? Memo { get; set; }
    public bool IsActive { get; set; } = true;
}

public class CompanyResponse
{
    public object Data { get; set; } = null!;
}

public class CompanyListResponse
{
    public List<object> Data { get; set; } = [];
    public int Total { get; set; }
    public int Page { get; set; }
    public int PageSize { get; set; }
}

public class CompanyCreateResponse
{
    public string Message { get; set; } = string.Empty;
    public int Id { get; set; }
}

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

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

public class GetPagedQuery
{
    public int Page { get; set; } = 1;
    public int PageSize { get; set; } = 20;
}

// Endpoints
public class GetByIdEndpoint : Endpoint<EmptyRequest, CompanyResponse>
{
    private readonly CompanyService _service;
    public GetByIdEndpoint(CompanyService service) => _service = service;

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

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var id = Route<int>("id");
        try
        {
            var company = await _service.GetByIdAsync(id);
            if (company == null)
                ThrowError("회사를 찾을 수 없습니다.", statusCode: 404);
            await SendAsync(new CompanyResponse { Data = company }, 200, cancellation: ct);
        }
        catch
        {
            ThrowError("회사 조회 실패", statusCode: 500);
        }
    }
}

public class GetByCodeEndpoint : Endpoint<EmptyRequest, CompanyResponse>
{
    private readonly CompanyService _service;
    public GetByCodeEndpoint(CompanyService service) => _service = service;

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

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var code = Route<string>("code");
        try
        {
            if (string.IsNullOrWhiteSpace(code))
                ThrowError("회사 코드가 필요합니다.", statusCode: 400);
            var company = await _service.GetByCodeAsync(code);
            if (company == null)
                ThrowError("회사를 찾을 수 없습니다.", statusCode: 404);
            await SendAsync(new CompanyResponse { Data = company }, 200, cancellation: ct);
        }
        catch
        {
            ThrowError("회사 조회 실패", statusCode: 500);
        }
    }
}

public class GetPagedEndpoint : Endpoint<GetPagedQuery, CompanyListResponse>
{
    private readonly CompanyService _service;
    public GetPagedEndpoint(CompanyService service) => _service = service;

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

    public override async Task HandleAsync(GetPagedQuery request, CancellationToken ct)
    {
        try
        {
            var (companies, total) = await _service.GetPagedAsync(request.Page, request.PageSize);
            await SendAsync(new CompanyListResponse
            {
                Data = companies.Cast<object>().ToList(),
                Total = total,
                Page = request.Page,
                PageSize = request.PageSize
            }, 200, cancellation: ct);
        }
        catch
        {
            ThrowError("회사 목록 조회 실패", statusCode: 500);
        }
    }
}

public class CreateEndpoint : Endpoint<CreateCompanyRequest, CompanyCreateResponse>
{
    private readonly CompanyService _service;
    public CreateEndpoint(CompanyService service) => _service = service;

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

    public override async Task HandleAsync(CreateCompanyRequest request, CancellationToken ct)
    {
        try
        {
            var id = await _service.CreateAsync(
                request.CompanyCode, request.CompanyName, request.ContactPerson,
                request.Phone, request.Email, request.Memo);
            await SendAsync(new CompanyCreateResponse { Message = "회사가 등록되었습니다.", Id = id }, 201, cancellation: ct);
        }
        catch (ValidationException ex)
        {
            ThrowError(ex.Message);
        }
        catch
        {
            ThrowError("회사 등록 실패", statusCode: 500);
        }
    }
}

public class UpdateEndpoint : Endpoint<UpdateCompanyRequest, CompanyUpdateResponse>
{
    private readonly CompanyService _service;
    public UpdateEndpoint(CompanyService service) => _service = service;

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

    public override async Task HandleAsync(UpdateCompanyRequest request, CancellationToken ct)
    {
        var id = Route<int>("id");
        try
        {
            await _service.UpdateAsync(id, request.CompanyCode, request.CompanyName,
                request.ContactPerson, request.Phone, request.Email, request.Memo, request.IsActive);
            await SendAsync(new CompanyUpdateResponse { Message = "회사가 수정되었습니다." }, 200, cancellation: ct);
        }
        catch (ValidationException ex)
        {
            ThrowError(ex.Message);
        }
        catch
        {
            ThrowError("회사 수정 실패", statusCode: 500);
        }
    }
}

public class DeleteEndpoint : Endpoint<EmptyRequest, CompanyDeleteResponse>
{
    private readonly CompanyService _service;
    public DeleteEndpoint(CompanyService service) => _service = service;

    public override void Configure()
    {
        Delete("/api/company/{id:int}");
        Policies("Bearer");
    }

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var id = Route<int>("id");
        try
        {
            await _service.DeleteAsync(id);
            await SendAsync(new CompanyDeleteResponse { Message = "회사가 삭제되었습니다." }, 200, cancellation: ct);
        }
        catch (ValidationException ex)
        {
            ThrowError(ex.Message);
        }
        catch
        {
            ThrowError("회사 삭제 실패", statusCode: 500);
        }
    }
}
