using System.Diagnostics;
using System.IO;
using System.Text.Json;
using NexusShell.Models;

namespace NexusShell.Services;

public sealed class NexusPlatformLockService
{
    private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true };

    private readonly LockdownService _lockdown;
    private readonly NexusPlatformUnlockConfig _config;
    private NexusPlatformLockState _state = new();

    public NexusPlatformLockService(LockdownService lockdown)
    {
        _lockdown = lockdown;
        _config = LoadConfig();
        Load();
        RefreshBypass();
    }

    public event EventHandler? LockStateChanged;

    public NexusPlatformUnlockConfig Config => _config;

    public NexusPlatformLockState State => _state;

    public bool IsWindowsLocked
    {
        get
        {
            ExpireIfNeeded();
            return _state.Mode == NexusPlatformLockMode.Locked;
        }
    }

    public string StatusLabel
    {
        get
        {
            ExpireIfNeeded();
            if (_state.Mode == NexusPlatformLockMode.Locked)
            {
                return "Windows låst — Nexus ejer skrivebordet";
            }

            var until = _state.UnlockedUntilUtc?.ToLocalTime().ToString("HH:mm") ?? "manuelt";
            return $"Windows låst op (POC) — indtil {until}";
        }
    }

    public bool ShouldHideWindowsTaskbar(NexusUserSettings settings) =>
        IsWindowsLocked || (settings.HideWindowsTaskbar && !SafePocRuntime.IsOverlayMode);

    public bool ShouldUseShellFullscreen(NexusUserSettings settings) =>
        IsWindowsLocked || settings.ShellFullscreen;

    public bool TryUnlock(string pin, string actor, int? sessionMinutes = null)
    {
        if (!string.Equals(pin.Trim(), _config.UnlockPin, StringComparison.Ordinal))
        {
            _lockdown.LogDeveloperAttempt(actor, "Platform unlock failed — invalid PIN", false);
            return false;
        }

        var minutes = sessionMinutes ?? _config.DefaultSessionMinutes;
        var now = DateTimeOffset.UtcNow;
        _state = new NexusPlatformLockState
        {
            Mode = NexusPlatformLockMode.Unlocked,
            UnlockedAtUtc = now,
            UnlockedUntilUtc = now.AddMinutes(minutes),
            UnlockedBy = actor,
        };

        Save();
        RefreshBypass();
        _lockdown.LogDeveloperAttempt(actor, $"Platform unlock granted for {minutes} min (POC)", true);
        LockStateChanged?.Invoke(this, EventArgs.Empty);
        return true;
    }

    public void Lock(string actor)
    {
        _state = new NexusPlatformLockState
        {
            Mode = NexusPlatformLockMode.Locked,
            LockedAtUtc = DateTimeOffset.UtcNow,
        };

        Save();
        RefreshBypass();
        _lockdown.LogDeveloperAttempt(actor, "Platform lock engaged — Windows hidden", true);
        LockStateChanged?.Invoke(this, EventArgs.Empty);
    }

    public void EnableAfterEnrollment(string actor)
    {
        Lock(actor);
    }

    private void ExpireIfNeeded()
    {
        if (_state.Mode != NexusPlatformLockMode.Unlocked || _state.UnlockedUntilUtc is null)
        {
            return;
        }

        if (DateTimeOffset.UtcNow <= _state.UnlockedUntilUtc.Value)
        {
            return;
        }

        _state = new NexusPlatformLockState
        {
            Mode = NexusPlatformLockMode.Locked,
            LockedAtUtc = DateTimeOffset.UtcNow,
        };

        Save();
        RefreshBypass();
        _lockdown.LogDeveloperAttempt("system", "Platform unlock session expired — Windows re-locked", true);
        LockStateChanged?.Invoke(this, EventArgs.Empty);
    }

    private void RefreshBypass()
    {
        ExpireIfNeeded();
        _lockdown.SetPlatformBypass(!IsWindowsLocked);
    }

    private void Load()
    {
        var path = GetStatePath();
        if (!File.Exists(path))
        {
            _state = new NexusPlatformLockState { Mode = NexusPlatformLockMode.Locked };
            return;
        }

        try
        {
            var json = File.ReadAllText(path);
            _state = JsonSerializer.Deserialize<NexusPlatformLockState>(json, JsonOptions) ?? new NexusPlatformLockState();
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"[Nexus PlatformLock] load failed: {ex.Message}");
            _state = new NexusPlatformLockState { Mode = NexusPlatformLockMode.Locked };
        }
    }

    private void Save()
    {
        var path = GetStatePath();
        Directory.CreateDirectory(Path.GetDirectoryName(path)!);
        File.WriteAllText(path, JsonSerializer.Serialize(_state, JsonOptions));
    }

    private static string GetStatePath() =>
        Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
            "NinjaNexus",
            "platform-lock.json");

    private static NexusPlatformUnlockConfig LoadConfig()
    {
        var path = Path.Combine(AppContext.BaseDirectory, "config", "platform-unlock.poc.json");
        if (!File.Exists(path))
        {
            return new NexusPlatformUnlockConfig();
        }

        try
        {
            var json = File.ReadAllText(path);
            return JsonSerializer.Deserialize<NexusPlatformUnlockConfig>(json, JsonOptions) ?? new NexusPlatformUnlockConfig();
        }
        catch
        {
            return new NexusPlatformUnlockConfig();
        }
    }
}
