using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
using AxCopilot.Models;
using AxCopilot.Services;
using AxCopilot.Views;

namespace AxCopilot.ViewModels;

public class SettingsViewModel : INotifyPropertyChanged
{
	private readonly SettingsService _service;

	private string _hotkey;

	private int _maxResults;

	private double _opacity;

	private string _selectedThemeKey;

	private string _launcherPosition;

	private string _webSearchEngine;

	private bool _snippetAutoExpand;

	private string _language;

	private string _indexSpeed;

	private bool _showNumberBadges;

	private bool _enableFavorites;

	private bool _enableRecent;

	private bool _enableActionMode;

	private bool _closeOnFocusLost;

	private bool _showPrefixBadge;

	private bool _enableIconAnimation;

	private bool _enableRainbowGlow;

	private bool _enableSelectionGlow;

	private bool _enableRandomPlaceholder;

	private bool _showLauncherBorder;

	private bool _shortcutHelpUseThemeColor;

	private string _llmService;

	private bool _llmStreaming;

	private int _llmMaxContextTokens;

	private int _llmRetentionDays;

	private double _llmTemperature;

	private string _ollamaEndpoint = "http://localhost:11434";

	private string _ollamaApiKey = "";

	private string _ollamaModel = "";

	private string _vllmEndpoint = "";

	private string _vllmApiKey = "";

	private string _vllmModel = "";

	private string _geminiApiKey = "";

	private string _geminiModel = "gemini-2.5-flash";

	private string _claudeApiKey = "";

	private string _claudeModel = "claude-sonnet-4-6";

	private string _defaultAgentPermission;

	private string _defaultOutputFormat;

	private string _autoPreview;

	private int _maxAgentIterations;

	private int _maxRetryOnError;

	private string _agentLogLevel;

	private string _agentDecisionLevel = "detailed";

	private string _planMode = "off";

	private bool _enableMultiPassDocument;

	private bool _enableCoworkVerification;

	private bool _enableFilePathHighlight = true;

	private string _folderDataUsage;

	private bool _enableAuditLog;

	private bool _enableAgentMemory;

	private bool _enableProjectRules = true;

	private int _maxMemoryEntries;

	private bool _enableImageInput = true;

	private int _maxImageSizeKb = 5120;

	private bool _enableAutoRouter;

	private double _autoRouterConfidence = 0.7;

	private bool _enableToolHooks = true;

	private int _toolHookTimeoutMs = 10000;

	private bool _enableSkillSystem = true;

	private string _skillsFolderPath = "";

	private int _slashPopupPageSize = 6;

	private bool _enableDragDropAiActions = true;

	private bool _dragDropAutoSend;

	private bool _enableCodeReview = true;

	private bool _enableChatRainbowGlow;

	private bool _notifyOnComplete;

	private bool _showTips;

	private bool _devMode;

	private bool _devModeStepApproval;

	private bool _workflowVisualizer;

	private bool _freeTierMode;

	private int _freeTierDelaySeconds = 4;

	private bool _showTotalCallStats;

	private string _defaultMood = "modern";

	private bool _enableTextAction = true;

	private bool _enableFileDialogIntegration = false;

	private bool _enableClipboardAutoCategory = true;

	private int _maxPinnedClipboardItems = 20;

	private string _textActionTranslateLanguage = "auto";

	private int _maxSubAgents = 3;

	private string _pdfExportPath = "";

	private int _tipDurationSeconds = 5;

	private string _newBatchKey = "";

	private string _newBatchCommand = "";

	private bool _newBatchShowWindow;

	private string _newKey = "";

	private string _newDescription = "";

	private string _newTarget = "";

	private string _newType = "app";

	private int _customWindowCornerRadius = 20;

	private int _customItemCornerRadius = 10;

	private static readonly HashSet<string> ReservedPrefixes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
	{
		"=", "?", "#", "$", ";", "@", "~", ">", "!", "emoji",
		"color", "recent", "note", "uninstall", "kill", "media", "info", "*", "json", "encode",
		"port", "env", "snap", "help", "pick", "date", "svc", "pipe", "journal", "routine",
		"batch", "diff", "win", "stats", "fav", "rename", "monitor", "scaffold"
	};

	private string _newSnippetKey = "";

	private string _newSnippetName = "";

	private string _newSnippetContent = "";

	private bool _clipboardEnabled;

	private int _clipboardMaxItems;

	private string _capPrefix = "cap";

	private bool _capGlobalHotkeyEnabled;

	private string _capGlobalHotkey = "PrintScreen";

	private string _capGlobalMode = "screen";

	private int _capScrollDelayMs = 120;

	private bool _reminderEnabled;

	private string _reminderCorner = "bottom-right";

	private int _reminderIntervalMinutes = 60;

	private int _reminderDisplaySeconds = 15;

	private bool _sysShowLock;

	private bool _sysShowSleep;

	private bool _sysShowRestart;

	private bool _sysShowShutdown;

	private bool _sysShowHibernate;

	private bool _sysShowLogout;

	private bool _sysShowRecycleBin;

	private string _aliasLock = "";

	private string _aliasSleep = "";

	private string _aliasRestart = "";

	private string _aliasShutdown = "";

	private string _aliasHibernate = "";

	private string _aliasLogout = "";

	private string _aliasRecycle = "";

	internal SettingsService Service => _service;

	public CodeSettings Code => _service.Settings.Llm.Code;

	public ObservableCollection<RegisteredModelRow> RegisteredModels { get; } = new ObservableCollection<RegisteredModelRow>();

	public string LlmService
	{
		get
		{
			return _llmService;
		}
		set
		{
			_llmService = value;
			OnPropertyChanged("LlmService");
			OnPropertyChanged("IsInternalService");
			OnPropertyChanged("IsExternalService");
			OnPropertyChanged("NeedsEndpoint");
			OnPropertyChanged("NeedsApiKey");
			OnPropertyChanged("IsGeminiSelected");
			OnPropertyChanged("IsClaudeSelected");
		}
	}

	public bool IsInternalService
	{
		get
		{
			string llmService = _llmService;
			if (llmService == "ollama" || llmService == "vllm")
			{
				return true;
			}
			return false;
		}
	}

	public bool IsExternalService
	{
		get
		{
			string llmService = _llmService;
			if (llmService == "gemini" || llmService == "claude")
			{
				return true;
			}
			return false;
		}
	}

	public bool NeedsEndpoint
	{
		get
		{
			string llmService = _llmService;
			if (llmService == "ollama" || llmService == "vllm")
			{
				return true;
			}
			return false;
		}
	}

	public bool NeedsApiKey => !(_llmService == "ollama");

	public bool IsGeminiSelected => _llmService == "gemini";

	public bool IsClaudeSelected => _llmService == "claude";

	public string OllamaEndpoint
	{
		get
		{
			return _ollamaEndpoint;
		}
		set
		{
			_ollamaEndpoint = value;
			OnPropertyChanged("OllamaEndpoint");
		}
	}

	public string OllamaApiKey
	{
		get
		{
			return _ollamaApiKey;
		}
		set
		{
			_ollamaApiKey = value;
			OnPropertyChanged("OllamaApiKey");
		}
	}

	public string OllamaModel
	{
		get
		{
			return _ollamaModel;
		}
		set
		{
			_ollamaModel = value;
			OnPropertyChanged("OllamaModel");
		}
	}

	public string VllmEndpoint
	{
		get
		{
			return _vllmEndpoint;
		}
		set
		{
			_vllmEndpoint = value;
			OnPropertyChanged("VllmEndpoint");
		}
	}

	public string VllmApiKey
	{
		get
		{
			return _vllmApiKey;
		}
		set
		{
			_vllmApiKey = value;
			OnPropertyChanged("VllmApiKey");
		}
	}

	public string VllmModel
	{
		get
		{
			return _vllmModel;
		}
		set
		{
			_vllmModel = value;
			OnPropertyChanged("VllmModel");
		}
	}

	public string GeminiApiKey
	{
		get
		{
			return _geminiApiKey;
		}
		set
		{
			_geminiApiKey = value;
			OnPropertyChanged("GeminiApiKey");
		}
	}

	public string GeminiModel
	{
		get
		{
			return _geminiModel;
		}
		set
		{
			_geminiModel = value;
			OnPropertyChanged("GeminiModel");
		}
	}

	public string ClaudeApiKey
	{
		get
		{
			return _claudeApiKey;
		}
		set
		{
			_claudeApiKey = value;
			OnPropertyChanged("ClaudeApiKey");
		}
	}

	public string ClaudeModel
	{
		get
		{
			return _claudeModel;
		}
		set
		{
			_claudeModel = value;
			OnPropertyChanged("ClaudeModel");
		}
	}

	public bool LlmStreaming
	{
		get
		{
			return _llmStreaming;
		}
		set
		{
			_llmStreaming = value;
			OnPropertyChanged("LlmStreaming");
		}
	}

	public int LlmMaxContextTokens
	{
		get
		{
			return _llmMaxContextTokens;
		}
		set
		{
			_llmMaxContextTokens = value;
			OnPropertyChanged("LlmMaxContextTokens");
		}
	}

