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

namespace NexusShell.Services;

public sealed class DeveloperConsoleService
{
    private readonly DeveloperPocConfig _config;
    private readonly LockdownService _lockdown;
    private int _failedAttempts;
    private DateTimeOffset _rateLimitUntil = DateTimeOffset.MinValue;
    private string? _authenticatedMaster;
    private DateTimeOffset _sessionExpires = DateTimeOffset.MinValue;

    public DeveloperConsoleService(LockdownService lockdown)
    {
        _lockdown = lockdown;
        _config = LoadConfig();
    }

    public bool IsAuthenticated => _authenticatedMaster is not null && DateTimeOffset.UtcNow < _sessionExpires;

    public string? AuthenticatedMaster => IsAuthenticated ? _authenticatedMaster : null;

    public bool IsMasterUsername(string email) =>
        _config.MasterUsernames.Any(u => string.Equals(u, email, StringComparison.OrdinalIgnoreCase));

    public bool IsRateLimited => DateTimeOffset.UtcNow < _rateLimitUntil;

    public string RateLimitMessage =>
        $"For mange forsøg. Prøv igen efter {_rateLimitUntil.ToLocalTime():HH:mm}.";

    public void RecordFailedAttempt(string username)
    {
        _failedAttempts++;
        _lockdown.LogDeveloperAttempt(username, $"Failed attempt {_failedAttempts}/{_config.MaxFailedAttempts}", false);

        if (_failedAttempts >= _config.MaxFailedAttempts)
        {
            _rateLimitUntil = DateTimeOffset.UtcNow.AddMinutes(_config.RateLimitWindowMinutes);
            _failedAttempts = 0;
        }
    }

    public void OpenSession(string username)
    {
        _authenticatedMaster = username;
        _sessionExpires = DateTimeOffset.UtcNow.AddMinutes(_config.UnlockSessionMinutes);
        _failedAttempts = 0;
        _lockdown.LogDeveloperAttempt(username, "Developer Console session opened (POC — no Windows escape)", true);
    }

    public void CloseSession()
    {
        if (_authenticatedMaster is not null)
        {
            _lockdown.LogDeveloperAction(_authenticatedMaster, "Exit Developer Mode", true);
        }

        _authenticatedMaster = null;
        _sessionExpires = DateTimeOffset.MinValue;
    }

    public void LogDisabledAction(string action)
    {
        _lockdown.LogDeveloperAction(_authenticatedMaster ?? "unknown", $"{action} — Disabled in POC for safety", false);
    }

    public bool VerifyViaIdentityApi => _config.VerifyViaIdentityApi;

    private static DeveloperPocConfig LoadConfig()
    {
        var path = Path.Combine(AppContext.BaseDirectory, "config", "developer.poc.json");
        if (!File.Exists(path))
        {
            return new DeveloperPocConfig { MasterUsernames = ["admin@nexus.local"] };
        }

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

    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNameCaseInsensitive = true,
    };
}
