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

namespace ERPCore.Controllers;

/// <summary>Customer master endpoints for Phase 1 sales.</summary>
[Route("api/v1/customers")]
public sealed class CustomersController : ApiControllerBase
{
    private readonly ICustomerService _customers;

    public CustomersController(ICustomerService customers) => _customers = customers;

    [HttpGet]
    [ProducesResponseType(typeof(PagedResponse<CustomerDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResponse<CustomerDto>>> List(
        [FromQuery] PageQuery query,
        [FromQuery] EntityStatus? status,
        [FromQuery] CustomerType? customerType,
        CancellationToken ct)
        => Ok(await _customers.ListAsync(query, status, customerType, ct));

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

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

    [HttpPost]
    [ProducesResponseType(typeof(CustomerDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<ActionResult<CustomerDto>> Create([FromBody] CreateCustomerRequest request, CancellationToken ct)
    {
        var result = await _customers.CreateAsync(request, ct);
        SetETag(result.RowVersion);
        return Created($"/api/v1/customers/{result.Value.CustomerId}", result.Value);
    }

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

    [HttpPatch("{customerId:int}/status")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> SetStatus(int customerId, [FromBody] UpdateCustomerStatusRequest request, CancellationToken ct)
    {
        await _customers.SetStatusAsync(customerId, request.Status, ct);
        return NoContent();
    }
}
