namespace YMhut.Box.Core.Tools;

using YMhut.Box.Core.Settings;

public enum ToolPrimaryInputKind
{
    None,
    Text,
    MultilineText,
    Query,
    Url,
    Token,
    Color,
    FixedOptions,
    FilePath,
    DateRange,
    Number,
    NumberPair,
    NumberTriple,
    NumberQuad
}

public enum ToolParameterControlKind
{
    None,
    ComboBox,
    RadioButtons,
    ToggleSwitch,
    NumberBox,
    Slider,
    CalendarDatePicker,
    FilePicker,
    TabView
}

public enum ToolRulePresentationKind
{
    SelectionCards,
    ComboBox,
    RadioButtons,
    ToggleSwitch,
    Expander
}

public enum ToolLayoutKind
{
    TextWorkbench,
    FormatterWorkbench,
    CodecWorkbench,
    QueryDashboard,
    Dashboard,
    CalculatorForm,
    UnitConverter,
    ReferenceBrowser,
    FileWorkflow,
    MediaNative,
    BrowserNative,
    RandomCinema,
    SystemLauncher,
    SecurityWorkbench
}

public enum ToolAssistPanelMode
{
    Hidden,
    RulesOnly,
    SourceOnly,
    ExamplesOnly,
    RulesAndSource,
    Custom
}

public enum ToolInteractionMode
{
    ManualRun,
    AutoLoad,
    LivePreview,
    NativeLauncher,
    MediaViewer,
    ReferenceBrowser
}

public enum ToolPageExperienceKind
{
    LivePreview,
    OneShotTransform,
    FormCalculator,
    LookupBrowser,
    RemoteDashboard,
    FileWorkflow,
    NativeWindow,
    SystemLauncher,
    MediaViewer
}

public enum ToolPageDensity
{
    Compact,
    Expanded
}

public enum ToolResultPriority
{
    Value,
    List,
    Table,
    Preview,
    Document,
    Status,
    Media
}

public enum ToolResultKind
{
    PlainText,
    CodePreview,
    JsonTree,
    KeyValueCards,
    Table,
    RankedList,
    NewsCards,
    ImagePreview,
    LinkCards,
    FileCards,
    Diff,
    StatusList,
    ColorSwatch,
    CalculatorTable,
    SystemCards,
    Media,
    ReferenceRows
}

public sealed record ToolTextPair(string Zh, string En)
{
    public string ForLanguage(string? language)
    {
        return LanguagePreference.IsEnglish(language) ? En : Zh;
    }
}

public sealed record ToolRuleSpec(
    string Key,
    string Label,
    ToolRulePresentationKind Presentation,
    IReadOnlyList<ToolRuleOptionSpec> Options,
    bool DefaultCollapsed = true,
    bool IsRequired = false,
    ToolTextPair? LocalizedLabel = null);

public sealed record ToolRuleOptionSpec(
    string Label,
    string Value,
    string Description = "",
    ToolTextPair? LocalizedLabel = null,
    ToolTextPair? LocalizedDescription = null);

public sealed record ToolParameterSpec(
    string Key,
    string Label,
    ToolParameterControlKind Control,
    string Placeholder,
    IReadOnlyList<ToolRuleOptionSpec> Options,
    string DefaultValue = "",
    bool IsRequired = false,
    ToolTextPair? LocalizedLabel = null,
    ToolTextPair? LocalizedPlaceholder = null);

public sealed record ToolPageSpec(
    string ToolId,
    ToolPrimaryInputKind PrimaryInput,
    ToolLayoutKind Layout,
    ToolResultKind Result,
    IReadOnlyList<ToolParameterControlKind> ParameterControls,
    bool AutoRunOnOpen,
    bool RequiresFilePicker,
    bool UseVirtualizedResults,
    IReadOnlyList<ToolRuleSpec> Rules,
    IReadOnlyList<ToolParameterSpec> Parameters,
    string EmptyState,
    string ErrorHint,
    ToolAssistPanelMode AssistPanelMode,
    ToolInteractionMode InteractionMode,
    ToolPageExperienceKind PageExperience,
    ToolPageDensity PageDensity,
    string PrimaryActionLabel,
    IReadOnlyList<string> SecondaryActions,
    ToolResultPriority ResultPriority,
    bool ShowInputHeader,
    bool ShowDescription,
    string DefaultFocusTarget)
{
    public bool UsesComboBox => ParameterControls.Contains(ToolParameterControlKind.ComboBox);

    public bool UsesRadioButtons => ParameterControls.Contains(ToolParameterControlKind.RadioButtons);

    public bool UsesDatePicker => ParameterControls.Contains(ToolParameterControlKind.CalendarDatePicker);

    public bool UsesNumberBox => ParameterControls.Contains(ToolParameterControlKind.NumberBox);
}

