using NexusShell.Agent;
using NexusShell.Agent.Models;
using NexusShell.Models;

namespace NexusShell.Services.ControlCenter;

/// <summary>
/// Foundation service for Nexus Control Center — aggregates local identity + agent inventory,
/// optionally merges remote platform dashboard when ControlCenter:BaseUrl is configured.
/// </summary>
public sealed class NexusControlCenterService : INexusControlCenterPresencePoller
{
    private readonly Services.Identity.NexusIdentityService _identity;
    private readonly NexusInventoryService _inventory;
    private readonly NexusHealthService _health;
    private readonly NexusControlCenterApiClient? _apiClient;

    public NexusControlCenterService(
        Services.Identity.NexusIdentityService identity,
        NexusInventoryService inventory,
        NexusHealthService health,
        NexusControlCenterApiClient? apiClient = null)
    {
        _identity = identity;
        _inventory = inventory;
        _health = health;
        _apiClient = apiClient;
    }

    public bool IsRemoteConfigured => _apiClient?.IsConfigured == true;

    public TimeSpan PollInterval => TimeSpan.FromSeconds(45);

    public async Task<NexusControlCenterPresenceSummary?> PollAsync(CancellationToken ct = default) =>
        await FetchPresenceSummaryAsync(ct);

    public NexusControlCenterSnapshot BuildSnapshot() =>
        BuildSnapshotAsync().GetAwaiter().GetResult();

    public async Task<NexusControlCenterSnapshot> BuildSnapshotAsync(CancellationToken ct = default)
    {
        var identity = _identity.GetSnapshot();
        var org = identity.Organization;
        var user = identity.User;
        var device = identity.Device;
        var trust = identity.Trust;

        NexusControlCenterOrganization? ccOrg = org is null
            ? null
            : new NexusControlCenterOrganization
            {
                Id = org.Id,
                Name = org.Name,
                UserCount = user is null ? 0 : 1,
                DeviceCount = device is null ? 0 : 1,
            };

        NexusControlCenterUser? ccUser = user is null
            ? null
            : new NexusControlCenterUser
            {
                Id = user.Id,
                DisplayName = user.DisplayName,
                OrganizationId = user.OrganizationId,
            };

        NexusControlCenterDevice? ccDevice = device is null
            ? null
            : new NexusControlCenterDevice
            {
                DeviceId = device.DeviceId,
                FriendlyName = device.FriendlyName,
                Owner = device.Owner,
                Organization = device.Organization,
                TrustStatus = trust?.Status ?? NexusTrustStatus.Unknown,
                EnrollmentStatus = device.Status,
                LastSeen = device.LastSeen,
            };

        NexusControlCenterDeviceHealth? ccHealth = null;
        NexusControlCenterDeviceInventory? ccInventory = null;

        if (device is not null && !string.IsNullOrWhiteSpace(device.DeviceId))
        {
            var healthSnap = _health.CaptureSnapshot();
            ccHealth = new NexusControlCenterDeviceHealth
            {
                DeviceId = device.DeviceId,
                Overall = healthSnap.Overall,
                HealthPercent = healthSnap.HealthPercent,
                CapturedAtUtc = healthSnap.CapturedAtUtc,
            };

            var inv = _inventory.CaptureSnapshot();
            ccInventory = new NexusControlCenterDeviceInventory
            {
                DeviceId = device.DeviceId,
                Cpu = inv.Cpu,
                Ram = inv.Ram,
                Storage = inv.Storage,
                Gpu = inv.Gpu,
                DisplayCount = inv.Displays.Count,
                PrinterCount = inv.Printers.Count,
                UsbDeviceCount = inv.UsbDevices.Count,
            };
        }

        NexusControlCenterRemoteDashboard? remote = null;
        if (_apiClient?.IsConfigured == true)
        {
            var dashboard = await _apiClient.TryFetchDashboardAsync(ct);
            if (dashboard is not null)
            {
                remote = MapRemoteDashboard(dashboard);
            }
        }

        return new NexusControlCenterSnapshot
        {
            Organization = ccOrg,
            CurrentUser = ccUser,
            CurrentDevice = ccDevice,
            Health = ccHealth,
            Inventory = ccInventory,
            Policies = remote?.Policies ?? GetPlaceholderPolicies(),
            RemoteDashboard = remote,
        };
    }

    public async Task<NexusControlCenterPresenceSummary?> FetchPresenceSummaryAsync(CancellationToken ct = default)
    {
        if (_apiClient?.IsConfigured == true)
        {
            var presence = await _apiClient.TryFetchPresenceAsync(ct);
            if (presence is not null)
            {
                return MapRemotePresence(presence, "remote");
            }

            var status = await _apiClient.TryFetchDeviceStatusAsync(ct);
            if (status is not null)
            {
                return MapRemotePresence(status, "remote");
            }
        }

        return BuildLocalPresenceSummary();
    }