	public int LlmRetentionDays
	{
		get
		{
			return _llmRetentionDays;
		}
		set
		{
			_llmRetentionDays = value;
			OnPropertyChanged("LlmRetentionDays");
		}
	}

	public double LlmTemperature
	{
		get
		{
			return _llmTemperature;
		}
		set
		{
			_llmTemperature = Math.Round(Math.Clamp(value, 0.0, 2.0), 1);
			OnPropertyChanged("LlmTemperature");
		}
	}

	public string DefaultAgentPermission
	{
		get
		{
			return _defaultAgentPermission;
		}
		set
		{
			_defaultAgentPermission = value;
			OnPropertyChanged("DefaultAgentPermission");
		}
	}

	public string DefaultOutputFormat
	{
		get
		{
			return _defaultOutputFormat;
		}
		set
		{
			_defaultOutputFormat = value;
			OnPropertyChanged("DefaultOutputFormat");
		}
	}

	public string AutoPreview
	{
		get
		{
			return _autoPreview;
		}
		set
		{
			_autoPreview = value;
			OnPropertyChanged("AutoPreview");
		}
	}

	public int MaxAgentIterations
	{
		get
		{
			return _maxAgentIterations;
		}
		set
		{
			_maxAgentIterations = Math.Clamp(value, 1, 100);
			OnPropertyChanged("MaxAgentIterations");
		}
	}

	public int MaxRetryOnError
	{
		get
		{
			return _maxRetryOnError;
		}
		set
		{
			_maxRetryOnError = Math.Clamp(value, 0, 10);
			OnPropertyChanged("MaxRetryOnError");
		}
	}

	public string AgentLogLevel
	{
		get
		{
			return _agentLogLevel;
		}
		set
		{
			_agentLogLevel = value;
			OnPropertyChanged("AgentLogLevel");
		}
	}

	public string AgentDecisionLevel
	{
		get
		{
			return _agentDecisionLevel;
		}
		set
		{
			_agentDecisionLevel = value;
			OnPropertyChanged("AgentDecisionLevel");
		}
	}

	public string PlanMode
	{
		get
		{
			return _planMode;
		}
		set
		{
			_planMode = value;
			OnPropertyChanged("PlanMode");
		}
	}

	public bool EnableMultiPassDocument
	{
		get
		{
			return _enableMultiPassDocument;
		}
		set
		{
			_enableMultiPassDocument = value;
			OnPropertyChanged("EnableMultiPassDocument");
		}
	}

	public bool EnableCoworkVerification
	{
		get
		{
			return _enableCoworkVerification;
		}
		set
		{
			_enableCoworkVerification = value;
			OnPropertyChanged("EnableCoworkVerification");
		}
	}

	public bool EnableFilePathHighlight
	{
		get
		{
			return _enableFilePathHighlight;
		}
		set
		{
			_enableFilePathHighlight = value;
			OnPropertyChanged("EnableFilePathHighlight");
		}
	}

	public string FolderDataUsage
	{
		get
		{
			return _folderDataUsage;
		}
		set
		{
			_folderDataUsage = value;
			OnPropertyChanged("FolderDataUsage");
		}
	}

	public bool EnableAuditLog
	{
		get
		{
			return _enableAuditLog;
		}
		set
		{
			_enableAuditLog = value;
			OnPropertyChanged("EnableAuditLog");
		}
	}

	public bool EnableAgentMemory
	{
		get
		{
			return _enableAgentMemory;
		}
		set
		{
			_enableAgentMemory = value;
			OnPropertyChanged("EnableAgentMemory");
		}
	}

	public bool EnableProjectRules
	{
		get
		{
			return _enableProjectRules;
		}
		set
		{
			_enableProjectRules = value;
			OnPropertyChanged("EnableProjectRules");
		}
	}

	public int MaxMemoryEntries
	{
		get
		{
			return _maxMemoryEntries;
		}
		set
		{
			_maxMemoryEntries = value;
			OnPropertyChanged("MaxMemoryEntries");
		}
	}

	public bool EnableImageInput
	{
		get
		{
			return _enableImageInput;
		}
		set
		{
			_enableImageInput = value;
			OnPropertyChanged("EnableImageInput");
		}
	}

	public int MaxImageSizeKb
	{
		get
		{
			return _maxImageSizeKb;
		}
		set
		{
			_maxImageSizeKb = value;
			OnPropertyChanged("MaxImageSizeKb");
		}
	}

	public bool EnableAutoRouter
	{
		get
		{
			return _enableAutoRouter;
		}
		set
		{
			_enableAutoRouter = value;
			OnPropertyChanged("EnableAutoRouter");
		}
	}

	public double AutoRouterConfidence
	{
		get
		{
			return _autoRouterConfidence;
		}
		set
		{
			_autoRouterConfidence = value;
			OnPropertyChanged("AutoRouterConfidence");
		}
	}

	public bool EnableToolHooks
	{
		get
		{
			return _enableToolHooks;
		}
		set
		{
			_enableToolHooks = value;
			OnPropertyChanged("EnableToolHooks");
		}
	}

	public int ToolHookTimeoutMs
	{
		get
		{
			return _toolHookTimeoutMs;
		}
		set
		{
			_toolHookTimeoutMs = value;
			OnPropertyChanged("ToolHookTimeoutMs");
		}
	}

	public bool EnableSkillSystem
	{
		get
		{
			return _enableSkillSystem;
		}
		set
		{
			_enableSkillSystem = value;
			OnPropertyChanged("EnableSkillSystem");
		}
	}

	public string SkillsFolderPath
	{
		get
		{
			return _skillsFolderPath;
		}
		set
		{
			_skillsFolderPath = value;
			OnPropertyChanged("SkillsFolderPath");
		}
	}

	public int SlashPopupPageSize
	{
		get
		{
			return _slashPopupPageSize;
		}
		set
		{
			_slashPopupPageSize = Math.Clamp(value, 3, 10);
			OnPropertyChanged("SlashPopupPageSize");
		}
	}

	public bool EnableDragDropAiActions
	{
		get
		{
			return _enableDragDropAiActions;
		}
		set
		{
			_enableDragDropAiActions = value;
			OnPropertyChanged("EnableDragDropAiActions");
		}
	}

	public bool DragDropAutoSend
	{
		get
		{
			return _dragDropAutoSend;
		}
		set
		{
			_dragDropAutoSend = value;
			OnPropertyChanged("DragDropAutoSend");
		}
	}

	public bool EnableCodeReview
	{
		get
		{
			return _enableCodeReview;
		}
		set
		{
			_enableCodeReview = value;
			OnPropertyChanged("EnableCodeReview");
		}
	}

	public bool EnableChatRainbowGlow
	{
		get
		{
			return _enableChatRainbowGlow;
		}
		set
		{
			_enableChatRainbowGlow = value;
			OnPropertyChanged("EnableChatRainbowGlow");
		}
	}

	public bool NotifyOnComplete
	{
		get
		{
			return _notifyOnComplete;
		}
		set
		{
			_notifyOnComplete = value;
			OnPropertyChanged("NotifyOnComplete");
		}
	}

	public bool ShowTips
	{
		get
		{
			return _showTips;
		}
		set
		{
			_showTips = value;
			OnPropertyChanged("ShowTips");
		}
	}

	public bool DevMode
	{
		get
		{
			return _devMode;
		}
		set
		{
			_devMode = value;
			OnPropertyChanged("DevMode");
		}
	}

	public bool DevModeStepApproval
	{
		get
		{
			return _devModeStepApproval;
		}
		set
		{
			_devModeStepApproval = value;
			OnPropertyChanged("DevModeStepApproval");
		}
	}

	public bool WorkflowVisualizer
	{
		get
		{
			return _workflowVisualizer;
		}
		set
		{
			_workflowVisualizer = value;
			OnPropertyChanged("WorkflowVisualizer");
		}
	}

	public bool FreeTierMode
	{
		get
		{
			return _freeTierMode;
		}
		set
		{
			_freeTierMode = value;
			OnPropertyChanged("FreeTierMode");
		}
	}

	public int FreeTierDelaySeconds
	{
		get
		{
			return _freeTierDelaySeconds;
		}
		set
		{
			_freeTierDelaySeconds = value;
			OnPropertyChanged("FreeTierDelaySeconds");
		}
	}

	public bool ShowTotalCallStats
	{
		get
		{
			return _showTotalCallStats;
		}
		set
		{
			_showTotalCallStats = value;
			OnPropertyChanged("ShowTotalCallStats");
		}
	}

	public string DefaultMood
	{
		get
		{
			return _defaultMood;
		}
		set
		{
			_defaultMood = value;
			OnPropertyChanged("DefaultMood");
		}
	}

	public ObservableCollection<string> BlockedPaths { get; } = new ObservableCollection<string>();

	public ObservableCollection<string> BlockedExtensions { get; } = new ObservableCollection<string>();

	public string Hotkey
	{
		get
		{
			return _hotkey;
		}
		set
		{
			_hotkey = value;
			OnPropertyChanged("Hotkey");
		}
	}