public static class ToolPageSpecCatalog
{
    public static ToolPageSpec For(IToolModule module)
    {
        var id = module.Id;
        return id switch
        {
            "safe_browser" => Spec(id, ToolPrimaryInputKind.Url, ToolLayoutKind.BrowserNative, ToolResultKind.LinkCards, controls: [ToolParameterControlKind.ComboBox]),
            "media_player" => Spec(id, ToolPrimaryInputKind.FilePath, ToolLayoutKind.MediaNative, ToolResultKind.Media, controls: [ToolParameterControlKind.FilePicker], filePicker: true),
            "random_cinema" => Spec(id, ToolPrimaryInputKind.None, ToolLayoutKind.RandomCinema, ToolResultKind.Media, controls: [ToolParameterControlKind.TabView], autoRun: true, virtualized: true),
            "system_tool" => Spec(id, ToolPrimaryInputKind.FixedOptions, ToolLayoutKind.SystemLauncher, ToolResultKind.SystemCards, controls: [ToolParameterControlKind.ComboBox], autoRun: false, virtualized: true),
            "system_info" or "pc_benchmark" => Spec(id, ToolPrimaryInputKind.None, ToolLayoutKind.Dashboard, ToolResultKind.SystemCards, controls: [ToolParameterControlKind.RadioButtons], autoRun: true),
            "serial_terminal" => Spec(id, ToolPrimaryInputKind.None, ToolLayoutKind.SystemLauncher, ToolResultKind.StatusList, controls: [ToolParameterControlKind.None], autoRun: false),
            "timestamp_converter" => Spec(id, ToolPrimaryInputKind.Text, ToolLayoutKind.CalculatorForm, ToolResultKind.CalculatorTable, controls: [ToolParameterControlKind.RadioButtons]),
            "number_base" or "number_base_converter" => Spec(id, ToolPrimaryInputKind.Text, ToolLayoutKind.UnitConverter, ToolResultKind.CalculatorTable, controls: [ToolParameterControlKind.ComboBox]),

            "json_formatter" or "csv_json_converter" or "yaml_json_converter" or "json_path_helper" or "jwt_decoder" =>
                Spec(id, TextInput(id), ToolLayoutKind.FormatterWorkbench, ToolResultKind.JsonTree, controls: [ToolParameterControlKind.RadioButtons]),
            "xml_formatter" or "sql_formatter" or "html_minifier" or "js_obfuscator" or "html_text_extractor" =>
                Spec(id, ToolPrimaryInputKind.MultilineText, ToolLayoutKind.FormatterWorkbench, ToolResultKind.CodePreview, controls: [ToolParameterControlKind.RadioButtons]),
            "base64_codec" or "compression_codec" or "url_codec" or "html_entity" or "unicode_codec" or "punycode_codec" or "query_builder" or "form_urlencoded_builder" or "key_value_converter" =>
                Spec(id, TextInput(id), ToolLayoutKind.CodecWorkbench, ToolResultKind.KeyValueCards, controls: [ToolParameterControlKind.RadioButtons]),
            "regex_tool" or "cron_helper" =>
                Spec(id, ToolPrimaryInputKind.MultilineText, ToolLayoutKind.FormatterWorkbench, ToolResultKind.Table, controls: [ToolParameterControlKind.RadioButtons, ToolParameterControlKind.ToggleSwitch]),

            "weather" or "train_query" or "dns_query" or "ip_lookup" or "ip_info" or "rdap_domain_lookup" or "rdap_ip_lookup" or "domain_price" or "http_diagnostic" or "url_redirect_trace" or "url_inspector" or "domain_extractor" or "cidr_subnet_calculator" or "wx_domain_check" =>
                Spec(id, QueryInput(id), ToolLayoutKind.QueryDashboard, ToolResultKind.KeyValueCards, controls: [ToolParameterControlKind.ComboBox], autoRun: !module.Metadata.OfflineCapable, virtualized: true),
            "ai_latest_news" =>
                Spec(id, ToolPrimaryInputKind.Token, ToolLayoutKind.QueryDashboard, ToolResultKind.NewsCards, controls: [ToolParameterControlKind.None], autoRun: false, virtualized: true),
            "city_route_query" =>
                Spec(id, ToolPrimaryInputKind.Query, ToolLayoutKind.QueryDashboard, ToolResultKind.KeyValueCards, controls: [ToolParameterControlKind.None], autoRun: false, virtualized: true),
            "hotboard" =>
                Spec(id, ToolPrimaryInputKind.FixedOptions, ToolLayoutKind.Dashboard, ToolResultKind.RankedList, controls: [ToolParameterControlKind.ComboBox], autoRun: false, virtualized: true),
            "history_today" =>
                Spec(id, ToolPrimaryInputKind.Query, ToolLayoutKind.Dashboard, ToolResultKind.RankedList, controls: [ToolParameterControlKind.None], autoRun: true, virtualized: true),
            "baidu_hot" or "bili_hot" or "zhihu_hot" or "cctv_news" or "tech_news" or "football_news" or "movie_box_office" or "earthquake_info" or "gold_price" or "oil_price" =>
                Spec(id, ToolPrimaryInputKind.None, ToolLayoutKind.Dashboard, DashboardResult(id), controls: [ToolParameterControlKind.ComboBox], autoRun: true, virtualized: true),
            "mime_lookup" or "http_status_lookup" or "port_lookup" or "dns_record_lookup" or "unicode_block_lookup" or "charset_lookup" or "timezone_abbr_lookup" or "regex_preset_lookup" or "magic_number_lookup" or "car_info" or "sanguosha_skin" =>
                Spec(id, ToolPrimaryInputKind.FixedOptions, ToolLayoutKind.ReferenceBrowser, ToolResultKind.ReferenceRows, controls: [ToolParameterControlKind.ComboBox], autoRun: true, virtualized: true),

            "calculator_tool" => Spec(id, ToolPrimaryInputKind.Text, ToolLayoutKind.CalculatorForm, ToolResultKind.CalculatorTable, controls: [ToolParameterControlKind.RadioButtons]),
            "unit_converter" or "length_converter" or "weight_converter" or "temperature_converter" or "speed_converter" or "area_converter" or "volume_converter" or "data_size_converter" or "time_duration_converter" =>
                Spec(id, ToolPrimaryInputKind.Number, ToolLayoutKind.UnitConverter, ToolResultKind.CalculatorTable, controls: [ToolParameterControlKind.NumberBox, ToolParameterControlKind.ComboBox]),
            "bmi_calculator" or "percentage_calculator" or "percentage_change_calculator" or "discount_calculator" or "tax_calculator" or "ratio_simplifier" or "average_calculator" or "median_calculator" or "gcd_lcm_calculator" or "permutation_calculator" or "combination_calculator" or "simple_interest_calculator" or "compound_interest_calculator" or "loan_emi_calculator" =>
                Spec(id, NumericInput(id), ToolLayoutKind.CalculatorForm, ToolResultKind.CalculatorTable, controls: [ToolParameterControlKind.NumberBox]),
            "date_difference_calculator" or "workday_calculator" or "age_calculator" =>
                Spec(id, ToolPrimaryInputKind.DateRange, ToolLayoutKind.CalculatorForm, ToolResultKind.CalculatorTable, controls: [ToolParameterControlKind.CalendarDatePicker]),
            "shelf_life" => Spec(id, ToolPrimaryInputKind.DateRange, ToolLayoutKind.CalculatorForm, ToolResultKind.KeyValueCards, controls: [ToolParameterControlKind.CalendarDatePicker, ToolParameterControlKind.NumberBox]),

            "qrcode_scanner" or "image_processor" or "image_metadata_inspector" or "archive_tool" or "hash_manifest_builder" or "hash_manifest_verify" =>
                Spec(id, ToolPrimaryInputKind.FilePath, ToolLayoutKind.FileWorkflow, FileResult(id), controls: [ToolParameterControlKind.FilePicker, ToolParameterControlKind.RadioButtons], filePicker: true, virtualized: true),
            "qr_generator" => Spec(id, ToolPrimaryInputKind.MultilineText, ToolLayoutKind.FileWorkflow, ToolResultKind.ImagePreview, controls: [ToolParameterControlKind.RadioButtons]),
            "color_picker" => Spec(id, ToolPrimaryInputKind.Color, ToolLayoutKind.TextWorkbench, ToolResultKind.ColorSwatch, controls: [ToolParameterControlKind.ComboBox]),
            "color_contrast_checker" => Spec(id, ToolPrimaryInputKind.Text, ToolLayoutKind.TextWorkbench, ToolResultKind.KeyValueCards, controls: [ToolParameterControlKind.RadioButtons]),
            "totp_generator" => Spec(id, ToolPrimaryInputKind.Token, ToolLayoutKind.SecurityWorkbench, ToolResultKind.KeyValueCards, controls: [ToolParameterControlKind.RadioButtons]),
            "markdown_preview" => Spec(id, ToolPrimaryInputKind.MultilineText, ToolLayoutKind.FormatterWorkbench, ToolResultKind.CodePreview, controls: [ToolParameterControlKind.RadioButtons]),
            "qq_avatar" => Spec(id, ToolPrimaryInputKind.Query, ToolLayoutKind.QueryDashboard, ToolResultKind.ImagePreview, controls: [ToolParameterControlKind.None], autoRun: false),
            "html_js_playground" => Spec(id, ToolPrimaryInputKind.MultilineText, ToolLayoutKind.BrowserNative, ToolResultKind.CodePreview, controls: [ToolParameterControlKind.None], autoRun: false),
            "ascii_art" or "password_generator" or "uuid_generator" or "ulid_generator" or "random_generator" or "random_picker" =>
                Spec(id, GeneratorInput(id), ToolLayoutKind.TextWorkbench, ToolResultKind.PlainText, controls: [ToolParameterControlKind.NumberBox, ToolParameterControlKind.RadioButtons]),

            _ when module.Metadata.Category == ToolCategory.Security =>
                Spec(id, ToolPrimaryInputKind.MultilineText, ToolLayoutKind.SecurityWorkbench, SecurityResult(id), controls: [ToolParameterControlKind.RadioButtons, ToolParameterControlKind.ToggleSwitch]),
            _ when module.Metadata.Category == ToolCategory.Text =>
                Spec(id, ToolPrimaryInputKind.MultilineText, ToolLayoutKind.TextWorkbench, TextResult(id), controls: [ToolParameterControlKind.RadioButtons, ToolParameterControlKind.ToggleSwitch], virtualized: true),
            _ when module.Metadata.Category == ToolCategory.Image =>
                Spec(id, ToolPrimaryInputKind.FilePath, ToolLayoutKind.FileWorkflow, ToolResultKind.FileCards, controls: [ToolParameterControlKind.FilePicker, ToolParameterControlKind.RadioButtons], filePicker: true),
            _ when module.Metadata.Category == ToolCategory.Network =>
                Spec(id, ToolPrimaryInputKind.Query, ToolLayoutKind.QueryDashboard, ToolResultKind.LinkCards, controls: [ToolParameterControlKind.ComboBox], autoRun: !module.Metadata.OfflineCapable),
            _ when module.Metadata.Category == ToolCategory.Data =>
                Spec(id, ToolPrimaryInputKind.None, ToolLayoutKind.Dashboard, ToolResultKind.RankedList, controls: [ToolParameterControlKind.ComboBox], autoRun: true, virtualized: true),
            _ when module.Metadata.Category == ToolCategory.Calculator =>
                Spec(id, ToolPrimaryInputKind.Number, ToolLayoutKind.CalculatorForm, ToolResultKind.CalculatorTable, controls: [ToolParameterControlKind.NumberBox]),
            _ when module.Metadata.Category == ToolCategory.Design =>
                Spec(id, ToolPrimaryInputKind.Text, ToolLayoutKind.TextWorkbench, ToolResultKind.ImagePreview, controls: [ToolParameterControlKind.RadioButtons]),
            _ when module.Metadata.Category == ToolCategory.Life =>
                Spec(id, ToolPrimaryInputKind.Query, ToolLayoutKind.QueryDashboard, ToolResultKind.KeyValueCards, controls: [ToolParameterControlKind.ComboBox]),
            _ when module.Metadata.Category == ToolCategory.System =>
                Spec(id, ToolPrimaryInputKind.FixedOptions, ToolLayoutKind.SystemLauncher, ToolResultKind.SystemCards, controls: [ToolParameterControlKind.ComboBox]),
            _ =>
                Spec(id, ToolPrimaryInputKind.MultilineText, ToolLayoutKind.TextWorkbench, ToolResultKind.PlainText, controls: [ToolParameterControlKind.RadioButtons])
        };
    }

