using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Versioning;
using System.Windows;
using System.Windows.Navigation;
using TeamsISO.App.Services;
using TeamsISO.Engine.NdiInterop;

namespace TeamsISO.App;

/// <summary>
/// Modal "About" dialog. Surfaces enough info that a user filing a support ticket
/// can paste version + NDI runtime + OS in a single screenshot.
/// </summary>
public partial class AboutWindow : Window
{
    public AboutWindow()
    {
        InitializeComponent();
        PopulateText();
    }

    private void PopulateText()
    {
        var asm = typeof(App).Assembly;
        var info = asm.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion
                   ?? asm.GetName().Version?.ToString()
                   ?? "unknown";
        VersionText.Text = info;
        RuntimeText.Text = $".NET {Environment.Version}";
        OsText.Text = Environment.OSVersion.ToString();
        NdiText.Text = TryGetNdiVersion();
    }

    [SupportedOSPlatform("windows")]
    private static string TryGetNdiVersion()
    {
        try
        {
            using var interop = new NdiInteropPInvoke(
                Microsoft.Extensions.Logging.Abstractions.NullLogger<NdiInteropPInvoke>.Instance);
            return interop.GetRuntimeVersion();
        }
        catch (Exception ex)
        {
            return $"not initialized ({ex.Message})";
        }
    }

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

    /// <summary>
    /// Re-open the first-launch welcome dialog from About so users can revisit
    /// the setup checklist without having to delete the suppression flag file
    /// by hand. The "Don't show again" checkbox in the welcome dialog defaults
    /// to checked so a re-shown welcome won't unset the suppression on close.
    /// </summary>
    private void OnShowOnboarding(object sender, RoutedEventArgs e)
    {
        var onboarding = new OnboardingWindow { Owner = this };
        onboarding.ShowDialog();
    }

    /// <summary>
    /// Quick-jump: open a path in Explorer. Creates the directory if missing
    /// (operator might click "Recordings" before any have been made). Best-
    /// effort — Explorer launch failures don't surface a dialog.
    /// </summary>
    private static void OpenInExplorer(string path)
    {
        try
        {
            if (!Directory.Exists(path)) Directory.CreateDirectory(path);
            Process.Start(new ProcessStartInfo
            {
                FileName = path,
                UseShellExecute = true,
            });
        }
        catch
        {
            // No-op: shell launch failed (path inaccessible / Explorer crashed)
        }
    }

    private void OnOpenLogs(object sender, RoutedEventArgs e) =>
        OpenInExplorer(Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
            "TeamsISO", "Logs"));

    private void OnOpenRecordings(object sender, RoutedEventArgs e)
    {
        // Default to the user-Videos folder. Operator can navigate into the
        // current session's date subfolder from there. We don't reach into
        // the engine for the live recording path because exposing the
        // controller through App would be a wider plumbing change for a
        // shortcut button.
        OpenInExplorer(Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.MyVideos),
            "TeamsISO"));
    }

    private void OnOpenNotes(object sender, RoutedEventArgs e) =>
        OpenInExplorer(Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
            "TeamsISO", "Notes"));

    /// <summary>
    /// Build the diagnostic bundle and tell the operator where it landed. The
    /// bundle is just zipped logs / config / presets — no screenshots, no
    /// memory dumps. Intended to be attached to a bug report.
    /// </summary>
    private void OnExportDiagnostics(object sender, RoutedEventArgs e)
    {
        try
        {
            var path = DiagnosticsBundle.Export();
            var open = MessageBox.Show(
                this,
                $"Diagnostic bundle written to:\n\n{path}\n\nOpen the containing folder?",
                "TeamsISO — Diagnostics exported",
                MessageBoxButton.YesNo,
                MessageBoxImage.Information);
            if (open == MessageBoxResult.Yes)
            {
                try
                {
                    Process.Start(new ProcessStartInfo
                    {
                        FileName = "explorer.exe",
                        Arguments = $"/select,\"{path}\"",
                        UseShellExecute = true,
                    });
                }
                catch { /* shell launch failure is best-effort */ }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                this,
                $"Diagnostic export failed.\n\n{ex.Message}",
                "TeamsISO — Diagnostic export",
                MessageBoxButton.OK,
                MessageBoxImage.Warning);
        }
    }

    /// <summary>
    /// Click handler for "Check for updates". Disables the button while the
    /// HTTP call is in flight (so a second click doesn't spawn parallel
    /// requests), then surfaces the result via MessageBox. On
    /// <see cref="UpdateChecker.UpdateStatus.UpdateAvailable"/> we offer
    /// to open the releases page so the operator can grab the new MSI.
    /// </summary>
    private async void OnCheckUpdate(object sender, RoutedEventArgs e)
    {
        UpdateButton.IsEnabled = false;
        try
        {
            var result = await UpdateChecker.CheckAsync();
            switch (result.Status)
            {
                case UpdateChecker.UpdateStatus.UpdateAvailable:
                    var open = MessageBox.Show(
                        this,
                        $"{result.Message}\n\n" +
                        $"You're on {result.CurrentVersion}; latest is {result.LatestTag}.\n\n" +
                        "Open the releases page to download the new MSI?",
                        "TeamsISO — Update available",
                        MessageBoxButton.YesNo,
                        MessageBoxImage.Information);
                    if (open == MessageBoxResult.Yes)
                        UpdateChecker.OpenReleasesPage();
                    break;

                case UpdateChecker.UpdateStatus.UpToDate:
                    MessageBox.Show(
                        this,
                        result.Message ?? "You're on the latest release.",
                        "TeamsISO — Up to date",
                        MessageBoxButton.OK,
                        MessageBoxImage.Information);
                    break;

                case UpdateChecker.UpdateStatus.Error:
                default:
                    MessageBox.Show(
                        this,
                        $"Couldn't check for updates.\n\n{result.Message}",
                        "TeamsISO — Update check failed",
                        MessageBoxButton.OK,
                        MessageBoxImage.Warning);
                    break;
            }
        }
        finally
        {
            UpdateButton.IsEnabled = true;
        }
    }

    /// <summary>
    /// Open the company site in the default browser. We intentionally use the
    /// shell's URL handler rather than a tab inside the app — this is a
    /// "tell me more" link, not a workflow.
    /// </summary>
    private void OnWebsiteClick(object sender, RoutedEventArgs e)
    {
        try
        {
            Process.Start(new ProcessStartInfo
            {
                FileName = "https://wilddragon.net",
                UseShellExecute = true,
            });
        }
        catch
        {
            // best-effort; if shell launch fails the click is a no-op
        }
    }
}
