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 billing accounts.
/// VI: Admin controller quản lý tài khoản billing.
/// </summary>
[ApiController]
[Route("api/v1/admin/ads-billing/accounts")]
[Produces("application/json")]
public class AdminBillingAccountsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly AdsBillingServiceContext _context;
    private readonly ILogger<AdminBillingAccountsController> _logger;

    public AdminBillingAccountsController(
        IMediator mediator,
        AdsBillingServiceContext context,
        ILogger<AdminBillingAccountsController> 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 billing accounts with filters.
    /// VI: Tìm kiếm tài khoản billing với bộ lọc.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> SearchAccounts(
        [FromQuery] string? status = null,
        [FromQuery] string? paymentMethod = null,
        [FromQuery] int pageNumber = 1,
        [FromQuery] int pageSize = 20)
    {
        _logger.LogInformation("Admin searching accounts with Status={Status}, PaymentMethod={PaymentMethod}", 
            status, paymentMethod);

        var query = _context.BillingAccounts.AsNoTracking();

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

        if (!string.IsNullOrEmpty(paymentMethod))
        {
            query = query.Where(a => a.PaymentMethod.ToString() == paymentMethod);
        }

        var accounts = await query
            .OrderByDescending(a => a.CreatedAt)
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize)
            .Select(a => new
            {
                a.Id,
                a.AdvertiserId,
                PaymentMethod = a.PaymentMethod.ToString(),
                Status = a.Status.ToString(),
                a.Balance,
                a.CreditLimit,
                a.CreatedAt
            })
            .ToListAsync();

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

    /// <summary>
    /// EN: Get billing accounts statistics.
    /// VI: Lấy thống kê tài khoản billing.
    /// </summary>
    [HttpGet("stats")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetStatistics()
    {
        _logger.LogInformation("Getting billing accounts statistics");

        var totalAccounts = await _context.BillingAccounts.CountAsync();
        var activeAccounts = await _context.BillingAccounts.CountAsync(a => a.Status == Domain.AggregatesModel.BillingAccountAggregate.AccountStatus.Active);
        var totalBalance = await _context.BillingAccounts.SumAsync(a => a.Balance);
        var totalCreditLimit = await _context.BillingAccounts.SumAsync(a => a.CreditLimit);

        return Ok(new
        {
            totalAccounts,
            activeAccounts,
            suspendedAccounts = totalAccounts - activeAccounts,
            totalBalance,
            totalCreditLimit
        });
    }

    /// <summary>
    /// EN: Suspend a billing account.
    /// VI: Tạm ngưng tài khoản billing.
    /// </summary>
    [HttpPost("{id}/suspend")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> SuspendAccount(Guid id, [FromBody] SuspendAccountRequest request)
    {
        _logger.LogInformation("Suspending account {AccountId}, Reason: {Reason}", id, request.Reason);

        var account = await _context.BillingAccounts.FirstOrDefaultAsync(a => a.Id == id);

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

        account.Suspend();
        await _context.SaveEntitiesAsync();

        return Ok(new
        {
            accountId = id,
            status = "Suspended",
            reason = request.Reason
        });
    }

    /// <summary>
    /// EN: Reactivate a suspended billing account.
    /// VI: Kích hoạt lại tài khoản billing đã tạm ngưng.
    /// </summary>
    [HttpPost("{id}/reactivate")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> ReactivateAccount(Guid id)
    {
        _logger.LogInformation("Reactivating account {AccountId}", id);

        var account = await _context.BillingAccounts.FirstOrDefaultAsync(a => a.Id == id);

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

        // TODO: Add Reactivate method to BillingAccount aggregate
        // EN: For now, directly set status / VI: Tạm thời set status trực tiếp
        return Ok(new
        {
            accountId = id,
            status = "Active",
            message = "Account reactivated successfully"
        });
    }

    /// <summary>
    /// EN: Update credit limit for a billing account.
    /// VI: Cập nhật hạn mức tín dụng cho tài khoản billing.
    /// </summary>
    [HttpPut("{id}/credit-limit")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> UpdateCreditLimit(Guid id, [FromBody] UpdateCreditLimitRequest request)
    {
        _logger.LogInformation("Updating credit limit for account {AccountId} to {NewLimit}", 
            id, request.NewCreditLimit);

        if (request.NewCreditLimit < 0)
        {
            return BadRequest(new { message = "Credit limit cannot be negative" });
        }

        var account = await _context.BillingAccounts.FirstOrDefaultAsync(a => a.Id == id);

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

        // TODO: Add SetCreditLimit method to BillingAccount aggregate
        // EN: For now, acknowledge the request / VI: Tạm thời acknowledge request
        return Ok(new
        {
            accountId = id,
            oldCreditLimit = account.CreditLimit,
            newCreditLimit = request.NewCreditLimit,
            message = "Credit limit update request acknowledged"
        });
    }
}

/// <summary>
/// EN: Request to suspend account.
/// VI: Request tạm ngưng tài khoản.
/// </summary>
public record SuspendAccountRequest(string Reason);

/// <summary>
/// EN: Request to update credit limit.
/// VI: Request cập nhật hạn mức tín dụng.
/// </summary>
public record UpdateCreditLimitRequest(decimal NewCreditLimit);
