using FastEndpoints;
using TaxBaik.Application.DTOs;
using TaxBaik.Application.Services;

namespace TaxBaik.Web.Endpoints.Announcement;

// DTOs
public class GetAnnouncementResponse
{
    public List<object> Data { get; set; } = [];
}

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

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

// Endpoints
public class GetActiveEndpoint : Endpoint<EmptyRequest, GetAnnouncementResponse>
{
    private readonly AnnouncementService _service;
    public GetActiveEndpoint(AnnouncementService service) => _service = service;

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

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        try
        {
            var announcements = await _service.GetActiveAsync(ct);
            await SendAsync(new GetAnnouncementResponse { Data = announcements.Cast<object>().ToList() }, 200, cancellation: ct);
        }
        catch (Exception ex)
        {
            ThrowError(ex.Message, statusCode: 500);
        }
    }
}

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

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

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        try
        {
            var announcements = await _service.GetAllAsync(ct);
            await SendAsync(new GetAnnouncementResponse { Data = announcements.Cast<object>().ToList() }, 200, cancellation: ct);
        }
        catch (Exception ex)
        {
            ThrowError(ex.Message, statusCode: 500);
        }
    }
}

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

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

    public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
    {
        var id = Route<int>("id");
        try
        {
            var announcement = await _service.GetByIdAsync(id, ct);
            if (announcement == null)
                ThrowError("공지사항을 찾을 수 없습니다.", statusCode: 404);
            await SendAsync(announcement, 200, cancellation: ct);
        }
        catch (Exception ex)
        {
            ThrowError(ex.Message, statusCode: 500);
        }
    }
}

public class CreateEndpoint : Endpoint<AnnouncementDto, CreateAnnouncementResponse>
{
    private readonly AnnouncementService _service;
    public CreateEndpoint(AnnouncementService service) => _service = service;

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

    public override async Task HandleAsync(AnnouncementDto request, CancellationToken ct)
    {
        try
        {
            var announcementId = await _service.CreateAsync(request, ct);
            var result = await _service.GetByIdAsync(announcementId, ct);
            await SendAsync(new CreateAnnouncementResponse { Id = announcementId }, 201, cancellation: ct);
        }
        catch (Exception ex)
        {
            ThrowError(ex.Message, statusCode: 400);
        }
    }
}

public class UpdateEndpoint : Endpoint<AnnouncementDto, UpdateAnnouncementResponse>
{
    private readonly AnnouncementService _service;
    public UpdateEndpoint(AnnouncementService service) => _service = service;

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

    public override async Task HandleAsync(AnnouncementDto request, CancellationToken ct)
    {
        var id = Route<int>("id");
        request.Id = id;
        try
        {
            await _service.UpdateAsync(request, ct);
            var result = await _service.GetByIdAsync(id, ct);
            if (result == null)
                ThrowError("공지사항을 찾을 수 없습니다.", statusCode: 404);
            await SendAsync(new UpdateAnnouncementResponse { Message = "공지사항이 수정되었습니다." }, 200, cancellation: ct);
        }
        catch (Exception ex)
        {
            ThrowError(ex.Message, statusCode: 400);
        }
    }
}

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

    public override void Configure()
    {
        Delete("/api/announcement/{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);
        }
    }
}