    public static IReadOnlyDictionary<string, ToolPageSpec> CreateFor(ToolCatalog catalog)
    {
        return catalog.Modules.ToDictionary(module => module.Id, For, StringComparer.OrdinalIgnoreCase);
    }

    private static ToolPageSpec Spec(
        string id,
        ToolPrimaryInputKind input,
        ToolLayoutKind layout,
        ToolResultKind result,
        IReadOnlyList<ToolParameterControlKind>? controls = null,
        bool autoRun = false,
        bool filePicker = false,
        bool virtualized = false)
    {
        return new ToolPageSpec(
            id,
            input,
            layout,
            result,
            controls is { Count: > 0 } ? controls : [ToolParameterControlKind.None],
            autoRun,
            filePicker,
            virtualized,
            BuildRules(id, input, controls ?? [ToolParameterControlKind.None]),
            BuildParameters(id, input, controls ?? [ToolParameterControlKind.None]),
            input == ToolPrimaryInputKind.None ? "Open this tool to refresh and render live data." : "Enter values or choose options, then run the tool.",
            "The tool could not finish. Check the input and try again.",
            ResolveAssistPanelMode(id, input, layout, controls ?? [ToolParameterControlKind.None], autoRun, filePicker),
            ResolveInteractionMode(id, input, layout, autoRun),
            ResolvePageExperience(id, input, layout, autoRun, filePicker),
            ResolvePageDensity(result, layout, virtualized),
            ResolvePrimaryActionLabel(id, input, layout, autoRun, filePicker),
            ResolveSecondaryActions(input, filePicker, autoRun),
            ResolveResultPriority(result),
            ShouldShowInputHeader(input, layout, autoRun),
            ShouldShowDescription(input, layout, autoRun),
            ResolveDefaultFocusTarget(input, layout));
    }

