using AdsServingService.Domain.AggregatesModel.FrequencyAggregate;
using AdsServingService.Infrastructure;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace AdsServingService.API.Controllers;

/// <summary>
/// EN: Admin API Controller for managing frequency caps.
/// VI: API Controller Admin để quản lý frequency caps.
/// </summary>
[ApiController]
[Authorize]
[Route("api/v1/admin/frequency")]
[Produces("application/json")]
public class AdminFrequencyController : ControllerBase
{
    private readonly AdsServingServiceContext _context;
    private readonly ILogger<AdminFrequencyController> _logger;

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

    /// <summary>
    /// EN: Get list of frequency caps with optional ad filter.
    /// VI: Lấy danh sách frequency caps với bộ lọc ad tùy chọn.
    /// </summary>
    [HttpGet("caps")]
    [ProducesResponseType(typeof(List<FrequencyCapDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<List<FrequencyCapDto>>> GetFrequencyCaps([FromQuery] Guid? adId)
    {
        var query = _context.FrequencyCaps.AsQueryable();

        if (adId.HasValue)
            query = query.Where(fc => EF.Property<Guid>(fc, "_adId") == adId.Value);

        var caps = await query
            .Select(fc => new FrequencyCapDto
            {
                Id = fc.Id,
                AdId = EF.Property<Guid>(fc, "_adId"),
                MaxImpressionsPerUser = EF.Property<int>(fc, "_maxImpressionsPerUser"),
                Window = fc.Window.ToString()
            })
            .ToListAsync();

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

    /// <summary>
    /// EN: Get frequency cap by ID.
    /// VI: Lấy frequency cap theo ID.
    /// </summary>
    [HttpGet("caps/{id}")]
    [ProducesResponseType(typeof(FrequencyCapDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<FrequencyCapDto>> GetFrequencyCap(Guid id)
    {
        var cap = await _context.FrequencyCaps
            .Where(fc => fc.Id == id)
            .Select(fc => new FrequencyCapDto
            {
                Id = fc.Id,
                AdId = EF.Property<Guid>(fc, "_adId"),
                MaxImpressionsPerUser = EF.Property<int>(fc, "_maxImpressionsPerUser"),
                Window = fc.Window.ToString()
            })
            .FirstOrDefaultAsync();

        if (cap == null)
            return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Frequency cap not found" } });

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

    /// <summary>
    /// EN: Create a new frequency cap.
    /// VI: Tạo frequency cap mới.
    /// </summary>
    [HttpPost("caps")]
    [ProducesResponseType(typeof(FrequencyCapDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<FrequencyCapDto>> CreateFrequencyCap([FromBody] CreateFrequencyCapRequest request)
    {
        if (!Enum.TryParse<FrequencyWindow>(request.Window, out var window))
            return BadRequest(new { success = false, error = new { code = "BAD_REQUEST", message = "Invalid frequency window" } });

        var cap = new FrequencyCap(request.AdId, request.MaxImpressionsPerUser, window);
        
        _context.FrequencyCaps.Add(cap);
        await _context.SaveChangesAsync();

        var dto = new FrequencyCapDto
        {
            Id = cap.Id,
            AdId = request.AdId,
            MaxImpressionsPerUser = request.MaxImpressionsPerUser,
            Window = window.ToString()
        };

        _logger.LogInformation("Created frequency cap {Id} for Ad {AdId}", cap.Id, request.AdId);
        
        return CreatedAtAction(nameof(GetFrequencyCap), new { id = cap.Id }, new { success = true, data = dto });
    }

    /// <summary>
    /// EN: Delete a frequency cap.
    /// VI: Xóa frequency cap.
    /// </summary>
    [HttpDelete("caps/{id}")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> DeleteFrequencyCap(Guid id)
    {
        var cap = await _context.FrequencyCaps.FindAsync(id);
        
        if (cap == null)
            return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = "Frequency cap not found" } });

        _context.FrequencyCaps.Remove(cap);
        await _context.SaveChangesAsync();

        _logger.LogInformation("Deleted frequency cap {Id}", id);
        
        return NoContent();
    }
}

public record FrequencyCapDto
{
    public Guid Id { get; init; }
    public Guid AdId { get; init; }
    public int MaxImpressionsPerUser { get; init; }
    public string Window { get; init; } = string.Empty;
}

public record CreateFrequencyCapRequest
{
    public Guid AdId { get; init; }
    public int MaxImpressionsPerUser { get; init; }
    public string Window { get; init; } = "Day";
}