	public int MaxResults
	{
		get
		{
			return _maxResults;
		}
		set
		{
			_maxResults = value;
			OnPropertyChanged("MaxResults");
		}
	}

	public double Opacity
	{
		get
		{
			return _opacity;
		}
		set
		{
			_opacity = value;
			OnPropertyChanged("Opacity");
			OnPropertyChanged("OpacityPercent");
		}
	}

	public int OpacityPercent => (int)Math.Round(_opacity * 100.0);

	public string SelectedThemeKey
	{
		get
		{
			return _selectedThemeKey;
		}
		set
		{
			_selectedThemeKey = value;
			OnPropertyChanged("SelectedThemeKey");
			OnPropertyChanged("IsCustomTheme");
			foreach (ThemeCardModel themeCard in ThemeCards)
			{
				themeCard.IsSelected = themeCard.Key == value;
			}
		}
	}

	public bool IsCustomTheme => _selectedThemeKey == "custom";

	public string LauncherPosition
	{
		get
		{
			return _launcherPosition;
		}
		set
		{
			_launcherPosition = value;
			OnPropertyChanged("LauncherPosition");
		}
	}

	public string WebSearchEngine
	{
		get
		{
			return _webSearchEngine;
		}
		set
		{
			_webSearchEngine = value;
			OnPropertyChanged("WebSearchEngine");
		}
	}

	public bool SnippetAutoExpand
	{
		get
		{
			return _snippetAutoExpand;
		}
		set
		{
			_snippetAutoExpand = value;
			OnPropertyChanged("SnippetAutoExpand");
		}
	}

	public string Language
	{
		get
		{
			return _language;
		}
		set
		{
			_language = value;
			OnPropertyChanged("Language");
		}
	}

	public string IndexSpeed
	{
		get
		{
			return _indexSpeed;
		}
		set
		{
			_indexSpeed = value;
			OnPropertyChanged("IndexSpeed");
			OnPropertyChanged("IndexSpeedHint");
		}
	}

	public string IndexSpeedHint
	{
		get
		{
			string indexSpeed = _indexSpeed;
			if (1 == 0)
			{
			}
			string result = ((indexSpeed == "fast") ? "CPU 사용률이 높아질 수 있습니다. 고성능 PC에 권장합니다." : ((!(indexSpeed == "slow")) ? "일반적인 PC에 적합한 균형 설정입니다." : "인덱싱이 오래 걸리지만 PC 성능에 영향을 주지 않습니다."));
			if (1 == 0)
			{
			}
			return result;
		}
	}

	public bool ShowNumberBadges
	{
		get
		{
			return _showNumberBadges;
		}
		set
		{
			_showNumberBadges = value;
			OnPropertyChanged("ShowNumberBadges");
		}
	}

	public bool EnableFavorites
	{
		get
		{
			return _enableFavorites;
		}
		set
		{
			_enableFavorites = value;
			OnPropertyChanged("EnableFavorites");
		}
	}

	public bool EnableRecent
	{
		get
		{
			return _enableRecent;
		}
		set
		{
			_enableRecent = value;
			OnPropertyChanged("EnableRecent");
		}
	}

	public bool EnableActionMode
	{
		get
		{
			return _enableActionMode;
		}
		set
		{
			_enableActionMode = value;
			OnPropertyChanged("EnableActionMode");
		}
	}

	public bool CloseOnFocusLost
	{
		get
		{
			return _closeOnFocusLost;
		}
		set
		{
			_closeOnFocusLost = value;
			OnPropertyChanged("CloseOnFocusLost");
		}
	}

	public bool ShowPrefixBadge
	{
		get
		{
			return _showPrefixBadge;
		}
		set
		{
			_showPrefixBadge = value;
			OnPropertyChanged("ShowPrefixBadge");
		}
	}

	public bool EnableIconAnimation
	{
		get
		{
			return _enableIconAnimation;
		}
		set
		{
			_enableIconAnimation = value;
			OnPropertyChanged("EnableIconAnimation");
		}
	}

	public bool EnableRainbowGlow
	{
		get
		{
			return _enableRainbowGlow;
		}
		set
		{
			_enableRainbowGlow = value;
			OnPropertyChanged("EnableRainbowGlow");
		}
	}

	public bool EnableSelectionGlow
	{
		get
		{
			return _enableSelectionGlow;
		}
		set
		{
			_enableSelectionGlow = value;
			OnPropertyChanged("EnableSelectionGlow");
		}
	}

	public bool EnableRandomPlaceholder
	{
		get
		{
			return _enableRandomPlaceholder;
		}
		set
		{
			_enableRandomPlaceholder = value;
			OnPropertyChanged("EnableRandomPlaceholder");
		}
	}

	public bool ShowLauncherBorder
	{
		get
		{
			return _showLauncherBorder;
		}
		set
		{
			_showLauncherBorder = value;
			OnPropertyChanged("ShowLauncherBorder");
		}
	}

	public bool EnableTextAction
	{
		get
		{
			return _enableTextAction;
		}
		set
		{
			_enableTextAction = value;
			OnPropertyChanged("EnableTextAction");
		}
	}

	public bool EnableFileDialogIntegration
	{
		get
		{
			return _enableFileDialogIntegration;
		}
		set
		{
			_enableFileDialogIntegration = value;
			OnPropertyChanged("EnableFileDialogIntegration");
		}
	}

	public bool EnableClipboardAutoCategory
	{
		get
		{
			return _enableClipboardAutoCategory;
		}
		set
		{
			_enableClipboardAutoCategory = value;
			OnPropertyChanged("EnableClipboardAutoCategory");
		}
	}

	public int MaxPinnedClipboardItems
	{
		get
		{
			return _maxPinnedClipboardItems;
		}
		set
		{
			_maxPinnedClipboardItems = value;
			OnPropertyChanged("MaxPinnedClipboardItems");
		}
	}

	public string TextActionTranslateLanguage
	{
		get
		{
			return _textActionTranslateLanguage;
		}
		set
		{
			_textActionTranslateLanguage = value;
			OnPropertyChanged("TextActionTranslateLanguage");
		}
	}

	public int MaxSubAgents
	{
		get
		{
			return _maxSubAgents;
		}
		set
		{
			_maxSubAgents = value;
			OnPropertyChanged("MaxSubAgents");
		}
	}

	public string PdfExportPath
	{
		get
		{
			return _pdfExportPath;
		}
		set
		{
			_pdfExportPath = value;
			OnPropertyChanged("PdfExportPath");
		}
	}

	public int TipDurationSeconds
	{
		get
		{
			return _tipDurationSeconds;
		}
		set
		{
			_tipDurationSeconds = value;
			OnPropertyChanged("TipDurationSeconds");
		}
	}

	public bool ShortcutHelpUseThemeColor
	{
		get
		{
			return _shortcutHelpUseThemeColor;
		}
		set
		{
			_shortcutHelpUseThemeColor = value;
			OnPropertyChanged("ShortcutHelpUseThemeColor");
		}
	}