    private static ToolPageExperienceKind ResolvePageExperience(
        string id,
        ToolPrimaryInputKind input,
        ToolLayoutKind layout,
        bool autoRun,
        bool filePicker)
    {
        if (id == "color_picker")
        {
            return ToolPageExperienceKind.LivePreview;
        }

        if (id == "hotboard")
        {
            return ToolPageExperienceKind.RemoteDashboard;
        }

        return layout switch
        {
            ToolLayoutKind.BrowserNative => ToolPageExperienceKind.NativeWindow,
            ToolLayoutKind.MediaNative or ToolLayoutKind.RandomCinema => ToolPageExperienceKind.MediaViewer,
            ToolLayoutKind.SystemLauncher => ToolPageExperienceKind.SystemLauncher,
            ToolLayoutKind.FileWorkflow => ToolPageExperienceKind.FileWorkflow,
            ToolLayoutKind.ReferenceBrowser => ToolPageExperienceKind.LookupBrowser,
            ToolLayoutKind.Dashboard or ToolLayoutKind.QueryDashboard when autoRun || input == ToolPrimaryInputKind.None => ToolPageExperienceKind.RemoteDashboard,
            ToolLayoutKind.CalculatorForm or ToolLayoutKind.UnitConverter => ToolPageExperienceKind.FormCalculator,
            _ when filePicker => ToolPageExperienceKind.FileWorkflow,
            _ => ToolPageExperienceKind.OneShotTransform
        };
    }

