using Apollinare.API.Services;
using Apollinare.Domain.Entities;
using Microsoft.AspNetCore.Mvc;

namespace Apollinare.API.Controllers;

/// <summary>
/// Controller per la gestione dei moduli applicativi e delle subscription
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ModulesController : ControllerBase
{
    private readonly ModuleService _moduleService;
    private readonly ILogger<ModulesController> _logger;

    public ModulesController(ModuleService moduleService, ILogger<ModulesController> logger)
    {
        _moduleService = moduleService;
        _logger = logger;
    }

    /// <summary>
    /// Ottiene tutti i moduli disponibili con stato subscription
    /// </summary>
    [HttpGet]
    public async Task<ActionResult<List<ModuleDto>>> GetAllModules()
    {
        var modules = await _moduleService.GetAllModulesAsync();
        return Ok(modules.Select(MapToDto).ToList());
    }

    /// <summary>
    /// Ottiene solo i moduli attivi (per costruzione menu)
    /// </summary>
    [HttpGet("active")]
    public async Task<ActionResult<List<ModuleDto>>> GetActiveModules()
    {
        var modules = await _moduleService.GetActiveModulesAsync();
        return Ok(modules.Select(MapToDto).ToList());
    }

    /// <summary>
    /// Ottiene un modulo specifico per codice
    /// </summary>
    [HttpGet("{code}")]
    public async Task<ActionResult<ModuleDto>> GetModule(string code)
    {
        var module = await _moduleService.GetModuleByCodeAsync(code);
        if (module == null)
            return NotFound(new { message = $"Modulo '{code}' non trovato" });

        return Ok(MapToDto(module));
    }

    /// <summary>
    /// Verifica se un modulo è abilitato
    /// </summary>
    [HttpGet("{code}/enabled")]
    public async Task<ActionResult<ModuleStatusDto>> IsModuleEnabled(string code)
    {
        var module = await _moduleService.GetModuleByCodeAsync(code);
        if (module == null)
            return NotFound(new { message = $"Modulo '{code}' non trovato" });

        var isEnabled = await _moduleService.IsModuleEnabledAsync(code);
        var hasValidSubscription = await _moduleService.HasValidSubscriptionAsync(code);

        return Ok(new ModuleStatusDto
        {
            Code = code,
            IsEnabled = isEnabled,
            HasValidSubscription = hasValidSubscription,
            IsCore = module.IsCore,
            DaysRemaining = module.Subscription?.GetDaysRemaining(),
            IsExpiringSoon = module.Subscription?.IsExpiringSoon() ?? false
        });
    }

    /// <summary>
    /// Attiva un modulo
    /// </summary>
    [HttpPut("{code}/enable")]
    public async Task<ActionResult<SubscriptionDto>> EnableModule(string code, [FromBody] EnableModuleRequest request)
    {
        try
        {
            var subscription = await _moduleService.EnableModuleAsync(
                code,
                request.SubscriptionType,
                request.StartDate,
                request.EndDate,
                request.AutoRenew,
                request.PaidPrice,
                request.Notes);

            return Ok(MapSubscriptionToDto(subscription));
        }
        catch (ArgumentException ex)
        {
            return NotFound(new { message = ex.Message });
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// Disattiva un modulo
    /// </summary>
    [HttpPut("{code}/disable")]
    public async Task<ActionResult> DisableModule(string code)
    {
        try
        {
            await _moduleService.DisableModuleAsync(code);
            return Ok(new { message = $"Modulo '{code}' disattivato" });
        }
        catch (ArgumentException ex)
        {
            return NotFound(new { message = ex.Message });
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// Ottiene tutte le subscription
    /// </summary>
    [HttpGet("subscriptions")]
    public async Task<ActionResult<List<SubscriptionDto>>> GetAllSubscriptions()
    {
        var subscriptions = await _moduleService.GetAllSubscriptionsAsync();
        return Ok(subscriptions.Select(MapSubscriptionToDto).ToList());
    }

    /// <summary>
    /// Aggiorna la subscription di un modulo
    /// </summary>
    [HttpPut("{code}/subscription")]
    public async Task<ActionResult<SubscriptionDto>> UpdateSubscription(string code, [FromBody] UpdateSubscriptionRequest request)
    {
        try
        {
            var subscription = await _moduleService.UpdateSubscriptionAsync(
                code,
                request.SubscriptionType,
                request.EndDate,
                request.AutoRenew,
                request.Notes);

            return Ok(MapSubscriptionToDto(subscription));
        }
        catch (ArgumentException ex)
        {
            return NotFound(new { message = ex.Message });
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// Rinnova la subscription di un modulo
    /// </summary>
    [HttpPost("{code}/subscription/renew")]
    public async Task<ActionResult<SubscriptionDto>> RenewSubscription(string code, [FromBody] RenewSubscriptionRequest? request = null)
    {
        try
        {
            var subscription = await _moduleService.RenewSubscriptionAsync(code, request?.PaidPrice);
            return Ok(MapSubscriptionToDto(subscription));
        }
        catch (ArgumentException ex)
        {
            return NotFound(new { message = ex.Message });
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// Ottiene i moduli in scadenza
    /// </summary>
    [HttpGet("expiring")]
    public async Task<ActionResult<List<ModuleDto>>> GetExpiringModules([FromQuery] int daysThreshold = 30)
    {
        var modules = await _moduleService.GetExpiringModulesAsync(daysThreshold);
        return Ok(modules.Select(MapToDto).ToList());
    }

    /// <summary>
    /// Inizializza i moduli di default (per setup iniziale)
    /// </summary>
    [HttpPost("seed")]
    public async Task<ActionResult> SeedDefaultModules()
    {
        await _moduleService.SeedDefaultModulesAsync();
        return Ok(new { message = "Moduli di default inizializzati" });
    }

    /// <summary>
    /// Forza il controllo delle subscription scadute
    /// </summary>
    [HttpPost("check-expired")]
    public async Task<ActionResult> CheckExpiredSubscriptions()
    {
        var count = await _moduleService.CheckExpiredSubscriptionsAsync();
        return Ok(new { message = $"Controllate le subscription, {count} moduli disattivati per scadenza" });
    }

    /// <summary>
    /// Invalida la cache dei moduli
    /// </summary>
    [HttpPost("invalidate-cache")]
    public ActionResult InvalidateCache()
    {
        _moduleService.InvalidateCache();
        return Ok(new { message = "Cache moduli invalidata" });
    }

    #region Mapping

    private static ModuleDto MapToDto(AppModule module)
    {
        return new ModuleDto
        {
            Id = module.Id,
            Code = module.Code,
            Name = module.Name,
            Description = module.Description,
            Icon = module.Icon,
            BasePrice = module.BasePrice,
            MonthlyPrice = module.GetMonthlyPrice(),
            MonthlyMultiplier = module.MonthlyMultiplier,
            SortOrder = module.SortOrder,
            IsCore = module.IsCore,
            Dependencies = module.GetDependencies().ToList(),
            RoutePath = module.RoutePath,
            IsAvailable = module.IsAvailable,
            IsEnabled = module.IsCore || (module.Subscription?.IsValid() ?? false),
            Subscription = module.Subscription != null ? MapSubscriptionToDto(module.Subscription) : null
        };
    }

    private static SubscriptionDto MapSubscriptionToDto(ModuleSubscription subscription)
    {
        return new SubscriptionDto
        {
            Id = subscription.Id,
            ModuleId = subscription.ModuleId,
            ModuleCode = subscription.Module?.Code,
            ModuleName = subscription.Module?.Name,
            IsEnabled = subscription.IsEnabled,
            SubscriptionType = subscription.SubscriptionType,
            SubscriptionTypeName = subscription.SubscriptionType.ToString(),
            StartDate = subscription.StartDate,
            EndDate = subscription.EndDate,
            AutoRenew = subscription.AutoRenew,
            Notes = subscription.Notes,
            LastRenewalDate = subscription.LastRenewalDate,
            PaidPrice = subscription.PaidPrice,
            IsValid = subscription.IsValid(),
            DaysRemaining = subscription.GetDaysRemaining(),
            IsExpiringSoon = subscription.IsExpiringSoon()
        };
    }

    #endregion
}

#region DTOs

public class ModuleDto
{
    public int Id { get; set; }
    public string Code { get; set; } = string.Empty;
    public string Name { get; set; } = string.Empty;
    public string? Description { get; set; }
    public string? Icon { get; set; }
    public decimal BasePrice { get; set; }
    public decimal MonthlyPrice { get; set; }
    public decimal MonthlyMultiplier { get; set; }
    public int SortOrder { get; set; }
    public bool IsCore { get; set; }
    public List<string> Dependencies { get; set; } = new();
    public string? RoutePath { get; set; }
    public bool IsAvailable { get; set; }
    public bool IsEnabled { get; set; }
    public SubscriptionDto? Subscription { get; set; }
}

public class SubscriptionDto
{
    public int Id { get; set; }
    public int ModuleId { get; set; }
    public string? ModuleCode { get; set; }
    public string? ModuleName { get; set; }
    public bool IsEnabled { get; set; }
    public SubscriptionType SubscriptionType { get; set; }
    public string SubscriptionTypeName { get; set; } = string.Empty;
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public bool AutoRenew { get; set; }
    public string? Notes { get; set; }
    public DateTime? LastRenewalDate { get; set; }
    public decimal? PaidPrice { get; set; }
    public bool IsValid { get; set; }
    public int? DaysRemaining { get; set; }
    public bool IsExpiringSoon { get; set; }
}

public class ModuleStatusDto
{
    public string Code { get; set; } = string.Empty;
    public bool IsEnabled { get; set; }
    public bool HasValidSubscription { get; set; }
    public bool IsCore { get; set; }
    public int? DaysRemaining { get; set; }
    public bool IsExpiringSoon { get; set; }
}

public class EnableModuleRequest
{
    public SubscriptionType SubscriptionType { get; set; } = SubscriptionType.Annual;
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public bool AutoRenew { get; set; }
    public decimal? PaidPrice { get; set; }
    public string? Notes { get; set; }
}

public class UpdateSubscriptionRequest
{
    public SubscriptionType? SubscriptionType { get; set; }
    public DateTime? EndDate { get; set; }
    public bool? AutoRenew { get; set; }
    public string? Notes { get; set; }
}

public class RenewSubscriptionRequest
{
    public decimal? PaidPrice { get; set; }
}

#endregion
