using ERPCore.Domain.Enums;
using ERPCore.Dtos.Common;
using ERPCore.Dtos.Hrm;
using ERPCore.Infra.Auth;
using ERPCore.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;

namespace ERPCore.Controllers.Hrm;

/// <summary>Leave request endpoints (docs/13-BACKEND-HRM-API.md §5).</summary>
[Route("api/v1/leave-requests")]
public sealed class LeaveRequestsController : ApiControllerBase
{
    private readonly ILeaveRequestService _requests;
    private readonly ICurrentUser _currentUser;

    public LeaveRequestsController(ILeaveRequestService requests, ICurrentUser currentUser)
    {
        _requests = requests;
        _currentUser = currentUser;
    }

    [HttpGet]
    [ProducesResponseType(typeof(PagedResponse<LeaveRequestDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResponse<LeaveRequestDto>>> List(
        [FromQuery] PageQuery query, [FromQuery] int? employeeId, [FromQuery] LeaveRequestStatus? status, CancellationToken ct)
        => Ok(await _requests.ListAsync(query, employeeId, status, ct));

    [HttpGet("{leaveRequestId:int}")]
    [ProducesResponseType(typeof(LeaveRequestDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<LeaveRequestDto>> GetById(int leaveRequestId, CancellationToken ct)
    {
        var result = await _requests.GetAsync(leaveRequestId, ct);
        return result is null ? NotFound() : Ok(result);
    }

    [HttpPost]
    [ProducesResponseType(typeof(LeaveRequestDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
    public async Task<ActionResult<LeaveRequestDto>> Create([FromBody] CreateLeaveRequestRequest request, CancellationToken ct)
    {
        var result = await _requests.CreateAsync(request, _currentUser.AuditUserId, ct);
        return Created($"/api/v1/leave-requests/{result.LeaveRequestId}", result);
    }

    [HttpPost("{leaveRequestId:int}/submit")]
    [ProducesResponseType(typeof(LeaveRequestDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<ActionResult<LeaveRequestDto>> Submit(int leaveRequestId, CancellationToken ct)
        => Ok(await _requests.SubmitAsync(leaveRequestId, ct));

    [HttpPost("{leaveRequestId:int}/approve")]
    [ProducesResponseType(typeof(LeaveRequestDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<ActionResult<LeaveRequestDto>> Approve(int leaveRequestId, CancellationToken ct)
        => Ok(await _requests.ApproveAsync(leaveRequestId, _currentUser.AuditUserId, ct));

    [HttpPost("{leaveRequestId:int}/reject")]
    [ProducesResponseType(typeof(LeaveRequestDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<ActionResult<LeaveRequestDto>> Reject(int leaveRequestId, [FromBody] RejectLeaveRequestRequest request, CancellationToken ct)
        => Ok(await _requests.RejectAsync(leaveRequestId, request.Reason, _currentUser.AuditUserId, ct));

    [HttpPost("{leaveRequestId:int}/cancel")]
    [ProducesResponseType(typeof(LeaveRequestDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<ActionResult<LeaveRequestDto>> Cancel(int leaveRequestId, CancellationToken ct)
        => Ok(await _requests.CancelAsync(leaveRequestId, ct));
}
