using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using YMhut.Box.Core.Logging;
using YMhut.Box.Core.Settings;
using YMhut.Box.Core.Tools;
using YMhut.Box.WinUI.Services;

namespace YMhut.Box.WinUI.Views;

public sealed partial class ExternalToolDetailPage : ToolPageBase
{
    private readonly ExternalToolModule _module;
    private readonly Action? _goBack;
    private readonly IExternalToolLaunchService _launchService = AppServices.GetRequiredService<IExternalToolLaunchService>();
    private readonly IRiskConfirmationStore _riskStore = AppServices.GetRequiredService<IRiskConfirmationStore>();
    private readonly ISettingsService _settingsService = AppServices.GetRequiredService<ISettingsService>();
    private readonly ILogService _logService = AppServices.GetRequiredService<ILogService>();
    private readonly ComboBox _variantBox = new() { MinWidth = 220 };
    private readonly InfoBar _status = new()
    {
        IsOpen = true,
        Severity = InfoBarSeverity.Informational,
        Title = "外部工具",
        Message = "从 YMhut Box 随包 Tools 目录读取。高风险启动会先二次确认。"
    };
    private readonly TextBox _resultBox = new()
    {
        IsReadOnly = true,
        AcceptsReturn = true,
        MinHeight = 180,
        TextWrapping = TextWrapping.Wrap,
        Header = "运行结果"
    };
    private readonly ProgressRing _progress = new()
    {
        Width = 24,
        Height = 24,
        IsActive = false,
        Visibility = Visibility.Collapsed
    };

    public ExternalToolDetailPage(ExternalToolModule module, Action? goBack = null)
    {
        _module = module;
        _goBack = goBack;
        Background = ModernUi.AppBackground;
        BindModule(module);
        Content = BuildLayout();
    }

