using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using AxCopilot.Models;
using AxCopilot.Services;

namespace AxCopilot.Views.Controls;

/// <summary>
/// Phase 32-A: 우측 슬라이드인 설정 패널.
/// ChatWindow 내부에서 AX Agent 설정을 인라인으로 제어합니다.
/// CC의 Claude.ai 설정 패널과 동등한 UX.
/// </summary>
public partial class AgentSettingsPanel : UserControl
{
    private static App? CurrentApp => System.Windows.Application.Current as App;

    private bool _isOpen;
    private bool _isLoading = true; // 초기 로드 중 이벤트 발생 방지

    /// <summary>서비스 선택 요청 콜백 (ChatWindow.BtnModelSelector_Click으로 위임).</summary>
    public Action? ServiceSelectorRequested;

    /// <summary>모델 선택 요청 콜백 (ChatWindow.BtnModelSelector_Click으로 위임).</summary>
    public Action? ModelSelectorRequested;

    /// <summary>작업 폴더 탐색 요청 콜백 (ChatWindow.BrowseWorkFolder로 위임).</summary>
    public Action? WorkFolderBrowseRequested;

    /// <summary>새 프리셋 저장 요청 콜백 (ChatWindow.ShowCustomPresetDialog(null)로 위임).</summary>
    public Action? PresetSaveRequested;

    /// <summary>프리셋 관리 요청 콜백 (ChatWindow.ShowPresetManagePopup()으로 위임).</summary>
    public Action? PresetManageRequested;

    /// <summary>설정 패널 열림/닫힘 상태.</summary>
    public bool IsOpen
    {
        get => _isOpen;
        set
        {
            if (_isOpen == value) return;
            _isOpen = value;
            AnimateSlide(value);
        }
    }

    /// <summary>설정 변경 시 발생하는 이벤트.</summary>
    public event EventHandler? SettingsChanged;

    /// <summary>닫기 요청 이벤트.</summary>
    public event EventHandler? CloseRequested;

    public AgentSettingsPanel()
    {
        InitializeComponent();
        Visibility = Visibility.Collapsed;
    }

    /// <summary>현재 설정값으로 UI를 초기화합니다.</summary>
    public void LoadFromSettings(SettingsService settings, string activeTab,
        Services.Agent.ToolRegistry? toolRegistry = null)
    {
        _isLoading = true;

        var llm = settings.Settings.Llm;

        TxtCurrentTab.Text = activeTab;
        TxtServiceName.Text = llm.Service ?? "Ollama";
        TxtModelName.Text = llm.Model ?? "unknown";
        TxtApiEndpoint.Text = llm.OllamaEndpoint ?? "";

        SliderMaxIterations.Value = llm.MaxAgentIterations > 0 ? llm.MaxAgentIterations : 25;
        TxtMaxIterations.Text = ((int)SliderMaxIterations.Value).ToString();

        SliderMaxRetry.Value = llm.MaxRetryOnError > 0 ? llm.MaxRetryOnError : 3;
        TxtMaxRetry.Text = ((int)SliderMaxRetry.Value).ToString();

        ChkParallelTools.IsChecked = llm.EnableParallelTools;

        SliderAutoCompact.Value = llm.AutoCompactThreshold > 0 ? llm.AutoCompactThreshold : 80;
        TxtAutoCompact.Text = ((int)SliderAutoCompact.Value).ToString();

        // Phase 17-A: Reflexion 설정 로드
        var reflexion = llm.Reflexion;
        ChkReflexionEnabled.IsChecked = reflexion?.Enabled ?? true;
        ChkReflexionSuccessOnly.IsChecked = reflexion?.EvaluateOnSuccess ?? true;
        SliderReflexionMaxEntries.Value = reflexion?.MaxContextEntries > 0 ? reflexion.MaxContextEntries : 5;
        TxtReflexionMaxEntries.Text = ((int)SliderReflexionMaxEntries.Value).ToString();

        ChkDevMode.IsChecked = llm.DevMode;

        // 탭별 설정 표시
        PanelCoworkSettings.Visibility = activeTab == "Cowork" ? Visibility.Visible : Visibility.Collapsed;
        PanelCodeSettings.Visibility = activeTab == "Code" ? Visibility.Visible : Visibility.Collapsed;
        PanelWorkFolder.Visibility = activeTab == "Code" ? Visibility.Visible : Visibility.Collapsed;

        if (activeTab == "Cowork")
        {
            ChkCoworkVerify.IsChecked = llm.EnableCoworkVerification;
        }
        else if (activeTab == "Code")
        {
            ChkCodeLsp.IsChecked = llm.Code?.EnableLsp ?? true;
            ChkCodeVerify.IsChecked = llm.Code?.EnableCodeVerification ?? false;
        }

        // 도구 토글 동적 생성
        BuildToolToggles(settings, toolRegistry);

        // 작업 폴더 표시 (Code 탭)
        UpdateWorkFolder(settings);
        // MCP 서버 목록 표시
        BuildMcpServerList(settings);

        // Phase 17-C: 훅 UI 초기화
        if (ChkExtendedHooks != null)
            ChkExtendedHooks.IsChecked = llm.EnableToolHooks;
        RefreshHookSummary();

        _isLoading = false;
    }

