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

namespace ERPCore.Controllers;

[Route("api/v1/sales-slips")]
public sealed class SalesSlipsController : ApiControllerBase
{
    private readonly ISalesSlipService _slips;

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

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

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

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

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

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

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

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