    private UIElement BuildLayout()
    {
        var root = new Grid
        {
            Padding = new Thickness(24, 20, 24, 24),
            RowSpacing = 16
        };
        root.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        root.RowDefinitions.Add(new RowDefinition());

        root.Children.Add(BuildModernHeader());

        var body = new Grid { ColumnSpacing = 16 };
        body.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1.1, GridUnitType.Star) });
        body.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.9, GridUnitType.Star) });
        Grid.SetRow(body, 1);
        root.Children.Add(body);

        var left = new StackPanel
        {
            Spacing = 14,
            Children =
            {
                _status,
                BuildLaunchPanel(),
                BuildMetadataPanel()
            }
        };
        body.Children.Add(left);

        var right = new StackPanel
        {
            Spacing = 14,
            Children =
            {
                BuildRiskPanel(),
                _resultBox
            }
        };
        Grid.SetColumn(right, 1);
        body.Children.Add(right);

        body.SizeChanged += (_, e) =>
        {
            var narrow = e.NewSize.Width < 860;
            body.ColumnDefinitions.Clear();
            body.RowDefinitions.Clear();
            if (narrow)
            {
                body.ColumnDefinitions.Add(new ColumnDefinition());
                body.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
                body.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
                Grid.SetColumn(right, 0);
                Grid.SetRow(right, 1);
            }
            else
            {
                body.RowDefinitions.Add(new RowDefinition());
                body.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1.1, GridUnitType.Star) });
                body.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.9, GridUnitType.Star) });
                Grid.SetColumn(right, 1);
                Grid.SetRow(right, 0);
            }
        };

        return root;
    }

    private UIElement BuildHeader()
    {
        var tool = _module.Tool;
        var grid = new Grid { ColumnSpacing = 14 };
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        grid.ColumnDefinitions.Add(new ColumnDefinition());

        grid.Children.Add(ModernUi.IconButton("\uE72B", "返回工具箱", () => _goBack?.Invoke()));
        var icon = ModernUi.IconTile(_module.Metadata.IconGlyph, 50, ModernUi.AccentSoft, ModernUi.Accent, 22);
        Grid.SetColumn(icon, 1);
        grid.Children.Add(icon);

        var title = new StackPanel
        {
            Spacing = 5,
            Children =
            {
                ModernUi.Text(tool.Name, 26, FontWeights.SemiBold, maxLines: 1),
                ModernUi.Text($"{tool.CategoryName} / {tool.Extension} / {tool.PrimaryArchitecture ?? "默认架构"}", 14, foreground: ModernUi.TextSecondary, maxLines: 1),
                ModernUi.Text(tool.Description, 14, foreground: ModernUi.TextSecondary, maxLines: 2)
            }
        };
        Grid.SetColumn(title, 2);
        grid.Children.Add(title);
        return ModernUi.Card(grid, new Thickness(18), radius: 8);
    }

    private UIElement BuildLaunchPanel()
    {
        _variantBox.Items.Clear();
        _variantBox.Items.Add(new VariantChoice("默认启动", _module.Tool.LaunchPath, _module.Tool.PrimaryArchitecture));
        foreach (var variant in _module.Tool.Variants)
        {
            _variantBox.Items.Add(new VariantChoice(variant.Name, variant.Path, variant.Architecture));
        }
        _variantBox.SelectedIndex = 0;
        _variantBox.DisplayMemberPath = nameof(VariantChoice.Label);

        var runButton = ModernUi.PillButton("启动", "\uE768", () => RunAsync(admin: false), primary: true);
        var adminButton = ModernUi.PillButton("管理员启动", "\uE7EF", () => RunAsync(admin: true));
        var folderButton = ModernUi.PillButton("打开目录", "\uE838", OpenDirectoryAsync);

        var actions = new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Spacing = 10,
            Children = { runButton, adminButton, folderButton, _progress }
        };

        return ModernUi.Card(new StackPanel
        {
            Spacing = 12,
            Children =
            {
                ModernUi.Text("运行", 18, FontWeights.SemiBold),
                _variantBox,
                actions
            }
        }, new Thickness(16), radius: 8);
    }

    private UIElement BuildMetadataPanel()
    {
        var tool = _module.Tool;
        var text = string.Join(Environment.NewLine, new[]
        {
            $"工具 ID: {tool.Id}",
            $"分类: {tool.CategoryName}",
            $"启动文件: {tool.RelativePath}",
            $"发布者: {tool.Publisher ?? "未知"}",
            $"版本: {tool.Version ?? "未知"}",
            $"标签: {string.Join(", ", tool.Tags)}"
        });
        return ModernUi.Card(new TextBlock
        {
            Text = text,
            TextWrapping = TextWrapping.Wrap,
            IsTextSelectionEnabled = true,
            FontFamily = new Microsoft.UI.Xaml.Media.FontFamily("Cascadia Mono"),
            Foreground = ModernUi.TextSecondary
        }, new Thickness(16), radius: 8);
    }

    private UIElement BuildRiskPanel()
    {
        var tool = _module.Tool;
        var severity = tool.RiskLevel switch
        {
            ReferenceToolRiskLevel.High => InfoBarSeverity.Error,
            ReferenceToolRiskLevel.Medium => InfoBarSeverity.Warning,
            ReferenceToolRiskLevel.Low => InfoBarSeverity.Informational,
            _ => InfoBarSeverity.Success
        };

        return new InfoBar
        {
            IsOpen = true,
            Severity = severity,
            Title = tool.IsRisky ? "风险确认" : "安全状态",
            Message = tool.IsRisky
                ? "未知外部 EXE、脚本、管理员运行或系统修改类工具执行前必须确认。确认、取消和执行结果都会写入日志。"
                : "此工具未标记为风险工具，仍会记录启动结果。"
        };
    }

    private async void RunAsync(bool admin)
    {
        var choice = _variantBox.SelectedItem as VariantChoice;
        var path = choice?.Path ?? _module.Tool.LaunchPath;
        var operation = admin ? "launch-admin" : "launch";
        if (!await ConfirmRiskIfNeededAsync(operation, admin))
        {
            SetResult(ReferenceToolExecutionResult.Cancel("已取消启动。"), InfoBarSeverity.Warning);
            await _logService.WriteAsync("Warning", "risk", "External tool launch cancelled", $"{_module.Id}; operation={operation}");
            return;
        }

        await RunWithProgressAsync(async () =>
            await _launchService.LaunchAsync(_module.Tool, path, admin, confirmed: true));
    }

    private async void OpenDirectoryAsync()
    {
        await RunWithProgressAsync(async () => await _launchService.OpenDirectoryAsync(_module.Tool));
    }

    private async Task RunWithProgressAsync(Func<Task<ReferenceToolExecutionResult>> action)
    {
        _progress.Visibility = Visibility.Visible;
        _progress.IsActive = true;
        try
        {
            SetResult(await action(), InfoBarSeverity.Informational);
        }
        finally
        {
            _progress.IsActive = false;
            _progress.Visibility = Visibility.Collapsed;
        }
    }

    private async Task<bool> ConfirmRiskIfNeededAsync(string operation, bool admin)
    {
        if (!_module.Tool.IsRisky && !admin)
        {
            return true;
        }

        if (!_settingsService.Current.RequireRiskConfirmation)
        {
            await _logService.WriteAsync(
                "Warning",
                "risk",
                "External tool risk confirmation bypassed by settings",
                $"{_module.Id}; operation={operation}; admin={admin}");
            return true;
        }

        if (await _riskStore.IsRememberedAsync(_module.Id, operation))
        {
            return true;
        }

        var remember = new CheckBox { Content = "记住此工具的本操作确认", Margin = new Thickness(0, 10, 0, 0) };
        var content = new StackPanel
        {
            Spacing = 8,
            Children =
            {
                ModernUi.Text("即将启动外部工具。请确认你信任该工具来源，并理解管理员运行、脚本、未知 EXE 可能修改系统或文件。", 14, foreground: ModernUi.TextSecondary),
                ModernUi.Text($"工具: {_module.Tool.Name}\n路径: {_module.Tool.RelativePath}", 13, foreground: ModernUi.TextSecondary),
                remember
            }
        };

        var dialog = new ContentDialog
        {
            Title = "确认执行风险工具",
            Content = content,
            PrimaryButtonText = "确认执行",
            CloseButtonText = "取消",
            DefaultButton = ContentDialogButton.Close,
            XamlRoot = XamlRoot
        };
        var result = await dialog.ShowAsync();
        if (result != ContentDialogResult.Primary)
        {
            return false;
        }

        await _logService.WriteAsync("Information", "risk", "External tool risk confirmed", $"{_module.Id}; operation={operation}; remembered={remember.IsChecked == true}");
        if (remember.IsChecked == true)
        {
            await _riskStore.RememberAsync(_module.Id, operation);
        }

        return true;
    }

    private void SetResult(ReferenceToolExecutionResult result, InfoBarSeverity fallbackSeverity)
    {
        _status.Severity = result.Success ? InfoBarSeverity.Success : result.Cancelled ? InfoBarSeverity.Warning : result.RequiresConfirmation ? InfoBarSeverity.Warning : InfoBarSeverity.Error;
        if (fallbackSeverity != InfoBarSeverity.Informational && result.Success)
        {
            _status.Severity = fallbackSeverity;
        }

        _status.Title = result.Success ? "完成" : result.Cancelled ? "已取消" : "未完成";
        _status.Message = result.Message;
        _resultBox.Text = string.Join(Environment.NewLine, new[]
        {
            result.Message,
            result.Detail,
            result.ExitCode is null ? null : $"ExitCode: {result.ExitCode}"
        }.Where(value => !string.IsNullOrWhiteSpace(value)));
    }

    private sealed record VariantChoice(string Name, string Path, string? Architecture)
    {
        public string Label => string.IsNullOrWhiteSpace(Architecture) ? Name : $"{Name} ({Architecture})";
    }
}