    private static ToolPageDensity ResolvePageDensity(ToolResultKind result, ToolLayoutKind layout, bool virtualized)
    {
        return virtualized ||
            layout is ToolLayoutKind.MediaNative or ToolLayoutKind.RandomCinema or ToolLayoutKind.FileWorkflow ||
            result is ToolResultKind.Table or ToolResultKind.RankedList or ToolResultKind.NewsCards or ToolResultKind.ReferenceRows or ToolResultKind.Media
                ? ToolPageDensity.Expanded
                : ToolPageDensity.Compact;
    }

    private static string ResolvePrimaryActionLabel(
        string id,
        ToolPrimaryInputKind input,
        ToolLayoutKind layout,
        bool autoRun,
        bool filePicker)
    {
        if (id == "color_picker")
        {
            return string.Empty;
        }

        if (id == "hotboard")
        {
            return "查询";
        }

        if (filePicker || layout == ToolLayoutKind.FileWorkflow)
        {
            return id is "qrcode_scanner" ? "扫描" : id is "qr_generator" ? "生成" : "处理";
        }

        if (layout == ToolLayoutKind.SystemLauncher)
        {
            return "打开";
        }

        if (autoRun || input == ToolPrimaryInputKind.None)
        {
            return "重新加载";
        }

        if (layout is ToolLayoutKind.FormatterWorkbench)
        {
            return "格式化";
        }

        if (layout is ToolLayoutKind.CodecWorkbench or ToolLayoutKind.UnitConverter)
        {
            return "转换";
        }

        if (layout is ToolLayoutKind.CalculatorForm)
        {
            return "计算";
        }

        if (layout is ToolLayoutKind.QueryDashboard)
        {
            return "查询";
        }

        if (id.Contains("generator", StringComparison.OrdinalIgnoreCase))
        {
            return "生成";
        }

        return "处理";
    }

    private static IReadOnlyList<string> ResolveSecondaryActions(ToolPrimaryInputKind input, bool filePicker, bool autoRun)
    {
        var actions = new List<string>();
        if (filePicker)
        {
            actions.Add("chooseFile");
        }
        if (input != ToolPrimaryInputKind.None)
        {
            actions.Add("clear");
        }
        actions.Add("copyResult");
        return actions;
    }

    private static ToolResultPriority ResolveResultPriority(ToolResultKind result)
    {
        return result switch
        {
            ToolResultKind.JsonTree or ToolResultKind.CodePreview or ToolResultKind.Diff => ToolResultPriority.Document,
            ToolResultKind.Table or ToolResultKind.CalculatorTable or ToolResultKind.ReferenceRows => ToolResultPriority.Table,
            ToolResultKind.RankedList or ToolResultKind.NewsCards => ToolResultPriority.List,
            ToolResultKind.ImagePreview or ToolResultKind.ColorSwatch => ToolResultPriority.Preview,
            ToolResultKind.FileCards or ToolResultKind.StatusList or ToolResultKind.SystemCards => ToolResultPriority.Status,
            ToolResultKind.Media => ToolResultPriority.Media,
            _ => ToolResultPriority.Value
        };
    }

    private static bool ShouldShowInputHeader(ToolPrimaryInputKind input, ToolLayoutKind layout, bool autoRun)
    {
        return input != ToolPrimaryInputKind.None && layout is not ToolLayoutKind.ReferenceBrowser && !autoRun;
    }

    private static bool ShouldShowDescription(ToolPrimaryInputKind input, ToolLayoutKind layout, bool autoRun)
    {
        return input is ToolPrimaryInputKind.MultilineText or ToolPrimaryInputKind.FilePath or ToolPrimaryInputKind.DateRange ||
            layout is ToolLayoutKind.FileWorkflow or ToolLayoutKind.SecurityWorkbench ||
            (!autoRun && input != ToolPrimaryInputKind.None);
    }

    private static string ResolveDefaultFocusTarget(ToolPrimaryInputKind input, ToolLayoutKind layout)
    {
        return input switch
        {
            ToolPrimaryInputKind.Query or ToolPrimaryInputKind.Url => "query",
            ToolPrimaryInputKind.Number or ToolPrimaryInputKind.NumberPair or ToolPrimaryInputKind.NumberTriple or ToolPrimaryInputKind.NumberQuad => "number",
            ToolPrimaryInputKind.DateRange => "date",
            ToolPrimaryInputKind.FilePath => "file",
            ToolPrimaryInputKind.FixedOptions => "parameter",
            _ when layout == ToolLayoutKind.ReferenceBrowser => "parameter",
            _ => "input"
        };
    }