    private NexusControlCenterPresenceSummary BuildLocalPresenceSummary()
    {
        var snapshot = _identity.GetSnapshot();
        var device = snapshot.Device;
        var user = snapshot.User;
        var org = snapshot.Organization;
        var health = _health.CaptureOverallLabel();

        if (device is null)
        {
            return new NexusControlCenterPresenceSummary
            {
                GeneratedAtUtc = DateTime.UtcNow,
                Source = "local",
            };
        }

        var row = new NexusControlCenterDevicePresenceRow
        {
            DeviceId = device.DeviceId,
            FriendlyName = device.FriendlyName,
            Owner = user?.DisplayName ?? device.Owner,
            Organization = org?.Name ?? device.Organization,
            Online = true,
            Health = health,
            AgentVersion = device.AgentVersion,
            ShellVersion = device.ShellVersion,
            LastSeen = device.LastSeen ?? DateTimeOffset.UtcNow,
        };

        return new NexusControlCenterPresenceSummary
        {
            GeneratedAtUtc = DateTime.UtcNow,
            OfflineThresholdSeconds = 90,
            OnlineCount = 1,
            OfflineCount = 0,
            WarningCount = health == "Warning" ? 1 : 0,
            CriticalCount = health == "Critical" ? 1 : 0,
            Devices = [row],
            Source = "local",
        };
    }

    private static NexusControlCenterPresenceSummary MapRemotePresence(
        NexusControlCenterPresenceApiResponse response,
        string source) =>
        new()
        {
            GeneratedAtUtc = response.GeneratedAtUtc,
            OfflineThresholdSeconds = response.OfflineThresholdSeconds,
            OnlineCount = response.OnlineCount,
            OfflineCount = response.OfflineCount,
            WarningCount = response.WarningCount,
            CriticalCount = response.CriticalCount,
            Source = source,
            Devices = response.Devices.Select(d => new NexusControlCenterDevicePresenceRow
            {
                DeviceId = d.DeviceId,
                FriendlyName = d.FriendlyName,
                Owner = d.Owner,
                Organization = d.OrganizationName,
                Online = d.Online,
                Health = d.HealthStatus,
                AgentVersion = d.AgentVersion,
                ShellVersion = d.ShellVersion,
                LastSeen = d.LastSeenUtc.HasValue ? new DateTimeOffset(d.LastSeenUtc.Value, TimeSpan.Zero) : null,
            }).ToList(),
        };

    private static NexusControlCenterPresenceSummary MapRemotePresence(
        NexusControlCenterDeviceStatusApiResponse response,
        string source) =>
        MapRemotePresence(new NexusControlCenterPresenceApiResponse
        {
            GeneratedAtUtc = response.GeneratedAtUtc,
            OfflineThresholdSeconds = response.OfflineThresholdSeconds,
            OnlineCount = response.OnlineCount,
            OfflineCount = response.OfflineCount,
            WarningCount = response.WarningCount,
            CriticalCount = response.CriticalCount,
            Devices = response.Devices,
        }, source);

    private static NexusControlCenterRemoteDashboard MapRemoteDashboard(NexusControlCenterDashboard dashboard) =>
        new()
        {
            GeneratedAtUtc = dashboard.GeneratedAtUtc,
            OrganizationCount = dashboard.OrganizationCount,
            DeviceCount = dashboard.DeviceCount,
            PendingEnrollmentCount = dashboard.PendingEnrollmentCount,
            TrustSummary = dashboard.TrustSummary is null
                ? null
                : new NexusControlCenterTrustSummary
                {
                    Trusted = dashboard.TrustSummary.Trusted,
                    Pending = dashboard.TrustSummary.Pending,
                    Blocked = dashboard.TrustSummary.Blocked,
                    Unknown = dashboard.TrustSummary.Unknown,
                },
            Organizations = dashboard.Organizations
                .Select(o => new NexusControlCenterOrganization
                {
                    Id = o.Id,
                    Name = o.Name,
                    UserCount = o.UserCount,
                    DeviceCount = o.DeviceCount,
                })
                .ToList(),
            Policies = dashboard.Policies
                .Select(p => new NexusControlCenterPolicy
                {
                    Id = p.Id,
                    Name = p.Name,
                    Scope = p.Scope,
                    IsEnabled = true,
                    Summary = p.Summary,
                })
                .ToList(),
            Source = "remote",
        };

    private static IReadOnlyList<NexusControlCenterPolicy> GetPlaceholderPolicies() =>
    [
        new NexusControlCenterPolicy
        {
            Id = "policy-trust-local",
            Name = "Device Trust (local POC)",
            Scope = "device",
            IsEnabled = true,
            Summary = "Lokal tillidsmodel — Trusted, Pending, Blocked, Unknown.",
        },
    ];
}
