using Zentral.API.Services; using Zentral.Domain.Entities; using Microsoft.AspNetCore.Mvc; namespace Zentral.API.Controllers; /// /// Controller per la gestione delle applicazioni e delle subscription /// [ApiController] [Route("api/[controller]")] public class AppsController : ControllerBase { private readonly AppService _appService; private readonly ILogger _logger; public AppsController(AppService appService, ILogger logger) { _appService = appService; _logger = logger; } /// /// Ottiene tutte le applicazioni disponibili con stato subscription /// [HttpGet] public async Task>> GetAllApps() { var apps = await _appService.GetAllAppsAsync(); return Ok(apps.Select(MapToDto).ToList()); } /// /// Ottiene solo le applicazioni attive (per costruzione menu) /// [HttpGet("active")] public async Task>> GetActiveApps() { var apps = await _appService.GetActiveAppsAsync(); return Ok(apps.Select(MapToDto).ToList()); } /// /// Ottiene un'applicazione specifica per codice /// [HttpGet("{code}")] public async Task> GetApp(string code) { var app = await _appService.GetAppByCodeAsync(code); if (app == null) return NotFound(new { message = $"Applicazione '{code}' non trovata" }); return Ok(MapToDto(app)); } /// /// Verifica se un'applicazione รจ abilitata /// [HttpGet("{code}/enabled")] public async Task> IsAppEnabled(string code) { var app = await _appService.GetAppByCodeAsync(code); if (app == null) return NotFound(new { message = $"Applicazione '{code}' non trovata" }); var isEnabled = await _appService.IsAppEnabledAsync(code); var hasValidSubscription = await _appService.HasValidSubscriptionAsync(code); return Ok(new AppStatusDto { Code = code, IsEnabled = isEnabled, HasValidSubscription = hasValidSubscription, IsCore = app.IsCore, DaysRemaining = app.Subscription?.GetDaysRemaining(), IsExpiringSoon = app.Subscription?.IsExpiringSoon() ?? false }); } /// /// Attiva un'applicazione /// [HttpPut("{code}/enable")] public async Task> EnableApp(string code, [FromBody] EnableAppRequest request) { try { var subscription = await _appService.EnableAppAsync( 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 }); } } /// /// Disattiva un'applicazione /// [HttpPut("{code}/disable")] public async Task DisableApp(string code) { try { await _appService.DisableAppAsync(code); return Ok(new { message = $"Applicazione '{code}' disattivata" }); } catch (ArgumentException ex) { return NotFound(new { message = ex.Message }); } catch (InvalidOperationException ex) { return BadRequest(new { message = ex.Message }); } } /// /// Ottiene tutte le subscription /// [HttpGet("subscriptions")] public async Task>> GetAllAppSubscriptions() { var subscriptions = await _appService.GetAllSubscriptionsAsync(); return Ok(subscriptions.Select(MapSubscriptionToDto).ToList()); } /// /// Aggiorna la subscription di un'applicazione /// [HttpPut("{code}/subscription")] public async Task> UpdateAppSubscription(string code, [FromBody] UpdateAppSubscriptionRequest request) { try { var subscription = await _appService.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 }); } } /// /// Rinnova la subscription di un'applicazione /// [HttpPost("{code}/subscription/renew")] public async Task> RenewAppSubscription(string code, [FromBody] RenewAppSubscriptionRequest? request = null) { try { var subscription = await _appService.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 }); } } /// /// Ottiene le applicazioni in scadenza /// [HttpGet("expiring")] public async Task>> GetExpiringApps([FromQuery] int daysThreshold = 30) { var apps = await _appService.GetExpiringAppsAsync(daysThreshold); return Ok(apps.Select(MapToDto).ToList()); } /// /// Inizializza le applicazioni di default (per setup iniziale) /// [HttpPost("seed")] public async Task SeedDefaultApps() { await _appService.SeedDefaultAppsAsync(); return Ok(new { message = "Applicazioni di default inizializzate" }); } /// /// Forza il controllo delle subscription scadute /// [HttpPost("check-expired")] public async Task CheckExpiredAppSubscriptions() { var count = await _appService.CheckExpiredSubscriptionsAsync(); return Ok(new { message = $"Controllate le subscription, {count} applicazioni disattivate per scadenza" }); } /// /// Invalida la cache delle applicazioni /// [HttpPost("invalidate-cache")] public ActionResult InvalidateAppsCache() { _appService.InvalidateCache(); return Ok(new { message = "Cache applicazioni invalidata" }); } #region Mapping private static AppDto MapToDto(App app) { return new AppDto { Id = app.Id, Code = app.Code, Name = app.Name, Description = app.Description, Icon = app.Icon, BasePrice = app.BasePrice, MonthlyPrice = app.GetMonthlyPrice(), MonthlyMultiplier = app.MonthlyMultiplier, SortOrder = app.SortOrder, IsCore = app.IsCore, Dependencies = app.GetDependencies().ToList(), RoutePath = app.RoutePath, IsAvailable = app.IsAvailable, IsEnabled = app.IsCore || ((app.Subscription?.IsEnabled ?? false) && (app.Subscription?.IsValid() ?? false)), Subscription = app.Subscription != null ? MapSubscriptionToDto(app.Subscription) : null }; } private static AppSubscriptionDto MapSubscriptionToDto(AppSubscription subscription) { return new AppSubscriptionDto { Id = subscription.Id, AppId = subscription.AppId, AppCode = subscription.App?.Code, AppName = subscription.App?.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 AppDto { 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 Dependencies { get; set; } = new(); public string? RoutePath { get; set; } public bool IsAvailable { get; set; } public bool IsEnabled { get; set; } public AppSubscriptionDto? Subscription { get; set; } } public class AppSubscriptionDto { public int Id { get; set; } public int AppId { get; set; } public string? AppCode { get; set; } public string? AppName { 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 AppStatusDto { 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 EnableAppRequest { 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 UpdateAppSubscriptionRequest { public SubscriptionType? SubscriptionType { get; set; } public DateTime? EndDate { get; set; } public bool? AutoRenew { get; set; } public string? Notes { get; set; } } public class RenewAppSubscriptionRequest { public decimal? PaidPrice { get; set; } } #endregion