using ITNexusAgent.Models;
using ITNexusAgent.Services;
using Newtonsoft.Json;
using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;
using WinForms = System.Windows.Forms;
using DrawingIcon = System.Drawing.Icon;
using DrawingSystemIcons = System.Drawing.SystemIcons;
using MessageBox = System.Windows.MessageBox;
using SolidColorBrush = System.Windows.Media.SolidColorBrush;
using MediaColor = System.Windows.Media.Color;
using ProgressBar = System.Windows.Controls.ProgressBar;

namespace ITNexusAgent.UI;

public partial class DashboardWindow : Window
{
    private const string StatusPath = @"C:\ProgramData\IT Nexus Agent\status.json";
    private const string LogPath = @"C:\ProgramData\IT Nexus Agent\agent.log";
    private readonly DispatcherTimer _timer;
    private AgentConfig? _config;
    private string? _adminToken;
    private WinForms.NotifyIcon? _trayIcon;
    private List<string> _allSoftware = [];
    private bool _softwarePlaceholderActive = true;

    public DashboardWindow()
    {
        InitializeComponent();

        try { _config = AgentConfig.Load(@"C:\ProgramData\IT Nexus Agent\config.json"); }
        catch { }

        InitTrayIcon();
        InitSoftwareSearch();

        VersionLabel.Text = $"IT Nexus Agent v2.0.0  ·  Cereda Systems GmbH";

        _timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) };
        _timer.Tick += (_, _) => RefreshStatus();
        _timer.Start();

        RefreshStatus();
    }

    private void InitSoftwareSearch()
    {
        SoftwareSearch.Text = "Software suchen...";
        SoftwareSearch.Foreground = new SolidColorBrush(MediaColor.FromRgb(82, 82, 91));

        SoftwareSearch.GotFocus += (_, _) =>
        {
            if (_softwarePlaceholderActive)
            {
                _softwarePlaceholderActive = false;
                SoftwareSearch.Text = "";
                SoftwareSearch.Foreground = new SolidColorBrush(MediaColor.FromRgb(250, 250, 250));
            }
        };

        SoftwareSearch.LostFocus += (_, _) =>
        {
            if (string.IsNullOrWhiteSpace(SoftwareSearch.Text))
            {
                _softwarePlaceholderActive = true;
                SoftwareSearch.Text = "Software suchen...";
                SoftwareSearch.Foreground = new SolidColorBrush(MediaColor.FromRgb(82, 82, 91));
                ApplySoftwareFilter("");
            }
        };
    }

    private void RefreshStatus()
    {
        try
        {
            if (!File.Exists(StatusPath))
            {
                SetOffline("Noch kein Check-in");
                return;
            }

            var json = File.ReadAllText(StatusPath);
            var status = JsonConvert.DeserializeObject<StatusCache>(json);
            if (status == null) return;

            HostnameLabel.Text = $"{status.Hostname}  ·  {status.LastUser}";

            var ago = DateTime.Now - status.LastCheckin;
            var agoText = ago.TotalSeconds < 60
                ? $"vor {(int)ago.TotalSeconds} Sekunden"
                : ago.TotalMinutes < 60
                    ? $"vor {(int)ago.TotalMinutes} Minuten"
                    : $"vor {(int)ago.TotalHours} Stunden";

            if (status.Online && ago.TotalMinutes < 3)
            {
                StatusDot.Fill = new SolidColorBrush(MediaColor.FromRgb(34, 197, 94));
                StatusLabel.Text = "Online";
            }
            else
            {
                StatusDot.Fill = new SolidColorBrush(MediaColor.FromRgb(239, 68, 68));
                StatusLabel.Text = "Offline";
            }

            // Metrics
            var cpu = status.CpuUsage ?? 0;
            CpuLabel.Text = $"{cpu:0}%";
            CpuBar.Value = cpu;
            SetBarColor(CpuBar, cpu);

            if (status.RamTotal > 0)
            {
                var ramPct = (status.RamUsed ?? 0) / status.RamTotal.Value * 100;
                RamLabel.Text = $"{status.RamUsed:0.0}/{status.RamTotal:0} GB";
                RamBar.Value = ramPct;
                SetBarColor(RamBar, ramPct);
            }

            if (status.DiskTotal > 0)
            {
                var diskUsed = status.DiskTotal.Value - (status.DiskFree ?? 0);
                var diskPct = diskUsed / status.DiskTotal.Value * 100;
                DiskLabel.Text = $"{diskUsed:0}/{status.DiskTotal:0} GB";
                DiskBar.Value = diskPct;
                SetBarColor(DiskBar, diskPct);
            }

            // Security
            BitlockerLabel.Text = status.BitlockerStatus switch
            {
                "encrypted" => "✓ Verschlüsselt",
                "off"       => "✗ Nicht aktiv",
                _           => "? Unbekannt"
            };
            BitlockerLabel.Foreground = status.BitlockerStatus == "encrypted"
                ? new SolidColorBrush(MediaColor.FromRgb(22, 163, 74))
                : new SolidColorBrush(MediaColor.FromRgb(239, 68, 68));

            DefenderLabel.Text = status.DefenderEnabled
                ? status.DefenderSignaturesAge <= 3
                    ? "✓ Aktiv · Signaturen aktuell"
                    : $"⚠ Aktiv · Signaturen {status.DefenderSignaturesAge}d alt"
                : "✗ Inaktiv";
            DefenderLabel.Foreground = status.DefenderEnabled
                ? new SolidColorBrush(MediaColor.FromRgb(22, 163, 74))
                : new SolidColorBrush(MediaColor.FromRgb(239, 68, 68));

            UpdatesLabel.Text = status.PendingUpdates == 0 ? "✓ Aktuell" : $"⚠ {status.PendingUpdates} ausstehend";
            UpdatesLabel.Foreground = status.PendingUpdates == 0
                ? new SolidColorBrush(MediaColor.FromRgb(22, 163, 74))
                : new SolidColorBrush(MediaColor.FromRgb(245, 158, 11));

            SerialLabel.Text = string.IsNullOrEmpty(status.HardwareSerial) ? "—" : status.HardwareSerial;
            LastCheckinLabel.Text = $"Letzter Check-in: {agoText}";

            // Software-Liste nur aktualisieren wenn sich die Anzahl geändert hat
            if (status.InstalledSoftware.Count != _allSoftware.Count ||
                (status.InstalledSoftware.Count > 0 && _allSoftware.Count == 0))
            {
                _allSoftware = status.InstalledSoftware;
                var filterText = _softwarePlaceholderActive ? "" : SoftwareSearch.Text;
                ApplySoftwareFilter(filterText);
            }
        }
        catch { SetOffline("Fehler beim Laden"); }
    }

    private void ApplySoftwareFilter(string filter)
    {
        var filtered = string.IsNullOrWhiteSpace(filter)
            ? _allSoftware
            : _allSoftware.Where(s => s.Contains(filter, StringComparison.OrdinalIgnoreCase)).ToList();

        SoftwareList.ItemsSource = filtered;
        SoftwareCountLabel.Text = _allSoftware.Count > 0
            ? $"{filtered.Count} / {_allSoftware.Count}"
            : "";
    }

    private void SoftwareSearch_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
    {
        if (_softwarePlaceholderActive) return;
        ApplySoftwareFilter(SoftwareSearch.Text);
    }

    private void SetOffline(string reason)
    {
        StatusDot.Fill = new SolidColorBrush(MediaColor.FromRgb(156, 163, 175));
        StatusLabel.Text = reason;
    }

    private static void SetBarColor(System.Windows.Controls.ProgressBar bar, double pct)
    {
        var color = pct > 90 ? MediaColor.FromRgb(239, 68, 68)
            : pct > 70 ? MediaColor.FromRgb(245, 158, 11)
            : MediaColor.FromRgb(59, 130, 246);
        bar.Foreground = new SolidColorBrush(color);
    }

    private void WebButton_Click(object sender, RoutedEventArgs e)
    {
        var url = _config?.ServerUrl ?? "https://it-nexus.cereda-systems.de";
        Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
    }

    private async void MessageButton_Click(object sender, RoutedEventArgs e)
    {
        var dlg = new MessageDialog();
        if (dlg.ShowDialog() != true || string.IsNullOrWhiteSpace(dlg.Message)) return;

        try
        {
            if (_config != null)
            {
                var api = new ApiService(_config.ServerUrl, _config.AgentKey);
                await api.SendMessageAsync(Environment.MachineName, dlg.Message);
                MessageBox.Show("Nachricht wurde gesendet.", "IT Nexus", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }
        catch
        {
            MessageBox.Show("Fehler beim Senden.", "IT Nexus", MessageBoxButton.OK, MessageBoxImage.Warning);
        }
    }

    private async void RebootButton_Click(object sender, RoutedEventArgs e)
    {
        var result = MessageBox.Show(
            "Möchtest du einen Neustart bei der IT anfordern?\nDein Rechner wird nicht sofort neu gestartet.",
            "Neustart anfordern", MessageBoxButton.YesNo, MessageBoxImage.Question);
        if (result != MessageBoxResult.Yes) return;

        try
        {
            if (_config != null)
            {
                var api = new ApiService(_config.ServerUrl, _config.AgentKey);
                await api.SendRebootRequestAsync(Environment.MachineName);
                MessageBox.Show("Neustart wurde angefordert. Die IT wird sich darum kümmern.",
                    "IT Nexus", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }
        catch { }
    }

    private void AdminLoginButton_Click(object sender, RoutedEventArgs e)
    {
        if (_adminToken != null)
        {
            _adminToken = null;
            AdminPanel.Visibility = Visibility.Collapsed;
            AdminLoginButton.Content = "Admin-Modus";
            return;
        }
        AdminUsernameBox.Text = "";
        AdminPasswordBox.Password = "";
        AdminErrorLabel.Visibility = Visibility.Collapsed;
        AdminOverlay.Visibility = Visibility.Visible;
        AdminUsernameBox.Focus();
    }

    private void AdminCancelModal_Click(object sender, RoutedEventArgs e)
        => AdminOverlay.Visibility = Visibility.Collapsed;

    private async void AdminLoginModal_Click(object sender, RoutedEventArgs e)
    {
        var username = AdminUsernameBox.Text.Trim();
        var password = AdminPasswordBox.Password;
        if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return;

        AdminLoginBtn.IsEnabled = false;
        AdminErrorLabel.Visibility = Visibility.Collapsed;

        try
        {
            using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
            var body = Newtonsoft.Json.JsonConvert.SerializeObject(new { username, password });
            var resp = await http.PostAsync($"{_config?.ServerUrl?.TrimEnd('/')}/api/auth/login",
                new StringContent(body, Encoding.UTF8, "application/json"));
            var json = await resp.Content.ReadAsStringAsync();
            var result = Newtonsoft.Json.JsonConvert.DeserializeAnonymousType(json, new { token = "" });

            if (resp.IsSuccessStatusCode && !string.IsNullOrEmpty(result?.token))
            {
                _adminToken = result.token;
                AdminOverlay.Visibility = Visibility.Collapsed;

                if (_pendingExit)
                {
                    _pendingExit = false;
                    DoExit();
                    return;
                }

                AdminPanel.Visibility = Visibility.Visible;
                AdminUserLabel.Text = $"Angemeldet als {username}";
                AdminLoginButton.Content = "Admin-Modus beenden";
            }
            else
            {
                AdminErrorLabel.Text = "Ungültige Anmeldedaten";
                AdminErrorLabel.Visibility = Visibility.Visible;
            }
        }
        catch
        {
            AdminErrorLabel.Text = "Verbindung fehlgeschlagen";
            AdminErrorLabel.Visibility = Visibility.Visible;
        }
        finally { AdminLoginBtn.IsEnabled = true; }
    }

    private void AdminPasswordBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
    {
        if (e.Key == System.Windows.Input.Key.Enter)
            AdminLoginModal_Click(sender, new RoutedEventArgs());
    }

    private void AdminCheckin_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            Process.Start(new ProcessStartInfo("net.exe", "stop \"IT Nexus Agent\"")
            { CreateNoWindow = true, UseShellExecute = false })?.WaitForExit();
            Process.Start(new ProcessStartInfo("net.exe", "start \"IT Nexus Agent\"")
            { CreateNoWindow = true, UseShellExecute = false });
            MessageBox.Show("Agent wird neu gestartet — Check-in in ~5 Sekunden.",
                "IT Nexus", MessageBoxButton.OK, MessageBoxImage.Information);
        }
        catch (Exception ex)
        {
            MessageBox.Show($"Fehler: {ex.Message}", "IT Nexus", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }

    private void AdminUpdates_Click(object sender, RoutedEventArgs e)
    {
        Process.Start(new ProcessStartInfo("UsoClient.exe", "StartScan") { CreateNoWindow = true });
        MessageBox.Show("Update-Scan gestartet.", "IT Nexus", MessageBoxButton.OK, MessageBoxImage.Information);
    }

    private void AdminLog_Click(object sender, RoutedEventArgs e)
    {
        var dlg = new LogWindow();
        dlg.Show();
    }

    private void AdminRestart_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            Process.Start(new ProcessStartInfo("net.exe", "stop \"IT Nexus Agent\"")
            { CreateNoWindow = true, UseShellExecute = false })?.WaitForExit();
            Process.Start(new ProcessStartInfo("net.exe", "start \"IT Nexus Agent\"")
            { CreateNoWindow = true, UseShellExecute = false });
            MessageBox.Show("Agent-Service wird neu gestartet.", "IT Nexus", MessageBoxButton.OK, MessageBoxImage.Information);
        }
        catch (Exception ex)
        {
            MessageBox.Show($"Fehler: {ex.Message}", "IT Nexus", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }

    private void InitTrayIcon()
    {
        try
        {
            var iconPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "icon.ico");
            var icon = File.Exists(iconPath)
                ? new DrawingIcon(iconPath)
                : DrawingSystemIcons.Application;

            _trayIcon = new WinForms.NotifyIcon
            {
                Icon = icon,
                Text = "IT Nexus Agent",
                Visible = true
            };

            var menu = new WinForms.ContextMenuStrip();
            menu.Items.Add("Dashboard öffnen", null, (s, e) => ShowDashboard());
            menu.Items.Add("-");
            menu.Items.Add("IT Nexus Web", null, (s, e) =>
            {
                var url = _config?.ServerUrl ?? "https://it-nexus.cereda-systems.de";
                Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
            });
            menu.Items.Add("-");
            menu.Items.Add("Beenden", null, (s, e) => ExitWithAuth());

            _trayIcon.ContextMenuStrip = menu;
            _trayIcon.DoubleClick += (s, e) => ShowDashboard();
        }
        catch { }
    }

    private void ShowDashboard()
    {
        Show();
        WindowState = WindowState.Normal;
        Activate();
        Focus();
    }

    protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
    {
        e.Cancel = true;
        Hide();
    }

    private void ExitWithAuth()
    {
        Dispatcher.Invoke(() =>
        {
            if (_adminToken != null)
            {
                DoExit();
                return;
            }

            AdminUsernameBox.Text = "";
            AdminPasswordBox.Password = "";
            AdminErrorLabel.Visibility = Visibility.Collapsed;
            AdminOverlay.Visibility = Visibility.Visible;
            ShowDashboard();
            _pendingExit = true;
            AdminUsernameBox.Focus();
        });
    }

    private bool _pendingExit = false;

    private void DoExit()
    {
        _trayIcon!.Visible = false;
        System.Windows.Application.Current.Shutdown();
    }

    private void TitleBar_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
            DragMove();
    }

    private void Close_Click(object sender, RoutedEventArgs e) => Close();

    private bool _isMaximized = false;
    private double _restoreLeft, _restoreTop, _restoreWidth, _restoreHeight;

    private void Minimize_Click(object sender, RoutedEventArgs e)
        => WindowState = WindowState.Minimized;

    private void Maximize_Click(object sender, RoutedEventArgs e)
    {
        if (_isMaximized)
            RestoreWindow();
        else
            MaximizeWindow();
    }

    private void MaximizeWindow()
    {
        _restoreLeft = Left; _restoreTop = Top;
        _restoreWidth = Width; _restoreHeight = Height;

        var wa = SystemParameters.WorkArea;
        Left = wa.Left; Top = wa.Top;
        Width = wa.Width; Height = wa.Height;
        _isMaximized = true;

        OuterBorder.CornerRadius = new CornerRadius(0);
        OuterBorder.Margin = new Thickness(0);
        OuterBorder.Effect = null;
        TitleBarBorder.CornerRadius = new CornerRadius(0);
    }

    private void RestoreWindow()
    {
        Left = _restoreLeft; Top = _restoreTop;
        Width = _restoreWidth; Height = _restoreHeight;
        _isMaximized = false;

        OuterBorder.CornerRadius = new CornerRadius(14);
        OuterBorder.Margin = new Thickness(16);
        OuterBorder.Effect = new System.Windows.Media.Effects.DropShadowEffect
        {
            Color = System.Windows.Media.Colors.Black,
            Opacity = 0.4, BlurRadius = 20, ShadowDepth = 0
        };
        TitleBarBorder.CornerRadius = new CornerRadius(14, 14, 0, 0);
    }

    private void Window_StateChanged(object sender, EventArgs e) { }

    protected override void OnClosed(EventArgs e)
    {
        _timer.Stop();
        base.OnClosed(e);
    }
}
