using Microsoft.AspNetCore.Authorization;
using PowderCoating.Shared.Constants;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PowderCoating.Core.Entities;
using PowderCoating.Infrastructure.Data;
using System.Reflection;

namespace PowderCoating.Web.Controllers;

/// <summary>
/// SuperAdmin-only system health and runtime information page.
/// Aggregates application version, database connectivity, migration state,
/// seed history, user counts, and host environment details into a single view
/// to give platform operators a quick operational snapshot without needing
/// server or database console access.
/// </summary>
[Authorize(Policy = AppConstants.Policies.SuperAdminOnly)]
public class SystemInfoController : Controller
{
    private readonly ApplicationDbContext _dbContext;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IWebHostEnvironment _env;

    public SystemInfoController(
        ApplicationDbContext dbContext,
        UserManager<ApplicationUser> userManager,
        IWebHostEnvironment env)
    {
        _dbContext = dbContext;
        _userManager = userManager;
        _env = env;
    }

    /// <summary>
    /// Gathers and renders runtime system information into a
    /// <see cref="SystemInfoViewModel"/>.
    /// <para>
    /// Key design decisions:
    /// <list type="bullet">
    ///   <item>The informational version string (from
    ///     <see cref="AssemblyInformationalVersionAttribute"/>) is preferred over the
    ///     numeric version because it can include Git commit hashes or pre-release labels
    ///     set during CI builds.</item>
    ///   <item>Database connectivity is tested via <c>CanConnectAsync()</c> rather than
    ///     a raw query to keep the check lightweight and independent of schema state.</item>
    ///   <item>Applied migrations are listed (not pending) so the view can report the
    ///     last applied migration without needing write access to the migration history.</item>
    ///   <item><c>SeedData.LastSeedRun</c> is a static field updated by the seed service
    ///     each time seeding completes; it shows <c>null</c> if no seed has run since
    ///     the last application restart.</item>
    ///   <item>Server time is reported in both local and UTC to help operators diagnose
    ///     timezone-related scheduling issues.</item>
    /// </list>
    /// </para>
    /// </summary>
    public async Task<IActionResult> Index()
    {
        // App version from assembly
        var assembly = Assembly.GetEntryAssembly();
        var version = assembly?.GetName().Version?.ToString() ?? "Unknown";
        var infoVersion = assembly?
            .GetCustomAttribute<AssemblyInformationalVersionAttribute>()
            ?.InformationalVersion ?? version;

        // Database connectivity
        bool dbConnected;
        string dbStatus;
        string? lastMigration = null;
        int migrationCount = 0;
        try
        {
            dbConnected = await _dbContext.Database.CanConnectAsync();
            dbStatus = dbConnected ? "Connected" : "Unreachable";
            if (dbConnected)
            {
                var applied = await _dbContext.Database.GetAppliedMigrationsAsync();
                var migrations = applied.ToList();
                migrationCount = migrations.Count;
                lastMigration = migrations.LastOrDefault();
            }
        }
        catch (Exception ex)
        {
            dbConnected = false;
            dbStatus = $"Error: {ex.Message}";
        }

        // User counts
        var totalUsers = await _userManager.Users.CountAsync();
        var activeUsers = await _userManager.Users.CountAsync(u => u.IsActive);

        var vm = new SystemInfoViewModel
        {
            AppVersion = infoVersion,
            DatabaseConnected = dbConnected,
            DatabaseStatus = dbStatus,
            LastAppliedMigration = lastMigration,
            MigrationCount = migrationCount,
            LastSeedRun = SeedData.LastSeedRun,
            ServerTime = DateTime.Now,
            ServerTimeUtc = DateTime.UtcNow,
            ServerTimeZone = TimeZoneInfo.Local.DisplayName,
            ActiveUserCount = activeUsers,
            TotalUserCount = totalUsers,
            EnvironmentName = _env.EnvironmentName,
            MachineName = Environment.MachineName,
            OsDescription = System.Runtime.InteropServices.RuntimeInformation.OSDescription,
            RuntimeVersion = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription
        };

        return View(vm);
    }
}

public class SystemInfoViewModel
{
    public string AppVersion { get; set; } = string.Empty;
    public bool DatabaseConnected { get; set; }
    public string DatabaseStatus { get; set; } = string.Empty;
    public string? LastAppliedMigration { get; set; }
    public int MigrationCount { get; set; }
    public DateTime? LastSeedRun { get; set; }
    public DateTime ServerTime { get; set; }
    public DateTime ServerTimeUtc { get; set; }
    public string ServerTimeZone { get; set; } = string.Empty;
    public int ActiveUserCount { get; set; }
    public int TotalUserCount { get; set; }
    public string EnvironmentName { get; set; } = string.Empty;
    public string MachineName { get; set; } = string.Empty;
    public string OsDescription { get; set; } = string.Empty;
    public string RuntimeVersion { get; set; } = string.Empty;
}