    /// <summary>활성 탭 변경 시 UI를 업데이트합니다.</summary>
    public void UpdateActiveTab(string tab)
    {
        TxtCurrentTab.Text = tab;
        PanelCoworkSettings.Visibility = tab == "Cowork" ? Visibility.Visible : Visibility.Collapsed;
        PanelCodeSettings.Visibility   = tab == "Code" ? Visibility.Visible : Visibility.Collapsed;
        PanelWorkFolder.Visibility     = tab == "Code" ? Visibility.Visible : Visibility.Collapsed;
    }

    private void BuildToolToggles(SettingsService settings,
        Services.Agent.ToolRegistry? externalRegistry = null)
    {
        PanelToolToggles.Children.Clear();

        // Phase 17-UI: 외부에서 전달된 레지스트리 우선, 없으면 독립 생성
        var registry = externalRegistry ?? Services.Agent.ToolRegistry.CreateDefault();
        if (registry == null) return;

        var disabled = new HashSet<string>(
            settings.Settings.Llm.DisabledTools ?? new List<string>(),
            StringComparer.OrdinalIgnoreCase);

        foreach (var tool in registry.All.OrderBy(t => t.Name))
        {
            var grid = new Grid { Margin = new Thickness(0, 0, 0, 4) };
            grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });

            var label = new TextBlock
            {
                Text = tool.Name,
                FontSize = 11,
                Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
                VerticalAlignment = VerticalAlignment.Center,
            };
            Grid.SetColumn(label, 0);

            var toggle = new CheckBox
            {
                IsChecked = !disabled.Contains(tool.Name),
                Tag = tool.Name,
                VerticalAlignment = VerticalAlignment.Center,
            };
            if (TryFindResource("ToggleSwitch") is Style toggleStyle)
                toggle.Style = toggleStyle;
            toggle.Checked += ToolToggle_Changed;
            toggle.Unchecked += ToolToggle_Changed;
            Grid.SetColumn(toggle, 1);

