using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using AdsBillingService.Infrastructure;

namespace AdsBillingService.API.Controllers;

/// <summary>
/// EN: API Controller for managing credit lines.
/// VI: API Controller quản lý hạn mức tín dụng.
/// </summary>
[ApiController]
[Authorize]
[Route("api/v1/ads-billing/credit-lines")]
[Produces("application/json")]
public class CreditLinesController : ControllerBase
{
    private readonly AdsBillingServiceContext _context;
    private readonly ILogger<CreditLinesController> _logger;

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

    /// <summary>
    /// EN: Get credit line information for an advertiser.
    /// VI: Lấy thông tin hạn mức tín dụng của advertiser.
    /// </summary>
    [HttpGet("{advertiserId}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetCreditLine(Guid advertiserId, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Getting credit line for advertiser {AdvertiserId}", advertiserId);

        var account = await _context.BillingAccounts
            .AsNoTracking()
            .FirstOrDefaultAsync(a => a.AdvertiserId == advertiserId, cancellationToken);

        if (account == null)
        {
            return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Billing account for advertiser {advertiserId} not found" } });
        }

        var availableCredit = account.CreditLimit <= 0
            ? 0m
            : Math.Max(0m, account.CreditLimit - account.Balance);

        return Ok(new { success = true, data = new
        {
            advertiserId,
            accountId = account.Id,
            creditLimit = account.CreditLimit,
            balance = account.Balance,
            availableCredit,
            paymentMethod = account.PaymentMethod.ToString(),
            status = account.Status.ToString()
        } });
    }

    /// <summary>
    /// EN: Request credit limit increase.
    /// VI: Yêu cầu tăng hạn mức tín dụng.
    /// </summary>
    [HttpPost("request")]
    [ProducesResponseType(StatusCodes.Status202Accepted)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> RequestCreditIncrease(
        [FromBody] CreditIncreaseRequest request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Credit increase request for advertiser {AdvertiserId}, amount {Amount}", 
            request.AdvertiserId, request.RequestedAmount);

        if (request.RequestedAmount <= 0)
        {
            return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = "Requested amount must be positive" } });
        }

        var account = await _context.BillingAccounts
            .FirstOrDefaultAsync(a => a.AdvertiserId == request.AdvertiserId, cancellationToken);

        if (account == null)
        {
            return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = $"Billing account for advertiser {request.AdvertiserId} not found" } });
        }

        var oldCreditLimit = account.CreditLimit;
        account.SetCreditLimit(oldCreditLimit + request.RequestedAmount);
        await _context.SaveEntitiesAsync(cancellationToken);

        return Accepted(new { success = true, data = new
        {
            advertiserId = request.AdvertiserId,
            accountId = account.Id,
            requestedAmount = request.RequestedAmount,
            oldCreditLimit,
            newCreditLimit = account.CreditLimit,
            status = account.Status.ToString(),
            message = "Credit limit increased successfully"
        } });
    }
}

/// <summary>
/// EN: Request model for credit increase.
/// VI: Request model cho yêu cầu tăng tín dụng.
/// </summary>
public record CreditIncreaseRequest(
    Guid AdvertiserId,
    decimal RequestedAmount,
    string? Reason = null
);