	public List<ThemeCardModel> ThemeCards { get; } = new List<ThemeCardModel>
	{
		new ThemeCardModel
		{
			Key = "system",
			Name = "시스템",
			PreviewBackground = "#1E1E1E",
			PreviewText = "#FFFFFF",
			PreviewSubText = "#888888",
			PreviewAccent = "#0078D4",
			PreviewItem = "#2D2D2D",
			PreviewBorder = "#3D3D3D"
		},
		new ThemeCardModel
		{
			Key = "dark",
			Name = "Dark",
			PreviewBackground = "#1A1B2E",
			PreviewText = "#F0F0FF",
			PreviewSubText = "#7A7D9C",
			PreviewAccent = "#4B5EFC",
			PreviewItem = "#252637",
			PreviewBorder = "#2E2F4A"
		},
		new ThemeCardModel
		{
			Key = "light",
			Name = "Light",
			PreviewBackground = "#FAFAFA",
			PreviewText = "#1A1B2E",
			PreviewSubText = "#666680",
			PreviewAccent = "#4B5EFC",
			PreviewItem = "#F0F0F8",
			PreviewBorder = "#E0E0F0"
		},
		new ThemeCardModel
		{
			Key = "oled",
			Name = "OLED",
			PreviewBackground = "#000000",
			PreviewText = "#FFFFFF",
			PreviewSubText = "#888899",
			PreviewAccent = "#5C6EFF",
			PreviewItem = "#0A0A14",
			PreviewBorder = "#1A1A2E"
		},
		new ThemeCardModel
		{
			Key = "nord",
			Name = "Nord",
			PreviewBackground = "#2E3440",
			PreviewText = "#ECEFF4",
			PreviewSubText = "#D8DEE9",
			PreviewAccent = "#88C0D0",
			PreviewItem = "#3B4252",
			PreviewBorder = "#434C5E"
		},
		new ThemeCardModel
		{
			Key = "monokai",
			Name = "Monokai",
			PreviewBackground = "#272822",
			PreviewText = "#F8F8F2",
			PreviewSubText = "#75715E",
			PreviewAccent = "#A6E22E",
			PreviewItem = "#3E3D32",
			PreviewBorder = "#49483E"
		},
		new ThemeCardModel
		{
			Key = "catppuccin",
			Name = "Catppuccin",
			PreviewBackground = "#1E1E2E",
			PreviewText = "#CDD6F4",
			PreviewSubText = "#A6ADC8",
			PreviewAccent = "#CBA6F7",
			PreviewItem = "#313244",
			PreviewBorder = "#45475A"
		},
		new ThemeCardModel
		{
			Key = "sepia",
			Name = "Sepia",
			PreviewBackground = "#F5EFE0",
			PreviewText = "#3C2F1A",
			PreviewSubText = "#7A6040",
			PreviewAccent = "#C0822A",
			PreviewItem = "#EDE6D6",
			PreviewBorder = "#D8CCBA"
		},
		new ThemeCardModel
		{
			Key = "alfred",
			Name = "Indigo",
			PreviewBackground = "#26273B",
			PreviewText = "#EEEEFF",
			PreviewSubText = "#8888BB",
			PreviewAccent = "#8877EE",
			PreviewItem = "#3B3D60",
			PreviewBorder = "#40416A"
		},
		new ThemeCardModel
		{
			Key = "alfredlight",
			Name = "Frost",
			PreviewBackground = "#FFFFFF",
			PreviewText = "#1A1A2E",
			PreviewSubText = "#9090AA",
			PreviewAccent = "#5555EE",
			PreviewItem = "#E8E9FF",
			PreviewBorder = "#DCDCEE"
		},
		new ThemeCardModel
		{
			Key = "codex",
			Name = "Codex",
			PreviewBackground = "#FFFFFF",
			PreviewText = "#111111",
			PreviewSubText = "#6B7280",
			PreviewAccent = "#7C3AED",
			PreviewItem = "#F5F5F7",
			PreviewBorder = "#E5E7EB"
		},
		new ThemeCardModel
		{
			Key = "custom",
			Name = "커스텀",
			PreviewBackground = "#1A1B2E",
			PreviewText = "#F0F0FF",
			PreviewSubText = "#7A7D9C",
			PreviewAccent = "#4B5EFC",
			PreviewItem = "#252637",
			PreviewBorder = "#2E2F4A"
		}
	};

	public List<ColorRowModel> ColorRows { get; }

	public ObservableCollection<PromptTemplateRow> PromptTemplates { get; } = new ObservableCollection<PromptTemplateRow>();

	public ObservableCollection<BatchCommandModel> BatchCommands { get; } = new ObservableCollection<BatchCommandModel>();

	public string NewBatchKey
	{
		get
		{
			return _newBatchKey;
		}
		set
		{
			_newBatchKey = value;
			OnPropertyChanged("NewBatchKey");
		}
	}

	public string NewBatchCommand
	{
		get
		{
			return _newBatchCommand;
		}
		set
		{
			_newBatchCommand = value;
			OnPropertyChanged("NewBatchCommand");
		}
	}

	public bool NewBatchShowWindow
	{
		get
		{
			return _newBatchShowWindow;
		}
		set
		{
			_newBatchShowWindow = value;
			OnPropertyChanged("NewBatchShowWindow");
		}
	}

	public ObservableCollection<AppShortcutModel> AppShortcuts { get; } = new ObservableCollection<AppShortcutModel>();

	public string NewKey
	{
		get
		{
			return _newKey;
		}
		set
		{
			_newKey = value;
			OnPropertyChanged("NewKey");
		}
	}

	public string NewDescription
	{
		get
		{
			return _newDescription;
		}
		set
		{
			_newDescription = value;
			OnPropertyChanged("NewDescription");
		}
	}

	public string NewTarget
	{
		get
		{
			return _newTarget;
		}
		set
		{
			_newTarget = value;
			OnPropertyChanged("NewTarget");
		}
	}

	public string NewType
	{
		get
		{
			return _newType;
		}
		set
		{
			_newType = value;
			OnPropertyChanged("NewType");
		}
	}

	public int CustomWindowCornerRadius
	{
		get
		{
			return _customWindowCornerRadius;
		}
		set
		{
			_customWindowCornerRadius = Math.Clamp(value, 0, 30);
			OnPropertyChanged("CustomWindowCornerRadius");
		}
	}

	public int CustomItemCornerRadius
	{
		get
		{
			return _customItemCornerRadius;
		}
		set
		{
			_customItemCornerRadius = Math.Clamp(value, 0, 20);
			OnPropertyChanged("CustomItemCornerRadius");
		}
	}

	public ObservableCollection<string> IndexPaths { get; } = new ObservableCollection<string>();

	public ObservableCollection<string> IndexExtensions { get; } = new ObservableCollection<string>();

	public ObservableCollection<SnippetRowModel> Snippets { get; } = new ObservableCollection<SnippetRowModel>();

	public string NewSnippetKey
	{
		get
		{
			return _newSnippetKey;
		}
		set
		{
			_newSnippetKey = value;
			OnPropertyChanged("NewSnippetKey");
		}
	}

	public string NewSnippetName
	{
		get
		{
			return _newSnippetName;
		}
		set
		{
			_newSnippetName = value;
			OnPropertyChanged("NewSnippetName");
		}
	}

	public string NewSnippetContent
	{
		get
		{
			return _newSnippetContent;
		}
		set
		{
			_newSnippetContent = value;
			OnPropertyChanged("NewSnippetContent");
		}
	}

	public bool ClipboardEnabled
	{
		get
		{
			return _clipboardEnabled;
		}
		set
		{
			_clipboardEnabled = value;
			OnPropertyChanged("ClipboardEnabled");
		}
	}

	public int ClipboardMaxItems
	{
		get
		{
			return _clipboardMaxItems;
		}
		set
		{
			_clipboardMaxItems = value;
			OnPropertyChanged("ClipboardMaxItems");
		}
	}

	public string CapPrefix
	{
		get
		{
			return _capPrefix;
		}
		set
		{
			_capPrefix = value;
			OnPropertyChanged("CapPrefix");
		}
	}

	public bool CapGlobalHotkeyEnabled
	{
		get
		{
			return _capGlobalHotkeyEnabled;
		}
		set
		{
			_capGlobalHotkeyEnabled = value;
			OnPropertyChanged("CapGlobalHotkeyEnabled");
		}
	}

	public string CapGlobalHotkey
	{
		get
		{
			return _capGlobalHotkey;
		}
		set
		{
			_capGlobalHotkey = value;
			OnPropertyChanged("CapGlobalHotkey");
		}
	}

	public string CapGlobalMode
	{
		get
		{
			return _capGlobalMode;
		}
		set
		{
			_capGlobalMode = value;
			OnPropertyChanged("CapGlobalMode");
		}
	}

	public int CapScrollDelayMs
	{
		get
		{
			return _capScrollDelayMs;
		}
		set
		{
			_capScrollDelayMs = value;
			OnPropertyChanged("CapScrollDelayMs");
			OnPropertyChanged("CapScrollDelayMsStr");
		}
	}

	public string CapScrollDelayMsStr
	{
		get
		{
			return _capScrollDelayMs.ToString();
		}
		set
		{
			if (int.TryParse(value, out var result))
			{
				CapScrollDelayMs = result;
			}
		}
	}

	public bool ReminderEnabled
	{
		get
		{
			return _reminderEnabled;
		}
		set
		{
			_reminderEnabled = value;
			OnPropertyChanged("ReminderEnabled");
		}
	}

	public string ReminderCorner
	{
		get
		{
			return _reminderCorner;
		}
		set
		{
			_reminderCorner = value;
			OnPropertyChanged("ReminderCorner");
		}
	}

	public int ReminderIntervalMinutes
	{
		get
		{
			return _reminderIntervalMinutes;
		}
		set
		{
			_reminderIntervalMinutes = value;
			OnPropertyChanged("ReminderIntervalMinutes");
		}
	}

	public int ReminderDisplaySeconds
	{
		get
		{
			return _reminderDisplaySeconds;
		}
		set
		{
			_reminderDisplaySeconds = value;
			OnPropertyChanged("ReminderDisplaySeconds");
		}
	}

	public bool SysShowLock
	{
		get
		{
			return _sysShowLock;
		}
		set
		{
			_sysShowLock = value;
			OnPropertyChanged("SysShowLock");
		}
	}

	public bool SysShowSleep
	{
		get
		{
			return _sysShowSleep;
		}
		set
		{
			_sysShowSleep = value;
			OnPropertyChanged("SysShowSleep");
		}
	}

	public bool SysShowRestart
	{
		get
		{
			return _sysShowRestart;
		}
		set
		{
			_sysShowRestart = value;
			OnPropertyChanged("SysShowRestart");
		}
	}

	public bool SysShowShutdown
	{
		get
		{
			return _sysShowShutdown;
		}
		set
		{
			_sysShowShutdown = value;
			OnPropertyChanged("SysShowShutdown");
		}
	}

	public bool SysShowHibernate
	{
		get
		{
			return _sysShowHibernate;
		}
		set
		{
			_sysShowHibernate = value;
			OnPropertyChanged("SysShowHibernate");
		}
	}

