using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PowderCoating.Application.DTOs.Subscription;
using PowderCoating.Core.Interfaces;
using PowderCoating.Shared.Constants;

namespace PowderCoating.Web.Controllers;

/// <summary>
/// SuperAdmin-only interface for managing subscription plan configurations
/// (limits, pricing, feature flags, and Stripe price IDs).  Changes here
/// affect every new tenant assignment of the plan and any quota checks that
/// read plan limits at runtime.  Plan <c>DisplayName</c> and <c>Plan</c> enum
/// value are intentionally not editable here to prevent breaking existing company
/// subscription records that reference them by integer value.
/// </summary>
[Authorize(Policy = AppConstants.Policies.SuperAdminOnly)]
public class PlatformSubscriptionController : Controller
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<PlatformSubscriptionController> _logger;

    public PlatformSubscriptionController(IUnitOfWork unitOfWork, ILogger<PlatformSubscriptionController> logger)
    {
        _unitOfWork = unitOfWork;
        _logger = logger;
    }

    /// <summary>
    /// Lists all subscription plan configurations ordered by display sort order.
    /// Uses <c>ignoreQueryFilters: true</c> because plan configs carry
    /// <c>CompanyId = 0</c> and are otherwise hidden by the multi-tenancy filter.
    /// Projects to <see cref="SubscriptionPlanConfigDto"/> to avoid exposing the
    /// full entity (including internal Stripe secrets) to the view layer.
    /// </summary>
    [HttpGet]
    public async Task<IActionResult> Index()
    {
        var configs = (await _unitOfWork.SubscriptionPlanConfigs.GetAllAsync(ignoreQueryFilters: true))
            .OrderBy(c => c.SortOrder)
            .ToList();

        var dtos = configs.Select(c => new SubscriptionPlanConfigDto
        {
            Id = c.Id,
            Plan = c.Plan,
            DisplayName = c.DisplayName,
            Description = c.Description,
            MaxUsers = c.MaxUsers,
            MaxActiveJobs = c.MaxActiveJobs,
            MaxCustomers = c.MaxCustomers,
            MaxQuotes = c.MaxQuotes,
            MaxCatalogItems = c.MaxCatalogItems,
            MaxJobPhotos = c.MaxJobPhotos,
            MaxQuotePhotos = c.MaxQuotePhotos,
            MaxAiPhotoQuotesPerMonth = c.MaxAiPhotoQuotesPerMonth,
            MonthlyPrice = c.MonthlyPrice,
            AnnualPrice = c.AnnualPrice,
            StripePriceIdMonthly = c.StripePriceIdMonthly,
            StripePriceIdAnnual = c.StripePriceIdAnnual,
            AllowOnlinePayments = c.AllowOnlinePayments,
            AllowAccounting = c.AllowAccounting,
            AllowAiPhotoQuotes = c.AllowAiPhotoQuotes,
            AllowAiInventoryAssist = c.AllowAiInventoryAssist,
            AllowAiCatalogPriceCheck = c.AllowAiCatalogPriceCheck,
            AllowSms = c.AllowSms,
            AllowCustomFormulas = c.AllowCustomFormulas,
            IsActive = c.IsActive,
            SortOrder = c.SortOrder
        }).ToList();

        return View(dtos);
    }

    /// <summary>
    /// Returns the Edit form for a plan config, loaded into an
    /// <see cref="UpdateSubscriptionPlanConfigDto"/> to prevent over-posting of
    /// immutable fields such as <c>Plan</c>, <c>DisplayName</c>, and <c>SortOrder</c>.
    /// The plan display name is placed in ViewBag for the page heading.
    /// </summary>
    [HttpGet]
    public async Task<IActionResult> Edit(int id)
    {
        var config = await _unitOfWork.SubscriptionPlanConfigs.GetByIdAsync(id, ignoreQueryFilters: true);
        if (config == null) return NotFound();

        var dto = new UpdateSubscriptionPlanConfigDto
        {
            Id = config.Id,
            Description = config.Description,
            MaxUsers = config.MaxUsers,
            MaxActiveJobs = config.MaxActiveJobs,
            MaxCustomers = config.MaxCustomers,
            MaxQuotes = config.MaxQuotes,
            MaxCatalogItems = config.MaxCatalogItems,
            MaxJobPhotos = config.MaxJobPhotos,
            MaxQuotePhotos = config.MaxQuotePhotos,
            MaxAiPhotoQuotesPerMonth = config.MaxAiPhotoQuotesPerMonth,
            MonthlyPrice = config.MonthlyPrice,
            AnnualPrice = config.AnnualPrice,
            StripePriceIdMonthly = config.StripePriceIdMonthly,
            StripePriceIdAnnual = config.StripePriceIdAnnual,
            AllowOnlinePayments = config.AllowOnlinePayments,
            AllowAccounting = config.AllowAccounting,
            AllowAiPhotoQuotes = config.AllowAiPhotoQuotes,
            AllowAiInventoryAssist = config.AllowAiInventoryAssist,
            AllowAiCatalogPriceCheck = config.AllowAiCatalogPriceCheck,
            AllowSms = config.AllowSms,
            AllowCustomFormulas = config.AllowCustomFormulas,
            IsActive = config.IsActive
        };

        ViewBag.PlanName = config.DisplayName;
        return View(dto);
    }

    /// <summary>
    /// Applies the updated plan configuration values and saves.  Uses explicit field
    /// mapping from <paramref name="dto"/> to the tracked entity so that immutable
    /// identity fields (<c>Plan</c>, <c>DisplayName</c>, <c>SortOrder</c>) are never
    /// overwritten.  Logs the change at Information level for the audit trail.
    /// </summary>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(int id, UpdateSubscriptionPlanConfigDto dto)
    {
        if (!ModelState.IsValid)
        {
            var configForView = await _unitOfWork.SubscriptionPlanConfigs.GetByIdAsync(id, ignoreQueryFilters: true);
            ViewBag.PlanName = configForView?.DisplayName ?? "Unknown";
            return View(dto);
        }

        var config = await _unitOfWork.SubscriptionPlanConfigs.GetByIdAsync(id, ignoreQueryFilters: true);
        if (config == null) return NotFound();

        config.Description = dto.Description;
        config.MaxUsers = dto.MaxUsers;
        config.MaxActiveJobs = dto.MaxActiveJobs;
        config.MaxCustomers = dto.MaxCustomers;
        config.MaxQuotes = dto.MaxQuotes;
        config.MaxCatalogItems = dto.MaxCatalogItems;
        config.MaxJobPhotos = dto.MaxJobPhotos;
        config.MaxQuotePhotos = dto.MaxQuotePhotos;
        config.MaxAiPhotoQuotesPerMonth = dto.MaxAiPhotoQuotesPerMonth;
        config.MonthlyPrice = dto.MonthlyPrice;
        config.AnnualPrice = dto.AnnualPrice;
        config.StripePriceIdMonthly = dto.StripePriceIdMonthly;
        config.StripePriceIdAnnual = dto.StripePriceIdAnnual;
        config.AllowOnlinePayments = dto.AllowOnlinePayments;
        config.AllowAccounting = dto.AllowAccounting;
        config.AllowAiPhotoQuotes = dto.AllowAiPhotoQuotes;
        config.AllowAiInventoryAssist = dto.AllowAiInventoryAssist;
        config.AllowAiCatalogPriceCheck = dto.AllowAiCatalogPriceCheck;
        config.AllowSms = dto.AllowSms;
        config.AllowCustomFormulas = dto.AllowCustomFormulas;
        config.IsActive = dto.IsActive;

        await _unitOfWork.SubscriptionPlanConfigs.UpdateAsync(config);
        await _unitOfWork.CompleteAsync();

        _logger.LogInformation("SuperAdmin updated subscription plan config: {Plan}", config.DisplayName);
        TempData["Success"] = $"{config.DisplayName} plan configuration updated successfully.";
        return RedirectToAction(nameof(Index));
    }
}
