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

namespace AdsServingService.API.Controllers;

/// <summary>
/// EN: Admin API Controller for managing budget pacing.
/// VI: API Controller Admin để quản lý điều tiết ngân sách.
/// </summary>
[ApiController]
[Route("api/v1/admin/budget")]
[Produces("application/json")]
public class AdminBudgetController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly AdsServingServiceContext _context;
    private readonly ILogger<AdminBudgetController> _logger;

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

    /// <summary>
    /// EN: Get paginated list of budget pacers.
    /// VI: Lấy danh sách budget pacers phân trang.
    /// </summary>
    [HttpGet("pacers")]
    [ProducesResponseType(typeof(PagedResult<BudgetPacerDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResult<BudgetPacerDto>>> GetBudgetPacers(
        [FromQuery] Guid? campaignId,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20)
    {
        var query = new GetBudgetPacersQuery
        {
            CampaignId = campaignId,
            Page = page,
            PageSize = pageSize
        };

        var result = await _mediator.Send(query);
        return Ok(result);
    }

    /// <summary>
    /// EN: Get budget status for a specific campaign.
    /// VI: Lấy trạng thái ngân sách cho một chiến dịch cụ thể.
    /// </summary>
    [HttpGet("campaigns/{campaignId}")]
    [ProducesResponseType(typeof(BudgetPacerDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<BudgetPacerDto>> GetCampaignBudget(Guid campaignId)
    {
        var pacer = await _context.BudgetPacers
            .Where(bp => EF.Property<Guid>(bp, "_campaignId") == campaignId)
            .Select(bp => new BudgetPacerDto
            {
                Id = bp.Id,
                CampaignId = EF.Property<Guid>(bp, "_campaignId"),
                DailyBudget = EF.Property<decimal>(bp, "_dailyBudget"),
                SpentToday = EF.Property<decimal>(bp, "_spentToday"),
                RemainingBudget = bp.RemainingBudget,
                UtilizationPercent = bp.UtilizationPercent,
                Strategy = bp.Strategy.ToString(),
                LastUpdated = EF.Property<DateTime>(bp, "_lastUpdated")
            })
            .FirstOrDefaultAsync();

        if (pacer == null)
            return NotFound();

        return Ok(pacer);
    }

    /// <summary>
    /// EN: Reset daily spend for a campaign (manual intervention).
    /// VI: Reset chi tiêu hàng ngày cho một chiến dịch (can thiệp thủ công).
    /// </summary>
    [HttpPut("campaigns/{campaignId}/reset")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> ResetCampaignBudget(Guid campaignId)
    {
        var pacer = await _context.BudgetPacers
            .Where(bp => EF.Property<Guid>(bp, "_campaignId") == campaignId)
            .FirstOrDefaultAsync();

        if (pacer == null)
            return NotFound();

        pacer.ResetDailySpend();
        await _context.SaveChangesAsync();

        _logger.LogInformation("Manual budget reset for Campaign {CampaignId}", campaignId);
        return Ok();
    }

    /// <summary>
    /// EN: Get budget utilization statistics.
    /// VI: Lấy thống kê sử dụng ngân sách.
    /// </summary>
    [HttpGet("statistics")]
    [ProducesResponseType(typeof(BudgetStatisticsDto), StatusCodes.Status200OK)]
    public async Task<ActionResult<BudgetStatisticsDto>> GetStatistics()
    {
        var stats = await _context.BudgetPacers
            .Select(bp => new
            {
                DailyBudget = EF.Property<decimal>(bp, "_dailyBudget"),
                SpentToday = EF.Property<decimal>(bp, "_spentToday"),
                Utilization = bp.UtilizationPercent
            })
            .ToListAsync();

        var result = new BudgetStatisticsDto
        {
            TotalCampaigns = stats.Count,
            TotalDailyBudget = stats.Sum(s => s.DailyBudget),
            TotalSpentToday = stats.Sum(s => s.SpentToday),
            AverageUtilization = stats.Any() ? stats.Average(s => s.Utilization) : 0,
            CampaignsExceeded = stats.Count(s => s.Utilization >= 100)
        };

        return Ok(result);
    }
}