    private static ToolAssistPanelMode ResolveAssistPanelMode(
        string id,
        ToolPrimaryInputKind input,
        ToolLayoutKind layout,
        IReadOnlyList<ToolParameterControlKind> controls,
        bool autoRun,
        bool filePicker)
    {
        if (id == "color_picker")
        {
            return ToolAssistPanelMode.Custom;
        }

        if (layout is ToolLayoutKind.BrowserNative or ToolLayoutKind.MediaNative or ToolLayoutKind.RandomCinema ||
            id is "system_info" or "pc_benchmark" or "system_tool")
        {
            return ToolAssistPanelMode.Hidden;
        }

        if (input == ToolPrimaryInputKind.None && autoRun)
        {
            return ToolAssistPanelMode.Hidden;
        }

        if (!filePicker && layout == ToolLayoutKind.QueryDashboard && autoRun)
        {
            return ToolAssistPanelMode.SourceOnly;
        }

        if (layout == ToolLayoutKind.ReferenceBrowser || id == "smart_search")
        {
            return ToolAssistPanelMode.Hidden;
        }

        if (id is "regex_tool" or "template_filler" or "batch_text_replace" or "qr_generator" or "path_breakdown" or "path_normalizer")
        {
            return ToolAssistPanelMode.ExamplesOnly;
        }

        if (filePicker ||
            id is "json_formatter" or "xml_formatter" or "sql_formatter" or "html_minifier" or "js_obfuscator"
                or "base64_codec" or "url_codec" or "html_entity" or "unicode_codec" or "punycode_codec"
                or "text_sorter" or "text_deduplicator" or "duplicate_detector" or "manifest_deduplicator"
                or "text_filter" or "keyword_counter" or "hash_generator" or "hmac_generator")
        {
            return ToolAssistPanelMode.RulesOnly;
        }

        return ToolAssistPanelMode.Hidden;
    }

    private static ToolInteractionMode ResolveInteractionMode(
        string id,
        ToolPrimaryInputKind input,
        ToolLayoutKind layout,
        bool autoRun)
    {
        if (id == "color_picker")
        {
            return ToolInteractionMode.LivePreview;
        }

        return layout switch
        {
            ToolLayoutKind.BrowserNative => ToolInteractionMode.NativeLauncher,
            ToolLayoutKind.MediaNative => ToolInteractionMode.MediaViewer,
            ToolLayoutKind.RandomCinema => ToolInteractionMode.MediaViewer,
            ToolLayoutKind.ReferenceBrowser => ToolInteractionMode.ReferenceBrowser,
            _ when autoRun || input == ToolPrimaryInputKind.None => ToolInteractionMode.AutoLoad,
            _ => ToolInteractionMode.ManualRun
        };
    }

    private static IReadOnlyList<ToolRuleSpec> BuildRules(
        string id,
        ToolPrimaryInputKind input,
        IReadOnlyList<ToolParameterControlKind> controls)
    {
        static ToolTextPair Text(string zh, string en) => new(zh, en);

        if (id is "json_formatter" or "xml_formatter" or "sql_formatter" or "html_minifier" or "js_obfuscator")
        {
            return
            [
                new ToolRuleSpec("mode", "Mode", ToolRulePresentationKind.RadioButtons,
                [
                    new("Format", "format", LocalizedLabel: Text("格式化", "Format")),
                    new("Minify", "minify", LocalizedLabel: Text("压缩", "Minify")),
                    new("Validate", "validate", LocalizedLabel: Text("校验", "Validate"))
                ], LocalizedLabel: Text("模式", "Mode"))
            ];
        }

        if (id is "base64_codec" or "url_codec" or "html_entity" or "unicode_codec" or "punycode_codec" or "query_builder" or "form_urlencoded_builder" or "key_value_converter")
        {
            return
            [
                new ToolRuleSpec("direction", "Direction", ToolRulePresentationKind.SelectionCards,
                [
                    new("Encode", "encode", LocalizedLabel: Text("编码", "Encode")),
                    new("Decode", "decode", LocalizedLabel: Text("解码", "Decode")),
                    new("Both", "both", LocalizedLabel: Text("双向", "Both"))
                ], LocalizedLabel: Text("方向", "Direction"))
            ];
        }

        if (id is "text_sorter" or "manifest_sorter")
        {
            return
            [
                new ToolRuleSpec("sort", "Sort order", ToolRulePresentationKind.RadioButtons,
                [
                    new("Ascending", "ascending", LocalizedLabel: Text("升序", "Ascending")),
                    new("Descending", "descending", LocalizedLabel: Text("降序", "Descending")),
                    new("Natural", "natural", LocalizedLabel: Text("自然排序", "Natural"))
                ], LocalizedLabel: Text("排序方式", "Sort order"))
            ];
        }

        if (id is "text_deduplicator" or "duplicate_detector" or "manifest_deduplicator")
        {
            return
            [
                new ToolRuleSpec("dedupe", "Deduplication", ToolRulePresentationKind.SelectionCards,
                [
                    new("Keep first", "first", LocalizedLabel: Text("保留首次出现", "Keep first")),
                    new("Keep last", "last", LocalizedLabel: Text("保留最后出现", "Keep last")),
                    new("Ignore case", "ignoreCase", LocalizedLabel: Text("忽略大小写", "Ignore case"))
                ], LocalizedLabel: Text("去重规则", "Deduplication")),
                new ToolRuleSpec("preserveOrder", "Keep original order", ToolRulePresentationKind.ToggleSwitch, [], LocalizedLabel: Text("保留原始顺序", "Keep original order"))
            ];
        }

        if (id is "text_filter" or "keyword_counter")
        {
            return
            [
                new ToolRuleSpec("match", "Match mode", ToolRulePresentationKind.RadioButtons,
                [
                    new("Contains", "contains", LocalizedLabel: Text("包含", "Contains")),
                    new("Regex", "regex", LocalizedLabel: Text("正则", "Regex")),
                    new("Exclude", "exclude", LocalizedLabel: Text("排除", "Exclude"))
                ], LocalizedLabel: Text("匹配模式", "Match mode"))
            ];
        }

        if (id is "hash_generator" or "hmac_generator" or "hash_manifest_builder" or "hash_manifest_verify")
        {
            return
            [
                new ToolRuleSpec("algorithm", "Algorithm", ToolRulePresentationKind.ComboBox,
                [
                    new("SHA256", "sha256"),
                    new("SHA512", "sha512"),
                    new("MD5", "md5")
                ], LocalizedLabel: Text("算法", "Algorithm"))
            ];
        }

        if (input == ToolPrimaryInputKind.FixedOptions || controls.Contains(ToolParameterControlKind.ComboBox))
        {
            return
            [
                new ToolRuleSpec("source", "Source", ToolRulePresentationKind.ComboBox,
                [
                    new("Default", "default", LocalizedLabel: Text("默认", "Default")),
                    new("All", "all", LocalizedLabel: Text("全部", "All"))
                ], LocalizedLabel: Text("来源", "Source"))
            ];
        }

        if (controls.Contains(ToolParameterControlKind.ToggleSwitch))
        {
            return [new ToolRuleSpec("strict", "Strict mode", ToolRulePresentationKind.ToggleSwitch, [], LocalizedLabel: Text("严格模式", "Strict mode"))];
        }

        return [];
    }

