using Microsoft.AspNetCore.Authorization;
using PowderCoating.Shared.Constants;
using Microsoft.AspNetCore.Mvc;
using PowderCoating.Application.Interfaces;

namespace PowderCoating.Web.Controllers;

[Authorize(Policy = AppConstants.Policies.SuperAdminOnly)]
public class SeedDataController : Controller
{
    private readonly ISeedDataService _seedDataService;
    private readonly ILogger<SeedDataController> _logger;

    public SeedDataController(
        ISeedDataService seedDataService,
        ILogger<SeedDataController> logger)
    {
        _seedDataService = seedDataService;
        _logger = logger;
    }

    /// <summary>
    /// Displays the Seed Data management page with a list of all companies. Seeding is intentionally NOT automatic on startup — it must be triggered manually here by a SuperAdmin to avoid polluting production databases.
    /// </summary>
    public async Task<IActionResult> Index()
    {
        var companies = await _seedDataService.GetCompaniesAsync();
        return View(companies);
    }

    /// <summary>
    /// Triggers system-level seeding (global data such as SuperAdmin accounts and dashboard tips). Warnings are stored in TempData as a pipe-delimited string to survive the redirect; they display on the Index view after the POST-Redirect-GET cycle.
    /// </summary>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> SeedSystem()
    {
        try
        {
            var result = await _seedDataService.SeedSystemDataAsync();

            if (result.Success)
            {
                TempData["SuccessMessage"] = result.Message;
                TempData["SeedDetails"] = string.Join("|", result.Details);
                TempData["ItemsSeeded"] = result.ItemsSeeded;

                if (result.Warnings.Any())
                {
                    TempData["WarningMessage"] = $"{result.ItemsSkipped} item(s) were skipped";
                    TempData["SeedWarnings"] = string.Join("|", result.Warnings);
                }
            }
            else
            {
                TempData["ErrorMessage"] = result.Message;
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error seeding system data");
            TempData["ErrorMessage"] = $"An error occurred: {ex.Message}";
        }

        return RedirectToAction(nameof(Index));
    }

    /// <summary>
    /// Seeds demo data (customers, jobs, quotes, inventory, etc.) for a specific company. Warnings are capped at 30 entries in TempData to stay within the 4 KB browser cookie limit; any overflow is noted with a count and a pointer to the server logs.
    /// </summary>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> SeedCompany(int companyId)
    {
        try
        {
            var result = await _seedDataService.SeedCompanyDataAsync(companyId);

            if (result.Success)
            {
                TempData["SuccessMessage"] = result.Message;
                TempData["SeedDetails"] = string.Join("|", result.Details);
                TempData["ItemsSeeded"] = result.ItemsSeeded;

                if (result.Warnings.Any())
                {
                    TempData["WarningMessage"] = $"{result.ItemsSkipped} item(s) were skipped";
                    // Cap at 30 warnings to keep the TempData cookie under the 4 KB browser limit
                    var displayWarnings = result.Warnings.Take(30).ToList();
                    if (result.Warnings.Count > 30)
                        displayWarnings.Add($"… and {result.Warnings.Count - 30} more (see logs)");
                    TempData["SeedWarnings"] = string.Join("|", displayWarnings);
                }
            }
            else
            {
                TempData["ErrorMessage"] = result.Message;
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error seeding company data");
            TempData["ErrorMessage"] = $"An error occurred: {ex.Message}";
        }

        return RedirectToAction(nameof(Index));
    }

    /// <summary>
    /// Wipes all seeded data from the DEMO company and immediately re-seeds it with fresh demo data
    /// so all dates are current. Intended for tutorial recording resets — one click returns the demo
    /// company to a clean, realistic state without touching any other tenant.
    /// </summary>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> ResetDemoCompany()
    {
        try
        {
            var companies = await _seedDataService.GetCompaniesAsync();
            var demo = companies.FirstOrDefault(c => c.CompanyCode == "DEMO");
            if (demo == null)
            {
                TempData["ErrorMessage"] = "Demo company (code: DEMO) not found. Run Seed System Data first.";
                return RedirectToAction(nameof(Index));
            }

            // Full wipe — ForceRemoveAll bypasses fingerprint matching so stale seed data from
            // previous code versions (different emails, renamed SKUs, etc.) is always cleared.
            var removeOptions = new RemoveSeedDataOptions
            {
                Customers      = true,
                InventoryItems = true,
                Equipment      = true,
                Catalog        = true,
                PricingTiers   = true,
                OperatingCosts = true,
                Bills          = true,
                Expenses       = true,
                Workers        = false,  // workers stay static — never deleted on reset
                Vendors        = true,
                NamedOvens     = true,
                Appointments   = true,
                ForceRemoveAll = true,
            };

            var removeResult = await _seedDataService.RemoveSeedDataAsync(demo.Id, removeOptions);
            if (!removeResult.Success)
            {
                TempData["ErrorMessage"] = $"Wipe step failed: {removeResult.Message}";
                return RedirectToAction(nameof(Index));
            }

            // Re-seed with today's dates
            var seedResult = await _seedDataService.SeedCompanyDataAsync(demo.Id);

            if (seedResult.Success)
            {
                TempData["SuccessMessage"] = $"Demo company reset complete. {seedResult.ItemsSeeded} records re-seeded with today's dates.";
                TempData["SeedDetails"]    = string.Join("|", seedResult.Details);
                TempData["ItemsSeeded"]    = seedResult.ItemsSeeded;

                if (seedResult.Warnings.Any())
                {
                    TempData["WarningMessage"] = $"{seedResult.ItemsSkipped} item(s) were skipped";
                    var displayWarnings = seedResult.Warnings.Take(30).ToList();
                    if (seedResult.Warnings.Count > 30)
                        displayWarnings.Add($"... and {seedResult.Warnings.Count - 30} more (see logs)");
                    TempData["SeedWarnings"] = string.Join("|", displayWarnings);
                }
            }
            else
            {
                TempData["ErrorMessage"] = $"Wipe succeeded but re-seed failed: {seedResult.Message}";
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error resetting demo company");
            TempData["ErrorMessage"] = $"An error occurred during demo reset: {ex.Message}";
        }

        return RedirectToAction(nameof(Index));
    }

    /// <summary>
    /// Removes previously seeded demo data from a company according to the supplied options (e.g., jobs only, or all data). Used during QA/demo resets to return a company to a clean state without a full database drop.
    /// </summary>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> RemoveSeedData(int companyId, RemoveSeedDataOptions options)
    {
        try
        {
            var result = await _seedDataService.RemoveSeedDataAsync(companyId, options);

            if (result.Success)
            {
                TempData["SuccessMessage"] = result.Message;
                TempData["SeedDetails"] = string.Join("|", result.Details);
                TempData["ItemsSeeded"] = result.ItemsSeeded;
            }
            else
            {
                TempData["ErrorMessage"] = result.Message;
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error removing seed data for company {CompanyId}", companyId);
            TempData["ErrorMessage"] = $"An error occurred: {ex.Message}";
        }

        return RedirectToAction(nameof(Index));
    }
}
