using AdsBillingService.API.Application.Queries;
using AdsBillingService.Infrastructure;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace AdsBillingService.API.Controllers.Admin;

/// <summary>
/// EN: Admin controller for managing invoices.
/// VI: Admin controller quản lý hóa đơn.
/// </summary>
[ApiController]
[Route("api/v1/admin/ads-billing/invoices")]
[Produces("application/json")]
public class AdminInvoicesController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly AdsBillingServiceContext _context;
    private readonly ILogger<AdminInvoicesController> _logger;

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

    /// <summary>
    /// EN: Search invoices with advanced filters.
    /// VI: Tìm kiếm hóa đơn với bộ lọc nâng cao.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> SearchInvoices(
        [FromQuery] string? status = null,
        [FromQuery] DateTime? fromDate = null,
        [FromQuery] DateTime? toDate = null,
        [FromQuery] int pageNumber = 1,
        [FromQuery] int pageSize = 20)
    {
        _logger.LogInformation("Admin searching invoices with Status={Status}, FromDate={FromDate}, ToDate={ToDate}", 
            status, fromDate, toDate);

        var query = _context.Invoices.AsNoTracking();

        if (!string.IsNullOrEmpty(status))
        {
            query = query.Where(i => i.Status.ToString() == status);
        }

        if (fromDate.HasValue)
        {
            query = query.Where(i => i.IssueDate >= fromDate.Value);
        }

        if (toDate.HasValue)
        {
            query = query.Where(i => i.IssueDate <= toDate.Value);
        }

        var invoices = await query
            .OrderByDescending(i => i.IssueDate)
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize)
            .Select(i => new
            {
                i.Id,
                i.BillingAccountId,
                i.InvoiceNumber,
                Status = i.Status.ToString(),
                i.IssueDate,
                i.DueDate,
                i.TotalAmount
            })
            .ToListAsync();

        return Ok(new { pageNumber, pageSize, total = invoices.Count, data = invoices });
    }

    /// <summary>
    /// EN: Get invoice statistics.
    /// VI: Lấy thống kê hóa đơn.
    /// </summary>
    [HttpGet("stats")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetStatistics()
    {
        _logger.LogInformation("Getting invoice statistics");

        var totalInvoices = await _context.Invoices.CountAsync();
        var paidInvoices = await _context.Invoices.CountAsync(i => i.Status == Domain.AggregatesModel.InvoiceAggregate.InvoiceStatus.Paid);
        var overdueInvoices = await _context.Invoices.CountAsync(i => i.Status == Domain.AggregatesModel.InvoiceAggregate.InvoiceStatus.Overdue);
        var totalAmount = await _context.Invoices.SumAsync(i => i.TotalAmount);
        var paidAmount = await _context.Invoices
            .Where(i => i.Status == Domain.AggregatesModel.InvoiceAggregate.InvoiceStatus.Paid)
            .SumAsync(i => i.TotalAmount);

        return Ok(new
        {
            totalInvoices,
            paidInvoices,
            overdueInvoices,
            pendingInvoices = totalInvoices - paidInvoices - overdueInvoices,
            totalAmount,
            paidAmount,
            outstandingAmount = totalAmount - paidAmount
        });
    }

    /// <summary>
    /// EN: Mark invoice as paid.
    /// VI: Đánh dấu hóa đơn đã thanh toán.
    /// </summary>
    [HttpPost("{id}/mark-paid")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> MarkInvoiceAsPaid(Guid id)
    {
        _logger.LogInformation("Marking invoice {InvoiceId} as paid", id);

        var invoice = await _context.Invoices.FirstOrDefaultAsync(i => i.Id == id);

        if (invoice == null)
        {
            return NotFound(new { message = $"Invoice {id} not found" });
        }

        invoice.MarkAsPaid();
        await _context.SaveEntitiesAsync();

        return Ok(new
        {
            invoiceId = id,
            invoiceNumber = invoice.InvoiceNumber,
            status = "Paid",
            amount = invoice.TotalAmount
        });
    }

    /// <summary>
    /// EN: Regenerate invoice (placeholder).
    /// VI: Tạo lại hóa đơn (placeholder).
    /// </summary>
    [HttpPost("regenerate")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> RegenerateInvoice([FromBody] RegenerateInvoiceRequest request)
    {
        _logger.LogInformation("Regenerating invoice for account {AccountId}, period {StartDate} to {EndDate}", 
            request.BillingAccountId, request.StartDate, request.EndDate);

        // TODO: Implement invoice regeneration logic
        return Ok(new
        {
            message = "Invoice regeneration initiated",
            billingAccountId = request.BillingAccountId,
            period = new { request.StartDate, request.EndDate }
        });
    }
}

/// <summary>
/// EN: Request to regenerate invoice.
/// VI: Request tạo lại hóa đơn.
/// </summary>
public record RegenerateInvoiceRequest(
    Guid BillingAccountId,
    DateTime StartDate,
    DateTime EndDate
);
