using ERPCore.Domain.Enums;
using ERPCore.Dtos.Common;
using ERPCore.Dtos.Sales;
using ERPCore.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;

namespace ERPCore.Controllers;

/// <summary>
/// Thin API alias for free-issue handling. Free issues are modeled as sales slips
/// with line-level <c>IsFreeIssue</c>/<c>FreeQty</c> flags, so this controller reuses
/// the existing sales-slip CRUD surface under a more business-friendly route.
/// </summary>
[Route("api/v1/free-issues")]
public sealed class FreeIssuesController : ApiControllerBase
{
    private readonly ISalesSlipService _slips;

    public FreeIssuesController(ISalesSlipService slips) => _slips = slips;

    [HttpGet]
    [ProducesResponseType(typeof(PagedResponse<FreeIssueSummaryDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResponse<FreeIssueSummaryDto>>> List(
        [FromQuery] PageQuery query,
        [FromQuery] SalesSlipStatus? status,
        [FromQuery] int? customerId,
        [FromQuery] int? warehouseId,
        CancellationToken ct)
        => Ok(await _slips.ListFreeIssuesAsync(query, status, customerId, warehouseId, ct));

    [HttpGet("{freeIssueId:int}")]
    [ProducesResponseType(typeof(FreeIssueDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<FreeIssueDto>> GetById(int freeIssueId, CancellationToken ct)
    {
        var result = await _slips.GetFreeIssueAsync(freeIssueId, ct);
        if (result is null) return NotFound();
        SetETag(result.RowVersion);
        return Ok(result.Value);
    }

    [HttpGet("{freeIssueId:int}/posting-check")]
    [ProducesResponseType(typeof(SalesSlipPostingCheckDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<SalesSlipPostingCheckDto>> PostingCheck(int freeIssueId, CancellationToken ct)
        => Ok(await _slips.CheckPostingAsync(freeIssueId, ct));

    [HttpPost]
    [ProducesResponseType(typeof(FreeIssueDto), StatusCodes.Status201Created)]
    public async Task<ActionResult<FreeIssueDto>> Create([FromBody] CreateSalesSlipRequest request, CancellationToken ct)
    {
        var result = await _slips.CreateAsync(request, ct);
        SetETag(result.RowVersion);
        return Created($"/api/v1/free-issues/{result.Value.SalesSlipId}", result.Value);
    }

    [HttpPut("{freeIssueId:int}")]
    [ProducesResponseType(typeof(FreeIssueDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status412PreconditionFailed)]
    public async Task<ActionResult<FreeIssueDto>> Update(int freeIssueId, [FromBody] UpdateSalesSlipRequest request, CancellationToken ct)
    {
        var expected = RequireIfMatch();
        var result = await _slips.UpdateAsync(freeIssueId, request, expected, ct);
        SetETag(result.RowVersion);
        return Ok(result.Value);
    }

    [HttpPost("{freeIssueId:int}/post")]
    [ProducesResponseType(typeof(FreeIssueDto), StatusCodes.Status200OK)]
    public async Task<ActionResult<FreeIssueDto>> Post(int freeIssueId, CancellationToken ct)
        => Ok(await _slips.PostAsync(freeIssueId, ct));

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