    private static IReadOnlyList<ToolParameterSpec> BuildParameters(
        string id,
        ToolPrimaryInputKind input,
        IReadOnlyList<ToolParameterControlKind> controls)
    {
        static ToolTextPair Text(string zh, string en) => new(zh, en);

        if (input == ToolPrimaryInputKind.None)
        {
            return [];
        }

        if (input == ToolPrimaryInputKind.FixedOptions || controls.Contains(ToolParameterControlKind.ComboBox))
        {
            return
            [
                new ToolParameterSpec(
                    "preset",
                    "Preset",
                    ToolParameterControlKind.ComboBox,
                    "Choose a preset",
                    BuildPresetOptions(id),
                    BuildPresetOptions(id).FirstOrDefault()?.Value ?? "",
                    LocalizedLabel: Text("预设", "Preset"),
                    LocalizedPlaceholder: Text("选择预设", "Choose a preset"))
            ];
        }

        if (input is ToolPrimaryInputKind.Number or ToolPrimaryInputKind.NumberPair or ToolPrimaryInputKind.NumberTriple or ToolPrimaryInputKind.NumberQuad)
        {
            return [new ToolParameterSpec("value", "Value", ToolParameterControlKind.NumberBox, "Enter a number", [], "1", true, Text("数值", "Value"), Text("输入数字", "Enter a number"))];
        }

        if (input == ToolPrimaryInputKind.DateRange)
        {
            return [new ToolParameterSpec("date", "Date", ToolParameterControlKind.CalendarDatePicker, "Choose date", [], string.Empty, true, Text("日期", "Date"), Text("选择日期", "Choose date"))];
        }

        if (input == ToolPrimaryInputKind.FilePath)
        {
            return [new ToolParameterSpec("path", "File path", ToolParameterControlKind.FilePicker, "Choose or paste a local file", [], string.Empty, true, Text("文件路径", "File path"), Text("选择或粘贴本地文件", "Choose or paste a local file"))];
        }

        return [new ToolParameterSpec("input", "Input", ToolParameterControlKind.None, "Enter input", [], string.Empty, false, Text("输入", "Input"), Text("输入内容", "Enter input"))];
    }