	public bool SysShowLogout
	{
		get
		{
			return _sysShowLogout;
		}
		set
		{
			_sysShowLogout = value;
			OnPropertyChanged("SysShowLogout");
		}
	}

	public bool SysShowRecycleBin
	{
		get
		{
			return _sysShowRecycleBin;
		}
		set
		{
			_sysShowRecycleBin = value;
			OnPropertyChanged("SysShowRecycleBin");
		}
	}

	public string AliasLock
	{
		get
		{
			return _aliasLock;
		}
		set
		{
			_aliasLock = value;
			OnPropertyChanged("AliasLock");
		}
	}

	public string AliasSleep
	{
		get
		{
			return _aliasSleep;
		}
		set
		{
			_aliasSleep = value;
			OnPropertyChanged("AliasSleep");
		}
	}

	public string AliasRestart
	{
		get
		{
			return _aliasRestart;
		}
		set
		{
			_aliasRestart = value;
			OnPropertyChanged("AliasRestart");
		}
	}

	public string AliasShutdown
	{
		get
		{
			return _aliasShutdown;
		}
		set
		{
			_aliasShutdown = value;
			OnPropertyChanged("AliasShutdown");
		}
	}

	public string AliasHibernate
	{
		get
		{
			return _aliasHibernate;
		}
		set
		{
			_aliasHibernate = value;
			OnPropertyChanged("AliasHibernate");
		}
	}

	public string AliasLogout
	{
		get
		{
			return _aliasLogout;
		}
		set
		{
			_aliasLogout = value;
			OnPropertyChanged("AliasLogout");
		}
	}

	public string AliasRecycle
	{
		get
		{
			return _aliasRecycle;
		}
		set
		{
			_aliasRecycle = value;
			OnPropertyChanged("AliasRecycle");
		}
	}

	public event EventHandler? ThemePreviewRequested;

	public event EventHandler? SaveCompleted;

	public event PropertyChangedEventHandler? PropertyChanged;

	public bool AddBatchCommand()
	{
		if (string.IsNullOrWhiteSpace(_newBatchKey) || string.IsNullOrWhiteSpace(_newBatchCommand))
		{
			return false;
		}
		if (BatchCommands.Any((BatchCommandModel b) => b.Key.Equals(_newBatchKey.Trim(), StringComparison.OrdinalIgnoreCase)))
		{
			return false;
		}
		BatchCommands.Add(new BatchCommandModel
		{
			Key = _newBatchKey.Trim(),
			Command = _newBatchCommand.Trim(),
			ShowWindow = _newBatchShowWindow
		});
		NewBatchKey = "";
		NewBatchCommand = "";
		NewBatchShowWindow = false;
		return true;
	}

	public void RemoveBatchCommand(BatchCommandModel cmd)
	{
		BatchCommands.Remove(cmd);
	}

