// EN: Reports REST API Controller.
// VI: Controller REST API cho Reports.

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OrderService.API.Application.Commands.Reports;
using OrderService.API.Application.Queries;
using OrderService.API.Application.Queries.Reports;

namespace OrderService.API.Controllers;

/// <summary>
/// EN: Reports API Controller for revenue and product analytics.
/// VI: Controller API Reports cho phân tích doanh thu và sản phẩm.
/// </summary>
[ApiController]
[Route("api/v1/reports")]
[Authorize]
public class ReportsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<ReportsController> _logger;

    public ReportsController(
        IMediator mediator,
        ILogger<ReportsController> logger)
    {
        _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// EN: Get revenue report grouped by period (daily, weekly, monthly).
    /// VI: Lấy báo cáo doanh thu theo kỳ (ngày, tuần, tháng).
    /// </summary>
    [HttpGet("revenue")]
    [ProducesResponseType(typeof(RevenueReportDto), StatusCodes.Status200OK)]
    public async Task<ActionResult<RevenueReportDto>> GetRevenueReport(
        [FromQuery] Guid shopId,
        [FromQuery] string period = "daily",
        [FromQuery] DateTime? fromDate = null,
        [FromQuery] DateTime? toDate = null,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Getting revenue report for shop {ShopId}, period {Period} / VI: Lấy báo cáo doanh thu cho shop {ShopId}, kỳ {Period}",
            shopId, period);

        var query = new GetRevenueReportQuery(period, shopId, fromDate, toDate);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(result);
    }

    /// <summary>
    /// EN: Get top selling products.
    /// VI: Lấy sản phẩm bán chạy nhất.
    /// </summary>
    [HttpGet("top-products")]
    [ProducesResponseType(typeof(List<TopProductDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<List<TopProductDto>>> GetTopProducts(
        [FromQuery] Guid shopId,
        [FromQuery] int limit = 10,
        [FromQuery] DateTime? fromDate = null,
        [FromQuery] DateTime? toDate = null,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Getting top {Limit} products for shop {ShopId} / VI: Lấy top {Limit} sản phẩm cho shop {ShopId}",
            limit, shopId);

        var query = new GetTopProductsQuery(shopId, limit, fromDate, toDate);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(result);
    }

    /// <summary>
    /// EN: Get advanced revenue analytics with trends, payment methods, top products, and vertical breakdown.
    /// VI: Lay phan tich doanh thu nang cao voi xu huong, phuong thuc thanh toan, san pham ban chay, va phan tich theo nganh.
    /// </summary>
    [HttpGet("revenue-analytics")]
    [ProducesResponseType(typeof(RevenueAnalyticsDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<RevenueAnalyticsDto>> GetRevenueAnalytics(
        [FromQuery] Guid shopId,
        [FromQuery] DateTime startDate,
        [FromQuery] DateTime endDate,
        [FromQuery] string period = "daily",
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Getting revenue analytics for shop {ShopId}, {Start} to {End}, period {Period} / VI: Lay phan tich doanh thu cho shop {ShopId}, {Start} den {End}, ky {Period}",
            shopId, startDate.ToString("yyyy-MM-dd"), endDate.ToString("yyyy-MM-dd"), period);

        var query = new GetRevenueAnalyticsQuery(shopId, startDate, endDate, period);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(new { success = true, data = result });
    }

    /// <summary>
    /// EN: Get staff performance metrics for a shop over a date range.
    /// VI: Lay chi so hieu suat nhan vien cho shop trong khoang thoi gian.
    /// </summary>
    [HttpGet("staff-performance")]
    [ProducesResponseType(typeof(StaffPerformanceDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<StaffPerformanceDto>> GetStaffPerformance(
        [FromQuery] Guid shopId,
        [FromQuery] DateTime startDate,
        [FromQuery] DateTime endDate,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Getting staff performance for shop {ShopId}, {Start} to {End} / VI: Lay hieu suat nhan vien cho shop {ShopId}, {Start} den {End}",
            shopId, startDate.ToString("yyyy-MM-dd"), endDate.ToString("yyyy-MM-dd"));

        var query = new GetStaffPerformanceQuery(shopId, startDate, endDate);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(new { success = true, data = result });
    }

    /// <summary>
    /// EN: Get End-of-Day report for a shop on a specific date.
    /// VI: Lay bao cao cuoi ngay cho shop vao ngay cu the.
    /// </summary>
    [HttpGet("eod")]
    [ProducesResponseType(typeof(EodReportDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<EodReportDto>> GetEodReport(
        [FromQuery] Guid shopId,
        [FromQuery] DateTime? date = null,
        CancellationToken cancellationToken = default)
    {
        var reportDate = date ?? DateTime.UtcNow.Date;

        _logger.LogInformation(
            "EN: Getting EOD report for shop {ShopId} on {Date} / VI: Lay bao cao cuoi ngay cho shop {ShopId} ngay {Date}",
            shopId, reportDate.ToString("yyyy-MM-dd"));

        var query = new GetEodReportQuery(shopId, reportDate);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(new { success = true, data = result });
    }

    /// <summary>
    /// EN: Close the business day and generate final EOD report.
    /// VI: Dong ngay kinh doanh va tao bao cao cuoi ngay cuoi cung.
    /// </summary>
    [HttpPost("close-day")]
    [ProducesResponseType(typeof(CloseDayResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<CloseDayResult>> CloseDay(
        [FromBody] CloseDayRequest request,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Closing day for shop {ShopId} on {Date} / VI: Dong ngay cho shop {ShopId} ngay {Date}",
            request.ShopId, request.CloseDate?.ToString("yyyy-MM-dd") ?? "today");

        var closeDate = request.CloseDate ?? DateTime.UtcNow.Date;
        var command = new CloseDayCommand(request.ShopId, closeDate);
        var result = await _mediator.Send(command, cancellationToken);

        if (!result.Success)
        {
            return BadRequest(new { success = false, error = new { code = "CLOSE_DAY_FAILED", message = result.Message } });
        }

        return Ok(new { success = true, data = result });
    }
}

/// <summary>
/// EN: Request to close the business day.
/// VI: Yeu cau dong ngay kinh doanh.
/// </summary>
public record CloseDayRequest(Guid ShopId, DateTime? CloseDate = null);