    private static IReadOnlyList<ToolRuleOptionSpec> BuildPresetOptions(string id)
    {
        static ToolTextPair Text(string zh, string en) => new(zh, en);

        return id switch
        {
            "system_tool" =>
            [
                new("System status", "status", LocalizedLabel: Text("系统状态", "System status")),
                new("Temporary folder", "temp", LocalizedLabel: Text("临时目录", "Temporary folder")),
                new("Processes", "process", LocalizedLabel: Text("进程", "Processes")),
                new("Environment variables", "env", LocalizedLabel: Text("环境变量", "Environment variables")),
                new("Remote Desktop", "rdp", LocalizedLabel: Text("远程桌面", "Remote Desktop")),
                new("Paint", "paint", LocalizedLabel: Text("画图", "Paint")),
                new("Calculator", "calculator", LocalizedLabel: Text("计算器", "Calculator")),
                new("Control Panel", "control_panel", LocalizedLabel: Text("控制面板", "Control Panel")),
                new("Registry Editor", "registry_editor", LocalizedLabel: Text("注册表编辑器", "Registry Editor")),
                new("Task Manager", "task_manager", LocalizedLabel: Text("任务管理器", "Task Manager")),
                new("Services", "services", LocalizedLabel: Text("服务", "Services"))
            ],
            "http_status_lookup" => [new("All status codes", "", LocalizedLabel: Text("全部状态码", "All status codes")), new("2xx", "2"), new("3xx", "3"), new("4xx", "4"), new("5xx", "5"), new("404", "404")],
            "port_lookup" => [new("All ports", "", LocalizedLabel: Text("全部端口", "All ports")), new("Web service", "http", LocalizedLabel: Text("网页服务", "Web service")), new("Mail service", "mail", LocalizedLabel: Text("邮件服务", "Mail service")), new("Database", "sql", LocalizedLabel: Text("数据库", "Database")), new("Remote access", "remote", LocalizedLabel: Text("远程连接", "Remote access"))],
            "mime_lookup" => [new("All MIME", "", LocalizedLabel: Text("全部 MIME", "All MIME")), new("Image", "image", LocalizedLabel: Text("图片", "Image")), new("Audio", "audio", LocalizedLabel: Text("音频", "Audio")), new("Video", "video", LocalizedLabel: Text("视频", "Video")), new("Text", "text", LocalizedLabel: Text("文本", "Text")), new("JSON", "json")],
            "hotboard" => [new("百度热搜", "百度"), new("哔哩哔哩", "哔哩哔哩"), new("知乎", "知乎"), new("微博", "微博"), new("抖音", "抖音"), new("今日头条", "今日头条"), new("36氪", "36氪"), new("少数派", "少数派"), new("GitHub", "GitHub"), new("V2EX", "V2EX")],
            "dns_record_lookup" => [new("All records", "", LocalizedLabel: Text("全部记录", "All records")), new("A", "A"), new("AAAA", "AAAA"), new("CNAME", "CNAME"), new("MX", "MX"), new("TXT", "TXT")],
            _ => [new("Default", "", LocalizedLabel: Text("默认", "Default"))]
        };
    }

    private static ToolPrimaryInputKind TextInput(string id)
    {
        return id is "base64_codec" or "url_codec" or "html_entity" or "unicode_codec" or "punycode_codec"
            ? ToolPrimaryInputKind.Text
            : ToolPrimaryInputKind.MultilineText;
    }

    private static ToolPrimaryInputKind QueryInput(string id)
    {
        return id is "http_diagnostic" or "url_inspector" ? ToolPrimaryInputKind.Url : ToolPrimaryInputKind.Query;
    }

    private static ToolPrimaryInputKind NumericInput(string id)
    {
        return id is "compound_interest_calculator"
            ? ToolPrimaryInputKind.NumberQuad
            : id is "loan_emi_calculator" or "simple_interest_calculator"
            ? ToolPrimaryInputKind.NumberTriple
            : id is "bmi_calculator" or "percentage_calculator" or "percentage_change_calculator" or "discount_calculator" or "tax_calculator" or "ratio_simplifier" or "permutation_calculator" or "combination_calculator"
                ? ToolPrimaryInputKind.NumberPair
                : ToolPrimaryInputKind.MultilineText;
    }

    private static ToolPrimaryInputKind GeneratorInput(string id)
    {
        return id is "uuid_generator" or "ulid_generator" or "password_generator" or "random_generator" or "random_picker"
            ? ToolPrimaryInputKind.Number
            : ToolPrimaryInputKind.Text;
    }

    private static ToolResultKind DashboardResult(string id)
    {
        return id is "cctv_news" or "tech_news" or "football_news" ? ToolResultKind.NewsCards : ToolResultKind.RankedList;
    }

    private static ToolResultKind FileResult(string id)
    {
        return id is "qrcode_scanner" or "image_processor" ? ToolResultKind.ImagePreview :
            id is "hash_manifest_verify" ? ToolResultKind.StatusList :
            ToolResultKind.FileCards;
    }

    private static ToolResultKind SecurityResult(string id)
    {
        return id is "hash_manifest_verify" ? ToolResultKind.StatusList : ToolResultKind.KeyValueCards;
    }

    private static ToolResultKind TextResult(string id)
    {
        return id is "text_diff" ? ToolResultKind.Diff :
            id is "markdown_table_normalizer" ? ToolResultKind.Table :
            id.Contains("statistics", StringComparison.OrdinalIgnoreCase) || id.Contains("counter", StringComparison.OrdinalIgnoreCase) || id.Contains("analyzer", StringComparison.OrdinalIgnoreCase)
                ? ToolResultKind.KeyValueCards
                : ToolResultKind.PlainText;
    }
}