	public SettingsViewModel(SettingsService service)
	{
		_service = service;
		AppSettings settings = service.Settings;
		_hotkey = settings.Hotkey;
		_maxResults = settings.Launcher.MaxResults;
		_opacity = settings.Launcher.Opacity;
		_selectedThemeKey = (settings.Launcher.Theme ?? "system").ToLowerInvariant();
		_launcherPosition = settings.Launcher.Position;
		_webSearchEngine = settings.Launcher.WebSearchEngine;
		_snippetAutoExpand = settings.Launcher.SnippetAutoExpand;
		_language = settings.Launcher.Language;
		_indexSpeed = settings.IndexSpeed ?? "normal";
		_showNumberBadges = settings.Launcher.ShowNumberBadges;
		_enableFavorites = settings.Launcher.EnableFavorites;
		_enableRecent = settings.Launcher.EnableRecent;
		_enableActionMode = settings.Launcher.EnableActionMode;
		_closeOnFocusLost = settings.Launcher.CloseOnFocusLost;
		_showPrefixBadge = settings.Launcher.ShowPrefixBadge;
		_enableIconAnimation = settings.Launcher.EnableIconAnimation;
		_enableRainbowGlow = settings.Launcher.EnableRainbowGlow;
		_enableSelectionGlow = settings.Launcher.EnableSelectionGlow;
		_enableRandomPlaceholder = settings.Launcher.EnableRandomPlaceholder;
		_showLauncherBorder = settings.Launcher.ShowLauncherBorder;
		_shortcutHelpUseThemeColor = settings.Launcher.ShortcutHelpUseThemeColor;
		_enableTextAction = settings.Launcher.EnableTextAction;
		_enableFileDialogIntegration = false;
		settings.Launcher.EnableFileDialogIntegration = false;
		_enableClipboardAutoCategory = settings.Launcher.EnableClipboardAutoCategory;
		_maxPinnedClipboardItems = settings.Launcher.MaxPinnedClipboardItems;
		_textActionTranslateLanguage = settings.Launcher.TextActionTranslateLanguage;
		_maxSubAgents = settings.Llm.MaxSubAgents;
		_pdfExportPath = settings.Llm.PdfExportPath;
		_tipDurationSeconds = settings.Llm.TipDurationSeconds;
		LlmSettings llm = settings.Llm;
		_llmService = llm.Service;
		_llmStreaming = llm.Streaming;
		_llmMaxContextTokens = llm.MaxContextTokens;
		_llmRetentionDays = llm.RetentionDays;
		_llmTemperature = llm.Temperature;
		_defaultAgentPermission = llm.DefaultAgentPermission;
		_defaultOutputFormat = llm.DefaultOutputFormat;
		_defaultMood = (string.IsNullOrEmpty(llm.DefaultMood) ? "modern" : llm.DefaultMood);
		_autoPreview = llm.AutoPreview;
		_maxAgentIterations = ((llm.MaxAgentIterations > 0) ? llm.MaxAgentIterations : 25);
		_maxRetryOnError = ((llm.MaxRetryOnError > 0) ? llm.MaxRetryOnError : 3);
		_agentLogLevel = llm.AgentLogLevel;
		_agentDecisionLevel = llm.AgentDecisionLevel;
		_planMode = (string.IsNullOrEmpty(llm.PlanMode) ? "off" : llm.PlanMode);
		_enableMultiPassDocument = llm.EnableMultiPassDocument;
		_enableCoworkVerification = llm.EnableCoworkVerification;
		_enableFilePathHighlight = llm.EnableFilePathHighlight;
		_folderDataUsage = (string.IsNullOrEmpty(llm.FolderDataUsage) ? "active" : llm.FolderDataUsage);
		_enableAuditLog = llm.EnableAuditLog;
		_enableAgentMemory = llm.EnableAgentMemory;
		_enableProjectRules = llm.EnableProjectRules;
		_maxMemoryEntries = llm.MaxMemoryEntries;
		_enableImageInput = llm.EnableImageInput;
		_maxImageSizeKb = ((llm.MaxImageSizeKb > 0) ? llm.MaxImageSizeKb : 5120);
		_enableToolHooks = llm.EnableToolHooks;
		_toolHookTimeoutMs = ((llm.ToolHookTimeoutMs > 0) ? llm.ToolHookTimeoutMs : 10000);
		_enableSkillSystem = llm.EnableSkillSystem;
		_skillsFolderPath = llm.SkillsFolderPath;
		_slashPopupPageSize = ((llm.SlashPopupPageSize > 0) ? Math.Clamp(llm.SlashPopupPageSize, 3, 10) : 6);
		_enableDragDropAiActions = llm.EnableDragDropAiActions;
		_dragDropAutoSend = llm.DragDropAutoSend;
		_enableCodeReview = llm.Code.EnableCodeReview;
		_enableAutoRouter = llm.EnableAutoRouter;
		_autoRouterConfidence = llm.AutoRouterConfidence;
		_enableChatRainbowGlow = llm.EnableChatRainbowGlow;
		_notifyOnComplete = llm.NotifyOnComplete;
		_showTips = llm.ShowTips;
		_devMode = llm.DevMode;
		_devModeStepApproval = llm.DevModeStepApproval;
		_workflowVisualizer = llm.WorkflowVisualizer;
		_freeTierMode = llm.FreeTierMode;
		_freeTierDelaySeconds = ((llm.FreeTierDelaySeconds > 0) ? llm.FreeTierDelaySeconds : 4);
		_showTotalCallStats = llm.ShowTotalCallStats;
		_ollamaEndpoint = llm.OllamaEndpoint;
		_ollamaModel = llm.OllamaModel;
		_vllmEndpoint = llm.VllmEndpoint;
		_vllmModel = llm.VllmModel;
		_geminiModel = (string.IsNullOrEmpty(llm.GeminiModel) ? "gemini-2.5-flash" : llm.GeminiModel);
		_claudeModel = (string.IsNullOrEmpty(llm.ClaudeModel) ? "claude-sonnet-4-6" : llm.ClaudeModel);
		_geminiApiKey = llm.GeminiApiKey;
		_claudeApiKey = llm.ClaudeApiKey;
		if (llm.EncryptionEnabled)
		{
			_ollamaApiKey = (string.IsNullOrEmpty(llm.OllamaApiKey) ? "" : "(저장됨)");
			_vllmApiKey = (string.IsNullOrEmpty(llm.VllmApiKey) ? "" : "(저장됨)");
		}
		else
		{
			_ollamaApiKey = llm.OllamaApiKey;
			_vllmApiKey = llm.VllmApiKey;
		}
		if (string.IsNullOrEmpty(llm.OllamaEndpoint) && !string.IsNullOrEmpty(llm.Endpoint) && llm.Service == "ollama")
		{
			_ollamaEndpoint = llm.Endpoint;
			_ollamaModel = llm.Model;
			if (!llm.EncryptionEnabled)
			{
				_ollamaApiKey = llm.EncryptedApiKey;
			}
		}
		if (string.IsNullOrEmpty(llm.VllmEndpoint) && !string.IsNullOrEmpty(llm.Endpoint) && llm.Service == "vllm")
		{
			_vllmEndpoint = llm.Endpoint;
			_vllmModel = llm.Model;
			if (!llm.EncryptionEnabled)
			{
				_vllmApiKey = llm.EncryptedApiKey;
			}
		}
		if (string.IsNullOrEmpty(llm.GeminiApiKey) && !string.IsNullOrEmpty(llm.ApiKey) && llm.Service == "gemini")
		{
			_geminiApiKey = llm.ApiKey;
			_geminiModel = llm.Model;
		}
		if (string.IsNullOrEmpty(llm.ClaudeApiKey) && !string.IsNullOrEmpty(llm.ApiKey) && llm.Service == "claude")
		{
			_claudeApiKey = llm.ApiKey;
			_claudeModel = llm.Model;
		}
		foreach (string blockedPath in llm.BlockedPaths)
		{
			BlockedPaths.Add(blockedPath);
		}
		foreach (string blockedExtension in llm.BlockedExtensions)
		{
			BlockedExtensions.Add(blockedExtension);
		}
		foreach (RegisteredModel registeredModel in llm.RegisteredModels)
		{
			RegisteredModels.Add(new RegisteredModelRow
			{
				Alias = registeredModel.Alias,
				EncryptedModelName = registeredModel.EncryptedModelName,
				Service = registeredModel.Service,
				Endpoint = registeredModel.Endpoint,
				ApiKey = registeredModel.ApiKey,
				AuthType = (registeredModel.AuthType ?? "bearer"),
				Cp4dUrl = (registeredModel.Cp4dUrl ?? ""),
				Cp4dUsername = (registeredModel.Cp4dUsername ?? ""),
				Cp4dPassword = (registeredModel.Cp4dPassword ?? "")
			});
		}
		foreach (PromptTemplate promptTemplate in llm.PromptTemplates)
		{
			PromptTemplates.Add(new PromptTemplateRow
			{
				Name = promptTemplate.Name,
				Content = promptTemplate.Content,
				Icon = promptTemplate.Icon
			});
		}
		foreach (ThemeCardModel themeCard in ThemeCards)
		{
			themeCard.IsSelected = themeCard.Key == _selectedThemeKey;
		}
		_reminderEnabled = settings.Reminder.Enabled;
		_reminderCorner = settings.Reminder.Corner;
		_reminderIntervalMinutes = settings.Reminder.IntervalMinutes;
		_reminderDisplaySeconds = settings.Reminder.DisplaySeconds;
		_capPrefix = (string.IsNullOrWhiteSpace(settings.ScreenCapture.Prefix) ? "cap" : settings.ScreenCapture.Prefix);
		_capGlobalHotkeyEnabled = settings.ScreenCapture.GlobalHotkeyEnabled;
		_capGlobalHotkey = (string.IsNullOrWhiteSpace(settings.ScreenCapture.GlobalHotkey) ? "PrintScreen" : settings.ScreenCapture.GlobalHotkey);
		_capGlobalMode = (string.IsNullOrWhiteSpace(settings.ScreenCapture.GlobalHotkeyMode) ? "screen" : settings.ScreenCapture.GlobalHotkeyMode);
		_capScrollDelayMs = ((settings.ScreenCapture.ScrollDelayMs > 0) ? settings.ScreenCapture.ScrollDelayMs : 120);
		_clipboardEnabled = settings.ClipboardHistory.Enabled;
		_clipboardMaxItems = settings.ClipboardHistory.MaxItems;
		SystemCommandSettings systemCommands = settings.SystemCommands;
		_sysShowLock = systemCommands.ShowLock;
		_sysShowSleep = systemCommands.ShowSleep;
		_sysShowRestart = systemCommands.ShowRestart;
		_sysShowShutdown = systemCommands.ShowShutdown;
		_sysShowHibernate = systemCommands.ShowHibernate;
		_sysShowLogout = systemCommands.ShowLogout;
		_sysShowRecycleBin = systemCommands.ShowRecycleBin;
		Dictionary<string, List<string>> commandAliases = systemCommands.CommandAliases;
		_aliasLock = FormatAliases(commandAliases, "lock");
		_aliasSleep = FormatAliases(commandAliases, "sleep");
		_aliasRestart = FormatAliases(commandAliases, "restart");
		_aliasShutdown = FormatAliases(commandAliases, "shutdown");
		_aliasHibernate = FormatAliases(commandAliases, "hibernate");
		_aliasLogout = FormatAliases(commandAliases, "logout");
		_aliasRecycle = FormatAliases(commandAliases, "recycle");
		foreach (string indexPath in settings.IndexPaths)
		{
			IndexPaths.Add(indexPath);
		}
		foreach (string indexExtension in settings.IndexExtensions)
		{
			IndexExtensions.Add(indexExtension);
		}
		foreach (SnippetEntry snippet in settings.Snippets)
		{
			Snippets.Add(new SnippetRowModel
			{
				Key = snippet.Key,
				Name = snippet.Name,
				Content = snippet.Content
			});
		}
		foreach (AliasEntry item in settings.Aliases.Where((AliasEntry a) => a.Type == "batch"))
		{
			BatchCommands.Add(new BatchCommandModel
			{
				Key = item.Key,
				Command = item.Target,
				ShowWindow = item.ShowWindow
			});
		}
		foreach (AliasEntry item2 in settings.Aliases.Where(delegate(AliasEntry a)
		{
			switch (a.Type)
			{
			case "app":
			case "url":
			case "folder":
				return true;
			default:
				return false;
			}
		}))
		{
			AppShortcuts.Add(new AppShortcutModel
			{
				Key = item2.Key,
				Description = (item2.Description ?? ""),
				Target = item2.Target,
				Type = item2.Type
			});
		}
		CustomThemeColors customThemeColors = settings.Launcher.CustomTheme ?? new CustomThemeColors();
		ColorRows = new List<ColorRowModel>
		{
			new ColorRowModel("런처 배경", "LauncherBackground", customThemeColors.LauncherBackground),
			new ColorRowModel("항목 배경", "ItemBackground", customThemeColors.ItemBackground),
			new ColorRowModel("선택 항목 배경", "ItemSelectedBackground", customThemeColors.ItemSelectedBackground),
			new ColorRowModel("호버 배경", "ItemHoverBackground", customThemeColors.ItemHoverBackground),
			new ColorRowModel("기본 텍스트", "PrimaryText", customThemeColors.PrimaryText),
			new ColorRowModel("보조 텍스트", "SecondaryText", customThemeColors.SecondaryText),
			new ColorRowModel("플레이스홀더", "PlaceholderText", customThemeColors.PlaceholderText),
			new ColorRowModel("강조색", "AccentColor", customThemeColors.AccentColor),
			new ColorRowModel("구분선", "SeparatorColor", customThemeColors.SeparatorColor),
			new ColorRowModel("힌트 배경", "HintBackground", customThemeColors.HintBackground),
			new ColorRowModel("힌트 텍스트", "HintText", customThemeColors.HintText),
			new ColorRowModel("테두리", "BorderColor", customThemeColors.BorderColor),
			new ColorRowModel("스크롤바", "ScrollbarThumb", customThemeColors.ScrollbarThumb),
			new ColorRowModel("그림자", "ShadowColor", customThemeColors.ShadowColor)
		};
		_customWindowCornerRadius = customThemeColors.WindowCornerRadius;
		_customItemCornerRadius = customThemeColors.ItemCornerRadius;
	}

	public void AddIndexPath(string path)
	{
		string trimmed = path.Trim();
		if (!string.IsNullOrWhiteSpace(trimmed) && !IndexPaths.Any((string p) => p.Equals(trimmed, StringComparison.OrdinalIgnoreCase)))
		{
			IndexPaths.Add(trimmed);
		}
	}

	public void RemoveIndexPath(string path)
	{
		IndexPaths.Remove(path);
	}

	public void AddExtension(string ext)
	{
		string trimmed = ext.Trim().ToLowerInvariant();
		if (!string.IsNullOrWhiteSpace(trimmed))
		{
			if (!trimmed.StartsWith("."))
			{
				trimmed = "." + trimmed;
			}
			if (!IndexExtensions.Any((string e) => e.Equals(trimmed, StringComparison.OrdinalIgnoreCase)))
			{
				IndexExtensions.Add(trimmed);
			}
		}
	}

