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

namespace ERPCore.Controllers;

/// <summary>Cashier day-end close-out — locks a cashier's Posted sales slips for a business
/// date and posts one consolidated GL journal entry for the day (docs/14 Sales API).</summary>
[Route("api/v1/sales-day-end")]
public sealed class SalesDayEndController : ApiControllerBase
{
    private readonly ISalesDayEndService _dayEnds;

    public SalesDayEndController(ISalesDayEndService dayEnds) => _dayEnds = dayEnds;

    /// <summary>List day-end closes, newest first.</summary>
    [HttpGet]
    [ProducesResponseType(typeof(PagedResponse<SalesDayEndSummaryDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResponse<SalesDayEndSummaryDto>>> List(
        [FromQuery] PageQuery query, [FromQuery] int? cashierUserId, CancellationToken ct)
        => Ok(await _dayEnds.ListAsync(query, cashierUserId, ct));

    /// <summary>What closing this cashier/date right now would include (or the existing close's totals, if already closed).</summary>
    [HttpGet("preview")]
    [ProducesResponseType(typeof(SalesDayEndPreviewDto), StatusCodes.Status200OK)]
    public async Task<ActionResult<SalesDayEndPreviewDto>> Preview(
        [FromQuery] int cashierUserId, [FromQuery] DateOnly? businessDate, CancellationToken ct)
        => Ok(await _dayEnds.PreviewAsync(cashierUserId, businessDate ?? DateOnly.FromDateTime(DateTime.UtcNow), ct));

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

    /// <summary>Close the day: lock every Posted slip for (CashierUserId, BusinessDate) and post the
    /// consolidated GL journal entry. Idempotent — closing an already-closed date replays it.</summary>
    [HttpPost]
    [ProducesResponseType(typeof(SalesDayEndDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<ActionResult<SalesDayEndDto>> Close([FromBody] CreateSalesDayEndRequest request, CancellationToken ct)
    {
        var dto = await _dayEnds.CloseAsync(request, ct);
        return Created($"/api/v1/sales-day-end/{dto.SalesDayEndId}", dto);
    }
}
