using NexusShell.Agent.Models;
using NexusShell.Models;
using NexusShell.Services.Identity;
using NexusShell.Services.Policy;

namespace NexusShell.Agent;

public sealed class NexusAgentRuntimeState
{
    private readonly object _gate = new();
    private NexusAgentInventoryResponse? _inventory;
    private NexusAgentHealthResponse? _health;
    private readonly NexusIdentityService? _identity;

    public NexusAgentConfig Config { get; }
    public string ShellVersion { get; }

    public NexusAgentRuntimeState(NexusAgentConfig config, string shellVersion, NexusIdentityService? identity = null)
    {
        Config = config;
        ShellVersion = shellVersion;
        _identity = identity;
    }
    public void UpdateInventory(NexusAgentInventoryResponse snapshot)
    {
        lock (_gate)
        {
            _inventory = snapshot;
        }
    }

    public void UpdateHealth(NexusAgentHealthResponse snapshot)
    {
        lock (_gate)
        {
            _health = snapshot;
        }
    }

    public NexusAgentStatusResponse GetStatus()
    {
        lock (_gate)
        {
            return new NexusAgentStatusResponse
            {
                Connected = true,
                AgentVersion = NexusAgentConfig.AgentVersion,
                ShellVersion = ShellVersion,
                LastHeartbeatUtc = Config.LastHeartbeatUtc,
                LocalApiUrl = Config.LocalApiUrl,
            };
        }
    }

    public NexusAgentDeviceResponse GetDevice()
    {
        lock (_gate)
        {
            var name = _inventory?.ComputerName ?? Environment.MachineName;
            return new NexusAgentDeviceResponse
            {
                DeviceId = Config.DeviceId,
                IsRegistered = Config.IsRegistered,
                RegisteredAtUtc = Config.RegisteredAtUtc,
                BackendUrl = Config.BackendUrl,
                ComputerName = name,
            };
        }
    }

    public NexusAgentInventoryResponse GetInventory(NexusInventoryService inventory)
    {
        lock (_gate)
        {
            if (_inventory is not null && DateTimeOffset.UtcNow - _inventory.CapturedAtUtc < TimeSpan.FromSeconds(5))
            {
                return _inventory;
            }
        }

        var snapshot = inventory.CaptureSnapshot();
        UpdateInventory(snapshot);
        return snapshot;
    }

    public NexusAgentHealthResponse GetHealth(NexusHealthService health)
    {
        lock (_gate)
        {
            if (_health is not null && DateTimeOffset.UtcNow - _health.CapturedAtUtc < TimeSpan.FromSeconds(2))
            {
                return _health;
            }
        }

        var snapshot = health.CaptureSnapshot();
        UpdateHealth(snapshot);
        return snapshot;
    }

    public NexusAgentIdentityResponse GetIdentity()
    {
        var snapshot = _identity?.GetSnapshot();
        var device = snapshot?.Device;
        var trust = snapshot?.Trust;
        var user = snapshot?.User;
        var org = snapshot?.Organization;

        return new NexusAgentIdentityResponse
        {
            DeviceId = device?.DeviceId ?? Config.DeviceId,
            User = user?.DisplayName ?? "—",
            Organization = org?.Name ?? device?.Organization ?? "—",
            TrustStatus = trust?.Status.ToString() ?? NexusTrustStatus.Unknown.ToString(),
            EnrollmentStatus = device?.Status.ToString() ?? NexusDeviceEnrollmentStatus.Unknown.ToString(),
            EnrollmentDate = device?.EnrollmentDate,
            LastSeen = device?.LastSeen,
            IsEnrolled = snapshot?.IsEnrolled ?? false,
        };
    }

    public NexusAgentDeviceProfileResponse GetDeviceProfile(NexusInventoryService inventory, NexusHealthService health)
    {
        var snapshot = _identity?.GetSnapshot();
        var device = snapshot?.Device;
        var inv = GetInventory(inventory);
        var hel = GetHealth(health);

        return new NexusAgentDeviceProfileResponse
        {
            DeviceId = device?.DeviceId ?? Config.DeviceId,
            ComputerName = device?.ComputerName ?? inv.ComputerName,
            FriendlyName = device?.FriendlyName ?? inv.ComputerName,
            Owner = device?.Owner ?? "—",
            Organization = device?.Organization ?? "—",
            AgentVersion = device?.AgentVersion ?? NexusAgentConfig.AgentVersion,
            ShellVersion = device?.ShellVersion ?? ShellVersion,
            EnrollmentDate = device?.EnrollmentDate,
            LastSeen = device?.LastSeen ?? DateTimeOffset.UtcNow,
            Status = device?.Status.ToString() ?? NexusDeviceEnrollmentStatus.Unknown.ToString(),
            Inventory = inv,
            Health = hel,
        };
    }

    public NexusAgentTrustResponse GetTrust()
    {
        var trust = _identity?.Trust.Current;
        return new NexusAgentTrustResponse
        {
            DeviceId = trust?.DeviceId ?? Config.DeviceId,
            Status = trust?.Status.ToString() ?? NexusTrustStatus.Unknown.ToString(),
            EvaluatedAtUtc = trust?.EvaluatedAtUtc,
            Reason = trust?.Reason,
        };
    }

    public NexusAgentPoliciesResponse GetPolicies(NexusPolicyService? policyService)
    {
        if (policyService is null)
        {
            return new NexusAgentPoliciesResponse
            {
                Role = "Unknown",
                PolicyId = "unavailable",
                PolicyName = "Policy service not configured",
                PolicyVersion = "0",
                SourcePath = "—",
                EvaluatedAtUtc = DateTimeOffset.UtcNow,
            };
        }

        var snapshot = policyService.GetSnapshot();
        return new NexusAgentPoliciesResponse
        {
            Role = snapshot.Role,
            PolicyId = snapshot.PolicyId,
            PolicyName = snapshot.PolicyName,
            PolicyVersion = snapshot.PolicyVersion,
            SourcePath = snapshot.SourcePath,
            EvaluatedAtUtc = snapshot.EvaluatedAtUtc,
            AllowApps = snapshot.AllowApps,
            DenyApps = snapshot.DenyApps,
            AllowFeatures = snapshot.AllowFeatures,
            DenyFeatures = snapshot.DenyFeatures,
            AllowCommands = snapshot.AllowCommands,
            DenyCommands = snapshot.DenyCommands,
            DenySettingsSections = snapshot.DenySettingsSections,
            ConsoleAccess = snapshot.ConsoleAccess,
            StoreAccess = snapshot.StoreAccess,
        };
    }
}