	public void RemoveExtension(string ext)
	{
		IndexExtensions.Remove(ext);
	}

	public void BrowseIndexPath()
	{
		using FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog
		{
			Description = "인덱스할 폴더 선택",
			UseDescriptionForTitle = true,
			ShowNewFolderButton = false
		};
		if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
		{
			AddIndexPath(folderBrowserDialog.SelectedPath);
		}
	}

	public bool AddShortcut()
	{
		if (string.IsNullOrWhiteSpace(_newKey) || string.IsNullOrWhiteSpace(_newTarget))
		{
			return false;
		}
		if (AppShortcuts.Any((AppShortcutModel s) => s.Key.Equals(_newKey.Trim(), StringComparison.OrdinalIgnoreCase)))
		{
			return false;
		}
		AppShortcuts.Add(new AppShortcutModel
		{
			Key = _newKey.Trim(),
			Description = _newDescription.Trim(),
			Target = _newTarget.Trim(),
			Type = _newType
		});
		NewKey = "";
		NewDescription = "";
		NewTarget = "";
		NewType = "app";
		return true;
	}

	public void RemoveShortcut(AppShortcutModel shortcut)
	{
		AppShortcuts.Remove(shortcut);
	}

	public void BrowseTarget()
	{
		using OpenFileDialog openFileDialog = new OpenFileDialog
		{
			Filter = "실행 파일 (*.exe)|*.exe|모든 파일 (*.*)|*.*",
			Title = "앱 선택"
		};
		if (openFileDialog.ShowDialog() == DialogResult.OK)
		{
			NewTarget = openFileDialog.FileName;
			NewType = "app";
			if (string.IsNullOrWhiteSpace(NewDescription))
			{
				NewDescription = Path.GetFileNameWithoutExtension(openFileDialog.FileName);
			}
		}
	}

	public void SelectTheme(string key)
	{
		SelectedThemeKey = key;
		this.ThemePreviewRequested?.Invoke(this, EventArgs.Empty);
	}

	public void PickColor(ColorRowModel row)
	{
		using ColorDialog colorDialog = new ColorDialog
		{
			FullOpen = true
		};
		try
		{
			System.Windows.Media.Color color = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString(row.Hex);
			colorDialog.Color = System.Drawing.Color.FromArgb(color.R, color.G, color.B);
		}
		catch
		{
		}
		if (colorDialog.ShowDialog() == DialogResult.OK)
		{
			row.Hex = $"#{colorDialog.Color.R:X2}{colorDialog.Color.G:X2}{colorDialog.Color.B:X2}";
			if (_selectedThemeKey == "custom")
			{
				this.ThemePreviewRequested?.Invoke(this, EventArgs.Empty);
			}
		}
	}

	public string? ValidateBeforeSave()
	{
		string text = (string.IsNullOrWhiteSpace(_capPrefix) ? "cap" : _capPrefix.Trim());
		if (text != "cap" && ReservedPrefixes.Contains(text))
		{
			return "캡처 프리픽스 '" + text + "'은(는) 이미 사용 중인 예약어입니다.";
		}
		List<string> list = AppShortcuts.Select((AppShortcutModel s) => s.Key.ToLowerInvariant()).ToList();
		IGrouping<string, string> grouping = (from k in list
			group k by k).FirstOrDefault((IGrouping<string, string> g) => g.Count() > 1);
		if (grouping != null)
		{
			return "빠른 실행 키워드 '" + grouping.Key + "'이(가) 중복되었습니다.";
		}
		foreach (string item in list)
		{
			if (ReservedPrefixes.Contains(item))
			{
				return "빠른 실행 키워드 '" + item + "'은(는) 시스템 예약어와 충돌합니다.";
			}
		}
		List<string> source = BatchCommands.Select((BatchCommandModel b) => b.Key.ToLowerInvariant()).ToList();
		IGrouping<string, string> grouping2 = (from k in source
			group k by k).FirstOrDefault((IGrouping<string, string> g) => g.Count() > 1);
		if (grouping2 != null)
		{
			return "배치 명령 키워드 '" + grouping2.Key + "'이(가) 중복되었습니다.";
		}
		return null;
	}

