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

namespace ERPCore.Controllers;

/// <summary>Purchase-order endpoints (docs/11 §3.3).</summary>
[Route("api/v1/purchase-orders")]
public sealed class PurchaseOrdersController : ApiControllerBase
{
    private readonly IPurchaseOrderService _pos;

    public PurchaseOrdersController(IPurchaseOrderService pos) => _pos = pos;

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

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

        SetETag(result.RowVersion);
        return Ok(result.Value);
    }

    /// <summary>Create a PO — auto-approved on creation in Phase 1 (FR-PROC-04). Totals computed server-side.</summary>
    [HttpPost]
    [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
    public async Task<ActionResult<PurchaseOrderDto>> Create([FromBody] CreatePurchaseOrderRequest request, CancellationToken ct)
    {
        var result = await _pos.CreateAsync(request, ct);
        SetETag(result.RowVersion);
        return Created($"/api/v1/purchase-orders/{result.Value.PoId}", result.Value);
    }

    /// <summary>Edit while open (FR-PROC-05); requires <c>If-Match</c>. 409 PO_NOT_EDITABLE if closed.</summary>
    [HttpPut("{poId:int}")]
    [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    [ProducesResponseType(StatusCodes.Status412PreconditionFailed)]
    public async Task<ActionResult<PurchaseOrderDto>> Update(int poId, [FromBody] UpdatePurchaseOrderRequest request, CancellationToken ct)
    {
        var expected = RequireIfMatch();
        var result = await _pos.UpdateAsync(poId, request, expected, ct);
        SetETag(result.RowVersion);
        return Ok(result.Value);
    }

    /// <summary>Submit a Draft PO (Draft → Approved). 409 PO_NOT_EDITABLE if not Draft.</summary>
    [HttpPost("{poId:int}/submit")]
    [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<ActionResult<PurchaseOrderDto>> Submit(int poId, CancellationToken ct)
        => Ok(await _pos.SubmitAsync(poId, ct));

    /// <summary>Delete a PO — permitted only while Draft (409 PO_NOT_EDITABLE otherwise).</summary>
    [HttpDelete("{poId:int}")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<IActionResult> Delete(int poId, CancellationToken ct)
    {
        await _pos.DeleteAsync(poId, ct);
        return NoContent();
    }

    /// <summary>Approve — no-op in Phase 1 (POs auto-approve); transitions PendingApproval→Approved when enabled.</summary>
    [HttpPost("{poId:int}/approve")]
    [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<PurchaseOrderDto>> Approve(int poId, CancellationToken ct)
        => Ok(await _pos.ApproveAsync(poId, ct));

    /// <summary>Cancel — 409 if any goods have been received against the PO.</summary>
    [HttpPost("{poId:int}/cancel")]
    [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<ActionResult<PurchaseOrderDto>> Cancel(int poId, [FromBody] CancelPurchaseOrderRequest request, CancellationToken ct)
        => Ok(await _pos.CancelAsync(poId, request.Reason, ct));
}
