using FastEndpoints;
using TaxBaik.Application.Services;

namespace TaxBaik.Web.Endpoints.Category;

// DTOs
public class CreateCategoryRequest
{
    public string Name { get; set; } = string.Empty;
    public string? Description { get; set; }
}

public class CategoryResponse
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Slug { get; set; } = string.Empty;
    public int SortOrder { get; set; }
}

public class CategoryListResponse
{
    public List<CategoryResponse> Data { get; set; } = [];
}

public class CategoryCreateResponse
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Slug { get; set; } = string.Empty;
}

// Endpoints
public class GetAllEndpoint : Endpoint<EmptyRequest, CategoryListResponse>
{
    private readonly CategoryService _service;
    public GetAllEndpoint(CategoryService service) => _service = service;

    public override void Configure()
    {
        Get("/api/category");
        AllowAnonymous();
    }

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        try
        {
            var categories = await _service.GetAllAsync(ct);
            var response = new CategoryListResponse
            {
                Data = categories.Select(c => new CategoryResponse
                {
                    Id = c.Id,
                    Name = c.Name,
                    Slug = c.Slug,
                    SortOrder = c.SortOrder
                }).ToList()
            };
            await SendAsync(response, 200, cancellation: ct);
        }
        catch (Exception ex)
        {
            ThrowError(ex.Message, statusCode: 500);
        }
    }
}

public class CreateEndpoint : Endpoint<CreateCategoryRequest, CategoryCreateResponse>
{
    private readonly CategoryService _service;
    public CreateEndpoint(CategoryService service) => _service = service;

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

    public override async Task HandleAsync(CreateCategoryRequest request, CancellationToken ct)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(request.Name))
                ThrowError("카테고리 이름은 필수입니다.");

            var category = await _service.CreateAsync(request.Name, request.Description, ct);
            var response = new CategoryCreateResponse
            {
                Id = category.Id,
                Name = category.Name,
                Slug = category.Slug
            };
            await SendAsync(response, 201, cancellation: ct);
        }
        catch (ValidationException ex)
        {
            ThrowError(ex.Message);
        }
        catch (Exception ex)
        {
            ThrowError(ex.Message, statusCode: 500);
        }
    }
}

public class UpdateEndpoint : Endpoint<CreateCategoryRequest, CategoryResponse>
{
    private readonly CategoryService _service;
    public UpdateEndpoint(CategoryService service) => _service = service;

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

    public override async Task HandleAsync(CreateCategoryRequest request, CancellationToken ct)
    {
        var id = Route<int>("id");
        try
        {
            var category = await _service.UpdateAsync(id, request.Name, request.Description, ct);
            if (category == null)
                ThrowError("카테고리를 찾을 수 없습니다.", statusCode: 404);

            var response = new CategoryResponse
            {
                Id = category.Id,
                Name = category.Name,
                Slug = category.Slug,
                SortOrder = category.SortOrder
            };
            await SendAsync(response, 200, cancellation: ct);
        }
        catch (ValidationException ex)
        {
            ThrowError(ex.Message);
        }
        catch (Exception ex)
        {
            ThrowError(ex.Message, statusCode: 500);
        }
    }
}

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

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

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var id = Route<int>("id");
        try
        {
            await _service.DeleteAsync(id, ct);
            await SendAsync(new EmptyResponse(), 204, cancellation: ct);
        }
        catch (Exception ex)
        {
            ThrowError(ex.Message, statusCode: 500);
        }
    }
}