	public void Save()
	{
		string text = ValidateBeforeSave();
		if (text != null)
		{
			CustomMessageBox.Show(text, "AX Copilot — 설정 저장 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
			return;
		}
		AppSettings settings = _service.Settings;
		settings.Hotkey = _hotkey;
		settings.Launcher.MaxResults = _maxResults;
		settings.Launcher.Opacity = _opacity;
		settings.Launcher.Theme = _selectedThemeKey;
		settings.Launcher.Position = _launcherPosition;
		settings.Launcher.WebSearchEngine = _webSearchEngine;
		settings.Launcher.SnippetAutoExpand = _snippetAutoExpand;
		settings.Launcher.Language = _language;
		L10n.SetLanguage(_language);
		settings.Launcher.ShowNumberBadges = _showNumberBadges;
		settings.Launcher.EnableFavorites = _enableFavorites;
		settings.Launcher.EnableRecent = _enableRecent;
		settings.Launcher.EnableActionMode = _enableActionMode;
		settings.Launcher.CloseOnFocusLost = _closeOnFocusLost;
		settings.Launcher.ShowPrefixBadge = _showPrefixBadge;
		settings.Launcher.EnableIconAnimation = _enableIconAnimation;
		settings.Launcher.EnableRainbowGlow = _enableRainbowGlow;
		settings.Launcher.EnableSelectionGlow = _enableSelectionGlow;
		settings.Launcher.EnableRandomPlaceholder = _enableRandomPlaceholder;
		settings.Launcher.ShowLauncherBorder = _showLauncherBorder;
		settings.Launcher.ShortcutHelpUseThemeColor = _shortcutHelpUseThemeColor;
		settings.Launcher.EnableTextAction = _enableTextAction;
		settings.Launcher.EnableFileDialogIntegration = _enableFileDialogIntegration;
		settings.Launcher.EnableClipboardAutoCategory = _enableClipboardAutoCategory;
		settings.Launcher.MaxPinnedClipboardItems = _maxPinnedClipboardItems;
		settings.Launcher.TextActionTranslateLanguage = _textActionTranslateLanguage;
		settings.Llm.MaxSubAgents = _maxSubAgents;
		settings.Llm.PdfExportPath = _pdfExportPath;
		settings.Llm.TipDurationSeconds = _tipDurationSeconds;
		settings.Llm.Service = _llmService;
		settings.Llm.Streaming = _llmStreaming;
		settings.Llm.MaxContextTokens = _llmMaxContextTokens;
		settings.Llm.RetentionDays = _llmRetentionDays;
		settings.Llm.Temperature = _llmTemperature;
		settings.Llm.DefaultAgentPermission = _defaultAgentPermission;
		settings.Llm.DefaultOutputFormat = _defaultOutputFormat;
		settings.Llm.DefaultMood = _defaultMood;
		settings.Llm.AutoPreview = _autoPreview;
		settings.Llm.MaxAgentIterations = _maxAgentIterations;
		settings.Llm.MaxRetryOnError = _maxRetryOnError;
		settings.Llm.AgentLogLevel = _agentLogLevel;
		settings.Llm.AgentDecisionLevel = _agentDecisionLevel;
		settings.Llm.PlanMode = _planMode;
		settings.Llm.EnableMultiPassDocument = _enableMultiPassDocument;
		settings.Llm.EnableCoworkVerification = _enableCoworkVerification;
		settings.Llm.EnableFilePathHighlight = _enableFilePathHighlight;
		settings.Llm.FolderDataUsage = _folderDataUsage;
		settings.Llm.EnableAuditLog = _enableAuditLog;
		settings.Llm.EnableAgentMemory = _enableAgentMemory;
		settings.Llm.EnableProjectRules = _enableProjectRules;
		settings.Llm.MaxMemoryEntries = _maxMemoryEntries;
		settings.Llm.EnableImageInput = _enableImageInput;
		settings.Llm.MaxImageSizeKb = _maxImageSizeKb;
		settings.Llm.EnableToolHooks = _enableToolHooks;
		settings.Llm.ToolHookTimeoutMs = _toolHookTimeoutMs;
		settings.Llm.EnableSkillSystem = _enableSkillSystem;
		settings.Llm.SkillsFolderPath = _skillsFolderPath;
		settings.Llm.SlashPopupPageSize = _slashPopupPageSize;
		settings.Llm.EnableDragDropAiActions = _enableDragDropAiActions;
		settings.Llm.DragDropAutoSend = _dragDropAutoSend;
		settings.Llm.Code.EnableCodeReview = _enableCodeReview;
		settings.Llm.EnableAutoRouter = _enableAutoRouter;
		settings.Llm.AutoRouterConfidence = _autoRouterConfidence;
		settings.Llm.EnableChatRainbowGlow = _enableChatRainbowGlow;
		settings.Llm.NotifyOnComplete = _notifyOnComplete;
		settings.Llm.ShowTips = _showTips;
		settings.Llm.DevMode = _devMode;
		settings.Llm.DevModeStepApproval = _devModeStepApproval;
		settings.Llm.WorkflowVisualizer = _workflowVisualizer;
		settings.Llm.FreeTierMode = _freeTierMode;
		settings.Llm.FreeTierDelaySeconds = _freeTierDelaySeconds;
		settings.Llm.ShowTotalCallStats = _showTotalCallStats;
		settings.Llm.OllamaEndpoint = _ollamaEndpoint;
		settings.Llm.OllamaModel = _ollamaModel;
		settings.Llm.VllmEndpoint = _vllmEndpoint;
		settings.Llm.VllmModel = _vllmModel;
		settings.Llm.GeminiModel = _geminiModel;
		settings.Llm.ClaudeModel = _claudeModel;
		settings.Llm.GeminiApiKey = _geminiApiKey;
		settings.Llm.ClaudeApiKey = _claudeApiKey;
		if (!string.IsNullOrEmpty(_ollamaApiKey) && _ollamaApiKey != "(저장됨)")
		{
			settings.Llm.OllamaApiKey = CryptoService.EncryptIfEnabled(_ollamaApiKey, settings.Llm.EncryptionEnabled);
		}
		if (!string.IsNullOrEmpty(_vllmApiKey) && _vllmApiKey != "(저장됨)")
		{
			settings.Llm.VllmApiKey = CryptoService.EncryptIfEnabled(_vllmApiKey, settings.Llm.EncryptionEnabled);
		}
		switch (_llmService)
		{
		case "ollama":
			settings.Llm.Endpoint = _ollamaEndpoint;
			settings.Llm.Model = _ollamaModel;
			settings.Llm.EncryptedApiKey = settings.Llm.OllamaApiKey;
			break;
		case "vllm":
			settings.Llm.Endpoint = _vllmEndpoint;
			settings.Llm.Model = _vllmModel;
			settings.Llm.EncryptedApiKey = settings.Llm.VllmApiKey;
			break;
		case "gemini":
			settings.Llm.ApiKey = _geminiApiKey;
			settings.Llm.Model = _geminiModel;
			break;
		case "claude":
			settings.Llm.ApiKey = _claudeApiKey;
			settings.Llm.Model = _claudeModel;
			break;
		}
		settings.Llm.RegisteredModels = (from rm in RegisteredModels
			where !string.IsNullOrWhiteSpace(rm.Alias)
			select new RegisteredModel
			{
				Alias = rm.Alias,
				EncryptedModelName = rm.EncryptedModelName,
				Service = rm.Service,
				Endpoint = rm.Endpoint,
				ApiKey = rm.ApiKey,
				AuthType = (rm.AuthType ?? "bearer"),
				Cp4dUrl = (rm.Cp4dUrl ?? ""),
				Cp4dUsername = (rm.Cp4dUsername ?? ""),
				Cp4dPassword = (rm.Cp4dPassword ?? "")
			}).ToList();
		settings.Llm.PromptTemplates = (from pt in PromptTemplates
			where !string.IsNullOrWhiteSpace(pt.Name)
			select new PromptTemplate
			{
				Name = pt.Name,
				Content = pt.Content,
				Icon = pt.Icon
			}).ToList();
		settings.IndexPaths = IndexPaths.ToList();
		settings.IndexExtensions = IndexExtensions.ToList();
		settings.IndexSpeed = _indexSpeed;
		LauncherSettings launcher = settings.Launcher;
		CustomThemeColors customThemeColors = launcher.CustomTheme ?? (launcher.CustomTheme = new CustomThemeColors());
		foreach (ColorRowModel colorRow in ColorRows)
		{
			typeof(CustomThemeColors).GetProperty(colorRow.Property)?.SetValue(customThemeColors, colorRow.Hex);
		}
		customThemeColors.WindowCornerRadius = _customWindowCornerRadius;
		customThemeColors.ItemCornerRadius = _customItemCornerRadius;
		List<AliasEntry> first = settings.Aliases.Where(delegate(AliasEntry a)
		{
			bool flag;
			switch (a.Type)
			{
			case "app":
			case "url":
			case "folder":
			case "batch":
				flag = true;
				break;
			default:
				flag = false;
				break;
			}
			return !flag;
		}).ToList();
		settings.Aliases = first.Concat(AppShortcuts.Select((AppShortcutModel sc) => new AliasEntry
		{
			Key = sc.Key,
			Type = sc.Type,
			Target = sc.Target,
			Description = (string.IsNullOrWhiteSpace(sc.Description) ? null : sc.Description)
		})).Concat(BatchCommands.Select((BatchCommandModel b) => new AliasEntry
		{
			Key = b.Key,
			Type = "batch",
			Target = b.Command,
			ShowWindow = b.ShowWindow
		})).ToList();
		settings.Snippets = Snippets.Select((SnippetRowModel sn) => new SnippetEntry
		{
			Key = sn.Key,
			Name = sn.Name,
			Content = sn.Content
		}).ToList();
		settings.Reminder.Enabled = _reminderEnabled;
		settings.Reminder.Corner = _reminderCorner;
		settings.Reminder.IntervalMinutes = _reminderIntervalMinutes;
		settings.Reminder.DisplaySeconds = _reminderDisplaySeconds;
		settings.ScreenCapture.Prefix = (string.IsNullOrWhiteSpace(_capPrefix) ? "cap" : _capPrefix.Trim());
		settings.ScreenCapture.GlobalHotkeyEnabled = _capGlobalHotkeyEnabled;
		settings.ScreenCapture.GlobalHotkey = (string.IsNullOrWhiteSpace(_capGlobalHotkey) ? "PrintScreen" : _capGlobalHotkey.Trim());
		settings.ScreenCapture.GlobalHotkeyMode = _capGlobalMode;
		settings.ScreenCapture.ScrollDelayMs = Math.Max(50, _capScrollDelayMs);
		settings.ClipboardHistory.Enabled = _clipboardEnabled;
		settings.ClipboardHistory.MaxItems = _clipboardMaxItems;
		SystemCommandSettings systemCommands = settings.SystemCommands;
		systemCommands.ShowLock = _sysShowLock;
		systemCommands.ShowSleep = _sysShowSleep;
		systemCommands.ShowRestart = _sysShowRestart;
		systemCommands.ShowShutdown = _sysShowShutdown;
		systemCommands.ShowHibernate = _sysShowHibernate;
		systemCommands.ShowLogout = _sysShowLogout;
		systemCommands.ShowRecycleBin = _sysShowRecycleBin;
		Dictionary<string, List<string>> cmdAliases = new Dictionary<string, List<string>>();
		SaveAlias("lock", _aliasLock);
		SaveAlias("sleep", _aliasSleep);
		SaveAlias("restart", _aliasRestart);
		SaveAlias("shutdown", _aliasShutdown);
		SaveAlias("hibernate", _aliasHibernate);
		SaveAlias("logout", _aliasLogout);
		SaveAlias("recycle", _aliasRecycle);
		systemCommands.CommandAliases = cmdAliases;
		_service.Save();
		this.SaveCompleted?.Invoke(this, EventArgs.Empty);
		void SaveAlias(string key, string val)
		{
			List<string> list = ParseAliases(val);
			if (list.Count > 0)
			{
				cmdAliases[key] = list;
			}
		}
	}

	public bool AddSnippet()
	{
		if (string.IsNullOrWhiteSpace(_newSnippetKey) || string.IsNullOrWhiteSpace(_newSnippetContent))
		{
			return false;
		}
		if (Snippets.Any((SnippetRowModel sn) => sn.Key.Equals(_newSnippetKey.Trim(), StringComparison.OrdinalIgnoreCase)))
		{
			return false;
		}
		Snippets.Add(new SnippetRowModel
		{
			Key = _newSnippetKey.Trim(),
			Name = _newSnippetName.Trim(),
			Content = _newSnippetContent.Trim()
		});
		NewSnippetKey = "";
		NewSnippetName = "";
		NewSnippetContent = "";
		return true;
	}

	public void RemoveSnippet(SnippetRowModel row)
	{
		Snippets.Remove(row);
	}

	public void ResetCapPrefix()
	{
		CapPrefix = "cap";
	}

	public void ResetCapGlobalHotkey()
	{
		CapGlobalHotkey = "PrintScreen";
		CapGlobalMode = "screen";
	}

	public List<string> GetReminderCategories()
	{
		return _service.Settings.Reminder.EnabledCategories;
	}

	public void ResetSystemCommandAliases()
	{
		AliasLock = "";
		AliasSleep = "";
		AliasRestart = "";
		AliasShutdown = "";
		AliasHibernate = "";
		AliasLogout = "";
		AliasRecycle = "";
	}

	private static string FormatAliases(Dictionary<string, List<string>> dict, string key)
	{
		List<string> value;
		return dict.TryGetValue(key, out value) ? string.Join(", ", value) : "";
	}

	private static List<string> ParseAliases(string input)
	{
		return (from s in input.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
			where !string.IsNullOrWhiteSpace(s)
			select s).ToList();
	}

	protected void OnPropertyChanged([CallerMemberName] string? n = null)
	{
		this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(n));
	}
}
