using System.ComponentModel;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using SkiaSharp;
using Svg.Skia;
using ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;

namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;

public partial class MainWindow : Window
{
    /// <summary>Initializes a new instance of the MainWindow, loading the application icon.</summary>
    public MainWindow()
    {
        InitializeComponent();
        LoadIcon();
    }

    private void LoadIcon()
    {
        try
        {
            var assembly = Assembly.GetExecutingAssembly();
            using var stream = assembly.GetManifestResourceStream("ZB.MOM.WW.OtOpcUa.Client.UI.Assets.app-icon.svg");
            if (stream == null) return;

            using var svg = new SKSvg();
            svg.Load(stream);
            if (svg.Picture == null) return;

            var size = 64;
            using var bitmap = new SKBitmap(size, size);
            using var canvas = new SKCanvas(bitmap);
            canvas.Clear(SKColors.Transparent);

            var bounds = svg.Picture.CullRect;
            var scale = Math.Min(size / bounds.Width, size / bounds.Height);
            canvas.Translate((size - bounds.Width * scale) / 2, (size - bounds.Height * scale) / 2);
            canvas.Scale(scale);
            canvas.DrawPicture(svg.Picture);

            using var image = SKImage.FromBitmap(bitmap);
            using var data = image.Encode(SKEncodedImageFormat.Png, 100);
            using var pngStream = new MemoryStream(data.ToArray());
            Icon = new WindowIcon(pngStream);
        }
        catch
        {
            // Icon loading is best-effort
        }
    }

    /// <inheritdoc />
    protected override void OnLoaded(RoutedEventArgs e)
    {
        base.OnLoaded(e);

        var browseTreeView = this.FindControl<BrowseTreeView>("BrowseTreePanel");
        var treeView = browseTreeView?.FindControl<TreeView>("BrowseTree");
        if (treeView != null) treeView.SelectionChanged += OnTreeSelectionChanged;

        var contextMenu = this.FindControl<ContextMenu>("TreeContextMenu");
        if (contextMenu != null) contextMenu.Opening += OnTreeContextMenuOpening;

        var subscribeItem = this.FindControl<MenuItem>("SubscribeMenuItem");
        if (subscribeItem != null) subscribeItem.Click += OnSubscribeClicked;

        var viewHistoryItem = this.FindControl<MenuItem>("ViewHistoryMenuItem");
        if (viewHistoryItem != null) viewHistoryItem.Click += OnViewHistoryClicked;

        var monitorAlarmsItem = this.FindControl<MenuItem>("MonitorAlarmsMenuItem");
        if (monitorAlarmsItem != null) monitorAlarmsItem.Click += OnMonitorAlarmsClicked;

        var browseCertPath = this.FindControl<Button>("BrowseCertPathButton");
        if (browseCertPath != null) browseCertPath.Click += OnBrowseCertPathClicked;
    }

    private void OnTreeSelectionChanged(object? sender, SelectionChangedEventArgs e)
    {
        if (DataContext is not MainWindowViewModel vm || sender is not TreeView treeView) return;

        vm.SelectedTreeNode = treeView.SelectedItem as TreeNodeViewModel;

        vm.SelectedTreeNodes.Clear();
        foreach (var item in treeView.SelectedItems)
            if (item is TreeNodeViewModel node)
                vm.SelectedTreeNodes.Add(node);
    }

    private void OnTreeContextMenuOpening(object? sender, CancelEventArgs e)
    {
        if (DataContext is not MainWindowViewModel vm) return;

        vm.UpdateHistoryEnabledForSelection();

        var subscribeItem = this.FindControl<MenuItem>("SubscribeMenuItem");
        var viewHistoryItem = this.FindControl<MenuItem>("ViewHistoryMenuItem");
        var monitorAlarmsItem = this.FindControl<MenuItem>("MonitorAlarmsMenuItem");

        if (subscribeItem != null)
            subscribeItem.IsEnabled = vm.IsConnected && vm.SelectedTreeNodes.Count > 0;
        if (viewHistoryItem != null)
            viewHistoryItem.IsEnabled = vm.IsHistoryEnabledForSelection;
        if (monitorAlarmsItem != null)
            monitorAlarmsItem.IsEnabled = vm.IsConnected && vm.SelectedTreeNodes.Count > 0;
    }

    private async void OnSubscribeClicked(object? sender, RoutedEventArgs e)
    {
        if (DataContext is MainWindowViewModel vm)
            await vm.SubscribeSelectedNodesCommand.ExecuteAsync(null);
    }

    private void OnViewHistoryClicked(object? sender, RoutedEventArgs e)
    {
        if (DataContext is MainWindowViewModel vm)
            vm.ViewHistoryForSelectedNodeCommand.Execute(null);
    }

    private async void OnMonitorAlarmsClicked(object? sender, RoutedEventArgs e)
    {
        if (DataContext is MainWindowViewModel vm)
            await vm.MonitorAlarmsForSelectedNodeCommand.ExecuteAsync(null);
    }

    private async void OnBrowseCertPathClicked(object? sender, RoutedEventArgs e)
    {
        if (DataContext is not MainWindowViewModel vm) return;

        var topLevel = TopLevel.GetTopLevel(this);
        if (topLevel == null) return;

        IStorageFolder? startLocation = null;
        if (!string.IsNullOrEmpty(vm.CertificateStorePath))
        {
            try
            {
                startLocation = await topLevel.StorageProvider.TryGetFolderFromPathAsync(vm.CertificateStorePath);
            }
            catch
            {
                // Best-effort: if the existing path can't be resolved (missing/permission), open the dialog without it.
            }
        }

        var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
        {
            Title = "Select Certificate Store Folder",
            AllowMultiple = false,
            SuggestedStartLocation = startLocation
        });

        if (folders.Count == 0) return;

        var picked = folders[0].TryGetLocalPath();
        if (!string.IsNullOrEmpty(picked))
            vm.CertificateStorePath = picked;
    }

    /// <inheritdoc />
    protected override void OnClosing(WindowClosingEventArgs e)
    {
        if (DataContext is MainWindowViewModel vm)
        {
            vm.SaveSettings();
            vm.Dispose();
        }
        base.OnClosing(e);
    }
}