            grid.Children.Add(label);
            grid.Children.Add(toggle);
            PanelToolToggles.Children.Add(grid);
        }
    }

    #region ── 이벤트 핸들러 ──

    private void BtnClose_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        IsOpen = false;
        CloseRequested?.Invoke(this, EventArgs.Empty);
    }

    private void BtnServiceSelector_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        ServiceSelectorRequested?.Invoke();
    }

    private void BtnModelSelector_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        ModelSelectorRequested?.Invoke();
    }

    private void BtnWorkFolderBrowse_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        WorkFolderBrowseRequested?.Invoke();
    }

    private void BtnPresetSave_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
        => PresetSaveRequested?.Invoke();

    private void BtnPresetManage_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
        => PresetManageRequested?.Invoke();

    private void UpdateWorkFolder(SettingsService settings)
    {
        var folder = settings.Settings.Llm.WorkFolder;
        if (TxtWorkFolder == null) return;
        TxtWorkFolder.Text = string.IsNullOrWhiteSpace(folder)
            ? "(미지정)"
            : System.IO.Path.GetFileName(folder) is { Length: > 0 } name ? name : folder;
        TxtWorkFolder.ToolTip = folder;
    }

    private void BuildMcpServerList(SettingsService settings)
    {
        if (PanelMcpServers == null) return;
        PanelMcpServers.Children.Clear();

        var servers = settings.Settings.Llm.McpServers;
        if (servers == null || servers.Count == 0)
        {
            PanelMcpServers.Children.Add(new TextBlock
            {
                Text = "등록된 MCP 서버 없음",
                FontSize = 11,
                Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
                Margin = new Thickness(0, 0, 0, 4),
            });
            return;
        }

        foreach (var server in servers)
        {
            var grid = new System.Windows.Controls.Grid { Margin = new Thickness(0, 0, 0, 6) };
            grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(8) });
            grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });

            var dot = new System.Windows.Shapes.Ellipse
            {
                Width = 6, Height = 6,
                Fill = server.Enabled
                    ? new SolidColorBrush(Color.FromRgb(0x38, 0xA1, 0x69))
                    : new SolidColorBrush(Color.FromRgb(0x9E, 0x9E, 0x9E)),
                VerticalAlignment = VerticalAlignment.Center,
            };
            Grid.SetColumn(dot, 0);

            var nameLabel = new TextBlock
            {
                Text = server.Name,
                FontSize = 11,
                Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.White,
                VerticalAlignment = VerticalAlignment.Center,
                Margin = new Thickness(6, 0, 0, 0),
                TextTrimming = System.Windows.TextTrimming.CharacterEllipsis,
            };
            Grid.SetColumn(nameLabel, 1);

            var chk = new CheckBox
            {
                IsChecked = server.Enabled,
                Tag = server.Name,
                VerticalAlignment = VerticalAlignment.Center,
            };
            if (TryFindResource("ToggleSwitch") is Style toggleStyle)
                chk.Style = toggleStyle;
            chk.Checked += McpToggle_Changed;
            chk.Unchecked += McpToggle_Changed;
            Grid.SetColumn(chk, 2);

            grid.Children.Add(dot);
            grid.Children.Add(nameLabel);
            grid.Children.Add(chk);
            PanelMcpServers.Children.Add(grid);
        }
    }

    private void McpToggle_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading || sender is not CheckBox chk || chk.Tag is not string name) return;
        var app = System.Windows.Application.Current as App;
        var settings = app?.SettingsService;
        if (settings == null) return;
        var server = settings.Settings.Llm.McpServers?.FirstOrDefault(s => s.Name == name);
        if (server == null) return;
        server.Enabled = chk.IsChecked == true;
        settings.Save();
        SettingsChanged?.Invoke(this, EventArgs.Empty);
    }

    private void TxtApiEndpoint_LostFocus(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        SaveSetting(s => s.Llm.OllamaEndpoint = TxtApiEndpoint.Text);
    }

    private void SliderMaxIterations_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        if (_isLoading || TxtMaxIterations == null) return;
        var val = (int)SliderMaxIterations.Value;
        TxtMaxIterations.Text = val.ToString();
        SaveSetting(s => s.Llm.MaxAgentIterations = val);
    }

    private void SliderMaxRetry_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        if (_isLoading || TxtMaxRetry == null) return;
        var val = (int)SliderMaxRetry.Value;
        TxtMaxRetry.Text = val.ToString();
        SaveSetting(s => s.Llm.MaxRetryOnError = val);
    }

    private void ChkParallelTools_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        SaveSetting(s => s.Llm.EnableParallelTools = ChkParallelTools.IsChecked == true);
    }

    private void ChkCoworkVerify_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        SaveSetting(s => s.Llm.EnableCoworkVerification = ChkCoworkVerify.IsChecked == true);
    }

    private void ChkCodeLsp_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        SaveSetting(s => { if (s.Llm.Code != null) s.Llm.Code.EnableLsp = ChkCodeLsp.IsChecked == true; });
    }

    private void ChkCodeVerify_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        SaveSetting(s => { if (s.Llm.Code != null) s.Llm.Code.EnableCodeVerification = ChkCodeVerify.IsChecked == true; });
    }

    private void SliderAutoCompact_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        if (_isLoading || TxtAutoCompact == null) return;
        var val = (int)SliderAutoCompact.Value;
        TxtAutoCompact.Text = val.ToString();
        SaveSetting(s => s.Llm.AutoCompactThreshold = val);
    }

    private void ChkProjectRules_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        // 프로젝트 규칙 활성/비활성 — 현재 세션에만 영향
    }

    private void ChkDevMode_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        SaveSetting(s => s.Llm.DevMode = ChkDevMode.IsChecked == true);
    }

    // ── Phase 17-C: 훅 이벤트 UI ─────────────────────────────────────────

    private void ChkExtendedHooks_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        SaveSetting(s => s.Llm.EnableToolHooks = ChkExtendedHooks.IsChecked == true);
        RefreshHookSummary();
    }

    private void BtnViewHooks_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        // ChatWindow에서 /hooks 슬래시 명령 실행
        var chatWin = System.Windows.Application.Current?.Windows
            .OfType<ChatWindow>()
            .FirstOrDefault(w => w.IsVisible);
        chatWin?.InjectSlashCommand("/hooks");
    }

    private void BtnOpenHookSettings_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        // settings.json 파일을 기본 편집기로 열기
        var path = System.IO.Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
            "AxCopilot", "settings.dat");
        if (System.IO.File.Exists(path))
            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(path)
                { UseShellExecute = true });
    }

    private void RefreshHookSummary()
    {
        if (HookSummaryText == null) return;

        var settings = CurrentApp?.SettingsService?.Settings;
        if (settings == null) { HookSummaryText.Text = "설정 로드 실패"; return; }

        if (!settings.Llm.EnableToolHooks)
        {
            HookSummaryText.Text = "확장 훅 비활성화됨";
            return;
        }

        var hooks = settings.Llm.ExtendedHooks;
        var counts = new[]
        {
            hooks.PreToolUse.Count(h => h.Enabled),
            hooks.PostToolUse.Count(h => h.Enabled),
            hooks.PostToolUseFailure.Count(h => h.Enabled),
            hooks.SessionStart.Count(h => h.Enabled),
            hooks.SessionEnd.Count(h => h.Enabled),
            hooks.UserPromptSubmit.Count(h => h.Enabled),
            hooks.AgentStop.Count(h => h.Enabled),
            hooks.PreCompact.Count(h => h.Enabled),
            hooks.PostCompact.Count(h => h.Enabled),
            hooks.FileChanged.Count(h => h.Enabled),
            hooks.PermissionRequest.Count(h => h.Enabled),
        };

        var total = counts.Sum();
        if (total == 0)
        {
            HookSummaryText.Text = "등록된 훅 없음  ·  settings.json extended_hooks에서 추가";
            return;
        }

        var parts = new List<string>();
        if (hooks.PreToolUse.Any(h => h.Enabled))   parts.Add($"PreTool×{hooks.PreToolUse.Count(h => h.Enabled)}");
        if (hooks.PostToolUse.Any(h => h.Enabled))  parts.Add($"PostTool×{hooks.PostToolUse.Count(h => h.Enabled)}");
        if (hooks.SessionStart.Any(h => h.Enabled)) parts.Add($"Session×{hooks.SessionStart.Count(h => h.Enabled)}");
        if (hooks.UserPromptSubmit.Any(h => h.Enabled)) parts.Add($"Prompt×{hooks.UserPromptSubmit.Count(h => h.Enabled)}");

        HookSummaryText.Text = $"활성 훅 {total}개  ·  {string.Join(", ", parts)}";
    }

    // ── Phase 17-A: Reflexion 핸들러 ──────────────────────────────────────

    private void ChkReflexion_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        SaveSetting(s =>
        {
            s.Llm.Reflexion ??= new Models.ReflexionConfig();
            s.Llm.Reflexion.Enabled = ChkReflexionEnabled.IsChecked == true;
        });
    }

    private void ChkReflexionSuccessOnly_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading) return;
        SaveSetting(s =>
        {
            s.Llm.Reflexion ??= new Models.ReflexionConfig();
            s.Llm.Reflexion.EvaluateOnSuccess = ChkReflexionSuccessOnly.IsChecked == true;
        });
    }

    private void SliderReflexionMaxEntries_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        if (_isLoading || TxtReflexionMaxEntries == null) return;
        var val = (int)SliderReflexionMaxEntries.Value;
        TxtReflexionMaxEntries.Text = val.ToString();
        SaveSetting(s =>
        {
            s.Llm.Reflexion ??= new Models.ReflexionConfig();
            s.Llm.Reflexion.MaxContextEntries = val;
        });
    }

    private void ToolToggle_Changed(object sender, RoutedEventArgs e)
    {
        if (_isLoading || sender is not CheckBox chk || chk.Tag is not string toolName) return;

        SaveSetting(s =>
        {
            s.Llm.DisabledTools ??= new List<string>();
            if (chk.IsChecked == true)
                s.Llm.DisabledTools.Remove(toolName);
            else if (!s.Llm.DisabledTools.Contains(toolName))
                s.Llm.DisabledTools.Add(toolName);
        });
    }

    #endregion

    #region ── 설정 저장 & 애니메이션 ──

    private void SaveSetting(Action<Models.AppSettings> apply)
    {
        var svc = CurrentApp?.SettingsService;
        if (svc == null) return;

        apply(svc.Settings);
        svc.Save();
        SettingsChanged?.Invoke(this, EventArgs.Empty);
    }

    private void AnimateSlide(bool open)
    {
        if (open)
        {
            Visibility = Visibility.Visible;
            var anim = new DoubleAnimation(300, 0, TimeSpan.FromMilliseconds(200))
            {
                EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut }
            };
            SlideTransform.BeginAnimation(TranslateTransform.XProperty, anim);
        }
        else
        {
            var anim = new DoubleAnimation(0, 300, TimeSpan.FromMilliseconds(150))
            {
                EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseIn }
            };
            anim.Completed += (_, _) =>
            {
                if (!_isOpen) Visibility = Visibility.Collapsed;
            };
            SlideTransform.BeginAnimation(TranslateTransform.XProperty, anim);
        }
    }

    #endregion
}
