using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using AxCopilot.Models;
using AxCopilot.Services;
using AxCopilot.Services.Agent;

namespace AxCopilot.Views;

public partial class ChatWindow
{
    // ─── Phase 34: Cowork/Code 공통 에이전트 루프 실행 ──────────────────

    /// <summary>
    /// Cowork/Code 탭 공통 에이전트 루프 실행.
    /// 기존 Cowork/Code 분기의 중복 코드(~70줄)를 단일 메서드로 통합.
    /// </summary>
    private async Task<string> RunAgentLoopAsync(string tab, List<ChatMessage> sendMessages, CancellationToken ct)
    {
        OpenWorkflowAnalyzerIfEnabled();

        _agentCumulativeInputTokens = 0;
        _agentCumulativeOutputTokens = 0;

        // 탭별 시스템 프롬프트 삽입
        var systemPrompt = tab == "Code" ? BuildCodeSystemPrompt() : BuildCoworkSystemPrompt();
        if (!string.IsNullOrEmpty(systemPrompt))
            sendMessages.Insert(0, new ChatMessage { Role = "system", Content = systemPrompt });

        _agentLoop.ActiveTab = tab;
        _agentLoop.EventOccurred += OnAgentEvent;
        _agentLoop.UserDecisionCallback = CreatePlanDecisionCallback();
        try
        {
            var response = await _agentLoop.RunAsync(sendMessages, ct);

            // 완료 알림
            if (Llm.NotifyOnComplete)
            {
                var label = tab == "Code" ? "AX Code Agent" : "AX Cowork Agent";
                var desc = tab == "Code" ? "코드 작업이 완료되었습니다." : "코워크 작업이 완료되었습니다.";
                Services.NotificationService.Notify(label, desc);
            }

            return response;
        }
        finally
        {
            _agentLoop.EventOccurred -= OnAgentEvent;
            _agentLoop.UserDecisionCallback = null;
        }
    }

    // ─── 코워크 에이전트 지원 ────────────────────────────────────────────

    private string BuildCoworkSystemPrompt()
    {
        var workFolder = GetCurrentWorkFolder();
        var llm = Llm;
        var sb = new System.Text.StringBuilder();
        sb.AppendLine("You are AX Copilot Agent. You can read, write, and edit files using the provided tools.");
        sb.AppendLine($"Today's date: {DateTime.Now:yyyy년 M월 d일} ({DateTime.Now:yyyy-MM-dd}, {DateTime.Now:dddd}).");
        sb.AppendLine("Available skills: excel_create (.xlsx), docx_create (.docx), csv_create (.csv), markdown_create (.md), html_create (.html), script_create (.bat/.ps1), document_review (품질 검증), format_convert (포맷 변환).");
        sb.AppendLine("Always explain your plan step by step BEFORE executing tools. After creating files, summarize what was created.");
        sb.AppendLine("IMPORTANT: When creating documents with dates, always use today's actual date above. Never use placeholder or fictional dates.");
        sb.AppendLine("IMPORTANT: When asked to create a document with multiple sections (reports, proposals, analyses, etc.), you MUST:");
        sb.AppendLine("  1. First, plan the document: decide the exact sections (headings), their order, and key points for each section based on the topic.");
        sb.AppendLine("  2. Call document_plan with sections_hint = your planned section titles (comma-separated). Example: sections_hint=\"회사 개요, 사업 현황, 재무 분석, SWOT, 전략 제언, 결론\"");
        sb.AppendLine("     This ensures the document structure matches YOUR plan, not a generic template.");
        sb.AppendLine("  3. Then immediately call html_create (or docx_create/file_write) using the scaffold from document_plan.");
        sb.AppendLine("  4. Write actual detailed content for EVERY section — no skipping, no placeholders, no minimal content.");
        sb.AppendLine("  5. Do NOT call html_create directly without document_plan for multi-section documents.");

        // 문서 품질 검증 루프
        sb.AppendLine("\n## Document Quality Review");
        sb.AppendLine("After creating any document (html_create, docx_create, excel_create, etc.), you MUST perform a self-review:");
        sb.AppendLine("1. Use file_read to read the generated file and verify the content is complete");
        sb.AppendLine("2. Check for logical errors: incorrect dates, inconsistent data, missing sections, broken formatting");
        sb.AppendLine("3. Verify all requested topics/sections from the user's original request are covered");
        sb.AppendLine("4. If issues found, fix them using file_write or file_edit, then re-verify");
        sb.AppendLine("5. Report the review result to the user: what was checked and whether corrections were made");

        // 문서 포맷 변환 지원
        sb.AppendLine("\n## Format Conversion");
        sb.AppendLine("When the user requests format conversion (e.g., HTML→Word, Excel→CSV, Markdown→HTML):");
        sb.AppendLine("1. Use file_read or document_read to read the source file content");
        sb.AppendLine("2. Create a new file in the target format using the appropriate skill (docx_create, html_create, etc.)");
        sb.AppendLine("3. Preserve the content structure, formatting, and data as closely as possible");

        // 사용자 지정 출력 포맷
        var fmt = llm.DefaultOutputFormat;
        if (!string.IsNullOrEmpty(fmt) && fmt != "auto")
        {
            var fmtMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                ["xlsx"] = "Excel (.xlsx) using excel_create",
                ["docx"] = "Word (.docx) using docx_create",
                ["html"] = "HTML (.html) using html_create",
                ["md"] = "Markdown (.md) using markdown_create",
                ["csv"] = "CSV (.csv) using csv_create",
            };
            if (fmtMap.TryGetValue(fmt, out var fmtDesc))
                sb.AppendLine($"IMPORTANT: User prefers output format: {fmtDesc}. Use this format unless the user specifies otherwise.");
        }

        // 디자인 무드 — HTML 문서 생성 시 mood 파라미터로 전달하도록 안내
        if (!string.IsNullOrEmpty(_selectedMood) && _selectedMood != "modern")
            sb.AppendLine($"When creating HTML documents with html_create, use mood=\"{_selectedMood}\" for the design template.");
        else
            sb.AppendLine("When creating HTML documents with html_create, you can set 'mood' parameter: modern, professional, creative, minimal, elegant, dark, colorful, corporate, magazine, dashboard.");

        if (!string.IsNullOrEmpty(workFolder))
            sb.AppendLine($"Current work folder: {workFolder}");
        sb.AppendLine($"File permission mode: {llm.FilePermission}");

        // 폴더 데이터 활용 지침
        switch (_folderDataUsage)
        {
            case "active":
                sb.AppendLine("IMPORTANT: Folder Data Usage = ACTIVE. You have 'document_read' and 'folder_map' tools available.");
                sb.AppendLine("Before creating reports, use folder_map to scan the work folder structure. " +
                    "Then EVALUATE whether each document is RELEVANT to the user's current request topic. " +
                    "Only use document_read on files that are clearly related to the conversation subject. " +
                    "Do NOT read or reference files that are unrelated to the user's request, even if they exist in the folder. " +
                    "In your planning step, list which files you plan to read and explain WHY they are relevant.");
                break;
            case "passive":
                sb.AppendLine("Folder Data Usage = PASSIVE. You have 'document_read' and 'folder_map' tools. " +
                    "Only read folder documents when the user explicitly asks you to reference or use them.");
                break;
            default: // "none"
                sb.AppendLine("Folder Data Usage = NONE. Do NOT read or reference documents in the work folder unless the user explicitly provides a file path.");
                break;
        }

        // 프리셋 시스템 프롬프트가 있으면 추가
        lock (_convLock)
        {
            if (_currentConversation != null && !string.IsNullOrEmpty(_currentConversation.SystemCommand))
                sb.AppendLine("\n" + _currentConversation.SystemCommand);
        }

        // 프로젝트 문맥 파일 (AX.md) 주입 — Phase 27-C: @include 지시어 해석 포함
        sb.Append(LoadProjectContext(workFolder));

        // 프로젝트 규칙 (.ax/rules/) 자동 주입
        sb.Append(BuildProjectRulesSection(workFolder));

        // 에이전트 메모리 주입
        sb.Append(BuildMemorySection(workFolder));

        // 피드백 학습 컨텍스트 주입
        sb.Append(BuildFeedbackContext());

        // Phase 27-B: 현재 파일 경로 기반 자동 스킬 주입
        sb.Append(BuildPathBasedSkillSection());

        return sb.ToString();
    }

    private string BuildCodeSystemPrompt()
    {
        var workFolder = GetCurrentWorkFolder();
        var llm = Llm;
        var code = llm.Code;
        var sb = new System.Text.StringBuilder();

        sb.AppendLine("You are AX Copilot Code Agent — a senior software engineer for enterprise development.");
        sb.AppendLine($"Today's date: {DateTime.Now:yyyy년 M월 d일} ({DateTime.Now:yyyy-MM-dd}).");
        sb.AppendLine("Available tools: file_read, file_write, file_edit (supports replace_all), glob, grep (supports context_lines, case_sensitive), folder_map, process, dev_env_detect, build_run, git_tool.");
        sb.AppendLine("IMPORTANT: When creating documents with dates, always use today's actual date above.");

        sb.AppendLine("\n## Core Workflow (MANDATORY — follow this order)");
        sb.AppendLine("1. ORIENT: Run folder_map (depth=2) to understand project structure. Check .gitignore, README, config files.");
        sb.AppendLine("2. BASELINE: If tests exist, run build_run action='test' FIRST to establish baseline. Record pass/fail count.");
        sb.AppendLine("3. ANALYZE: Use grep (with context_lines=2) + file_read to deeply understand the code you'll modify.");
        sb.AppendLine("   - Always check callers/references: grep for function/class names to find all usage points.");
        sb.AppendLine("   - Read test files related to the code you're changing to understand expected behavior.");
        sb.AppendLine("4. PLAN: Present your analysis + impact assessment. List ALL files that will be modified.");
        sb.AppendLine("   - Explain WHY each change is needed and what could break.");
        sb.AppendLine("   - Wait for user approval before proceeding.");
        sb.AppendLine("5. IMPLEMENT: Apply changes using file_edit (preferred — shows diff). Use file_write only for new files.");
        sb.AppendLine("   - Make the MINIMUM changes needed. Don't refactor unrelated code.");
        sb.AppendLine("   - Prefer file_edit with replace_all=false for precision edits.");
        sb.AppendLine("6. VERIFY: Run build_run action='build' then action='test'. Compare results with baseline.");
        sb.AppendLine("   - If tests fail that passed before, fix immediately.");
        sb.AppendLine("   - If build fails, analyze error output and correct.");
        sb.AppendLine("7. GIT: Use git_tool to check status, create diff, and optionally commit.");
        sb.AppendLine("8. REPORT: Summarize changes, test results, and any remaining concerns.");

        sb.AppendLine("\n## Development Environment");
        sb.AppendLine("Use dev_env_detect to check installed IDEs, runtimes, and build tools before running commands.");
        sb.AppendLine("IMPORTANT: Do NOT attempt to install compilers, IDEs, or build tools. Only use what is already installed.");

        // 패키지 저장소 정보
        sb.AppendLine("\n## Package Repositories");
        if (!string.IsNullOrEmpty(code.NexusBaseUrl))
            sb.AppendLine($"Enterprise Nexus: {code.NexusBaseUrl}");
        sb.AppendLine($"NuGet (.NET): {code.NugetSource}");
        sb.AppendLine($"PyPI/Conda (Python): {code.PypiSource}");
        sb.AppendLine($"Maven (Java): {code.MavenSource}");
        sb.AppendLine($"npm (JavaScript): {code.NpmSource}");
        sb.AppendLine("When adding dependencies, use these repository URLs.");

        // IDE 정보
        if (!string.IsNullOrEmpty(code.PreferredIdePath))
            sb.AppendLine($"\nPreferred IDE: {code.PreferredIdePath}");

        // 사용자 선택 개발 언어
        if (_selectedLanguage != "auto")
        {
            var langName = _selectedLanguage switch { "python" => "Python", "java" => "Java", "csharp" => "C# (.NET)", "cpp" => "C/C++", "javascript" => "JavaScript/TypeScript", _ => _selectedLanguage };
            sb.AppendLine($"\nIMPORTANT: User selected language: {langName}. Prioritize this language for code analysis and generation.");
        }

        // 언어별 가이드라인
        sb.AppendLine("\n## Language Guidelines");
        sb.AppendLine("- C# (.NET): Use dotnet CLI. NuGet for packages. Follow Microsoft naming conventions.");
        sb.AppendLine("- Python: Use conda/pip. Follow PEP8. Use type hints. Virtual env preferred.");
        sb.AppendLine("- Java: Use Maven/Gradle. Follow Google Java Style Guide.");
        sb.AppendLine("- C++: Use CMake for build. Follow C++ Core Guidelines.");
        sb.AppendLine("- JavaScript/TypeScript: Use npm/yarn. Follow ESLint rules. Vue3 uses Composition API.");

        // 코드 품질 + 안전 수칙
        sb.AppendLine("\n## Code Quality & Safety");
        sb.AppendLine("- NEVER delete or overwrite files without user confirmation.");
        sb.AppendLine("- ALWAYS read a file before editing it. Don't guess contents.");
        sb.AppendLine("- Prefer file_edit over file_write for existing files (shows diff).");
        sb.AppendLine("- Use grep to find ALL references before renaming/removing anything.");
        sb.AppendLine("- If unsure about a change's impact, ask the user first.");
        sb.AppendLine("- For large refactors, do them incrementally with build verification between steps.");
        sb.AppendLine("- Use git_tool action='diff' to review your changes before committing.");

        sb.AppendLine("\n## Lint & Format");
        sb.AppendLine("After code changes, check for available linters:");
        sb.AppendLine("- Python: ruff, black, flake8, pylint");
        sb.AppendLine("- JavaScript: eslint, prettier");
        sb.AppendLine("- C#: dotnet format");
        sb.AppendLine("- C++: clang-format");
        sb.AppendLine("Run the appropriate linter via process tool if detected by dev_env_detect.");

        if (!string.IsNullOrEmpty(workFolder))
            sb.AppendLine($"\nCurrent work folder: {workFolder}");
        sb.AppendLine($"File permission mode: {llm.FilePermission}");

        // 폴더 데이터 활용
        sb.AppendLine("\nFolder Data Usage = ACTIVE. Use folder_map and file_read to understand the codebase.");
        sb.AppendLine("Analyze project structure before making changes. Read relevant files to understand context.");

        // 프리셋 시스템 프롬프트
        lock (_convLock)
        {
            if (_currentConversation?.SystemCommand is { Length: > 0 } sysCmd)
                sb.AppendLine("\n" + sysCmd);
        }

        // 프로젝트 문맥 파일 (AX.md) 주입 — Phase 27-C: @include 지시어 해석 포함
        sb.Append(LoadProjectContext(workFolder));

        // 프로젝트 규칙 (.ax/rules/) 자동 주입
        sb.Append(BuildProjectRulesSection(workFolder));

        // 에이전트 메모리 주입
        sb.Append(BuildMemorySection(workFolder));

        // 피드백 학습 컨텍스트 주입
        sb.Append(BuildFeedbackContext());

        // Phase 27-B: 현재 파일 경로 기반 자동 스킬 주입
        sb.Append(BuildPathBasedSkillSection());

        return sb.ToString();
    }

    /// <summary>프로젝트 규칙 (.ax/rules/)을 시스템 프롬프트 섹션으로 포맷합니다.</summary>
    private string BuildProjectRulesSection(string? workFolder)
    {
        if (string.IsNullOrEmpty(workFolder)) return "";
        if (!Llm.EnableProjectRules) return "";

        try
        {
            var rules = Services.Agent.ProjectRulesService.LoadRules(workFolder);
            if (rules.Count == 0) return "";

            // 컨텍스트별 필터링: Cowork=document, Code=always (기본)
            var when = _activeTab == "Code" ? "always" : "always";
            var filtered = Services.Agent.ProjectRulesService.FilterRules(rules, when);
            return Services.Agent.ProjectRulesService.FormatForSystemPrompt(filtered);
        }
        catch (Exception)
        {
            return "";
        }
    }

    /// <summary>에이전트 메모리를 시스템 프롬프트 섹션으로 포맷합니다.</summary>
    private string BuildMemorySection(string? workFolder)
    {
        if (!Llm.EnableAgentMemory) return "";

        var memService = CurrentApp?.MemoryService;
        if (memService == null || memService.Count == 0) return "";

        // 메모리를 로드 (작업 폴더 변경 시 재로드)
        memService.Load(workFolder ?? "");

        var all = memService.All;
        if (all.Count == 0) return "";

        var sb = new System.Text.StringBuilder();
        sb.AppendLine("\n## 프로젝트 메모리 (이전 대화에서 학습한 내용)");
        sb.AppendLine("아래는 이전 대화에서 학습한 규칙과 선호도입니다. 작업 시 참고하세요.");
        sb.AppendLine("새로운 규칙이나 선호도를 발견하면 memory 도구의 save 액션으로 저장하세요.");
        sb.AppendLine("사용자가 이전 학습 내용과 다른 지시를 하면 memory 도구의 delete 후 새로 save 하세요.\n");

        foreach (var group in all.GroupBy(e => e.Type))
        {
            var label = group.Key switch
            {
                "rule" => "프로젝트 규칙",
                "preference" => "사용자 선호",
                "fact" => "프로젝트 사실",
                "correction" => "이전 교정",
                _ => group.Key,
            };
            sb.AppendLine($"[{label}]");
            foreach (var e in group.OrderByDescending(e => e.UseCount).Take(15))
                sb.AppendLine($"- {e.Content}");
            sb.AppendLine();
        }

        return sb.ToString();
    }

    /// <summary>워크플로우 시각화 설정이 켜져있으면 분석기 창을 열고 이벤트를 구독합니다.</summary>
    private void OpenWorkflowAnalyzerIfEnabled()
    {
        var llm = Llm;
        if (!llm.DevMode || !llm.WorkflowVisualizer) return;

        if (_analyzerWindow == null)
        {
            // 새로 생성
            _analyzerWindow = new WorkflowAnalyzerWindow();
            _analyzerWindow.Closed += (_, _) => _analyzerWindow = null;
            // 테마 리소스 전달
            foreach (var dict in System.Windows.Application.Current.Resources.MergedDictionaries)
                _analyzerWindow.Resources.MergedDictionaries.Add(dict);
            _analyzerWindow.Show();
        }
        else if (!_analyzerWindow.IsVisible)
        {
            // Hide()로 숨겨진 창 → 기존 내용 유지한 채 다시 표시
            _analyzerWindow.Show();
            _analyzerWindow.Activate();
        }
        else
        {
            // 이미 보이는 상태 → 새 에이전트 실행을 위해 초기화 후 활성화
            _analyzerWindow.Reset();
            _analyzerWindow.Activate();
        }

        // 타임라인 탭으로 전환 (새 실행 시작)
        _analyzerWindow.SwitchToTimelineTab();

        // 이벤트 구독 (중복 방지)
        _agentLoop.EventOccurred -= _analyzerWindow.OnAgentEvent;
        _agentLoop.EventOccurred += _analyzerWindow.OnAgentEvent;
    }

    /// <summary>워크플로우 분석기 버튼의 표시 상태를 갱신합니다.</summary>
    private void UpdateAnalyzerButtonVisibility()
    {
        var llm = Llm;
        BtnShowAnalyzer.Visibility = (llm.DevMode && llm.WorkflowVisualizer)
            ? Visibility.Visible : Visibility.Collapsed;
    }

    /// <summary>워크플로우 분석기 창을 수동으로 열거나 포커스합니다 (하단 바 버튼).</summary>
    private void BtnShowAnalyzer_Click(object sender, MouseButtonEventArgs e)
    {
        if (_analyzerWindow == null)
        {
            _analyzerWindow = new WorkflowAnalyzerWindow();
            _analyzerWindow.Closed += (_, _) => _analyzerWindow = null;
            foreach (var dict in System.Windows.Application.Current.Resources.MergedDictionaries)
                _analyzerWindow.Resources.MergedDictionaries.Add(dict);
            // 에이전트 이벤트 구독
            _agentLoop.EventOccurred -= _analyzerWindow.OnAgentEvent;
            _agentLoop.EventOccurred += _analyzerWindow.OnAgentEvent;
            _analyzerWindow.Show();
        }
        else if (!_analyzerWindow.IsVisible)
        {
            _analyzerWindow.Show();
            _analyzerWindow.Activate();
        }
        else
        {
            _analyzerWindow.Activate();
        }
    }

    // ─── Phase 18-A: 백그라운드 에이전트 완료 알림 ──────────────────────────

    /// <summary>
    /// 위임 에이전트(delegate_agent)가 백그라운드에서 완료되면 트레이 알림을 표시합니다.
    /// </summary>
    private void OnBackgroundAgentCompleted(object? sender, AgentCompletedEventArgs e)
    {
        // UI 스레드에서 안전하게 실행
        Dispatcher.BeginInvoke(() =>
        {
            var task = e.Task;
            if (e.Error != null)
            {
                Services.NotificationService.Notify(
                    $"에이전트 '{task.AgentType}' 실패",
                    $"ID {task.Id}: {e.Error[..Math.Min(80, e.Error.Length)]}");
            }
            else
            {
                Services.NotificationService.Notify(
                    $"에이전트 '{task.AgentType}' 완료",
                    $"ID {task.Id}: {task.Description[..Math.Min(60, task.Description.Length)]}");
            }
        });
    }

    /// <summary>에이전트 루프 동안 누적 토큰 (하단 바 표시용)</summary>
    private int _agentCumulativeInputTokens;
    private int _agentCumulativeOutputTokens;

    private static readonly HashSet<string> WriteToolNames = new(StringComparer.OrdinalIgnoreCase)
    {
        "file_write", "file_edit", "html_create", "xlsx_create",
        "docx_create", "csv_create", "md_create", "script_create",
        "diff_preview", "open_external",
    };

    private void OnAgentEvent(AgentEvent evt)
    {
        // 에이전트 이벤트를 채팅 UI에 표시 (도구 호출/결과 배너)
        AddAgentEventBanner(evt);
        AutoScrollIfNeeded();

        // 하단 상태바 업데이트
        UpdateStatusBar(evt);

        // 하단 바 토큰 누적 업데이트 (에이전트 루프 전체 합계)
        if (evt.InputTokens > 0 || evt.OutputTokens > 0)
        {
            _agentCumulativeInputTokens += evt.InputTokens;
            _agentCumulativeOutputTokens += evt.OutputTokens;
            UpdateStatusTokens(_agentCumulativeInputTokens, _agentCumulativeOutputTokens);
        }

        // 스티키 진행률 바 업데이트
        UpdateAgentProgressBar(evt);

        // 계획 뷰어 단계 갱신
        if (evt.StepCurrent > 0 && evt.StepTotal > 0)
            UpdatePlanViewerStep(evt);
        if (evt.Type == AgentEventType.Complete)
            CompletePlanViewer();

        // 파일 탐색기 자동 새로고침
        if (evt.Success && !string.IsNullOrEmpty(evt.FilePath))
            RefreshFileTreeIfVisible();

        // suggest_actions 도구 결과 → 후속 작업 칩 표시
        if (evt.Type == AgentEventType.ToolResult && evt.ToolName == "suggest_actions" && evt.Success)
            RenderSuggestActionChips(evt.Summary);

        // 파일 생성/수정 결과가 있으면 미리보기 자동 표시 또는 갱신
        if (evt.Success && !string.IsNullOrEmpty(evt.FilePath) &&
            (evt.Type == AgentEventType.ToolResult || evt.Type == AgentEventType.Complete) &&
            WriteToolNames.Contains(evt.ToolName))
        {
            var autoPreview = Llm.AutoPreview;
            if (autoPreview == "auto")
            {
                // 별도 창 미리보기: 이미 열린 파일이면 새로고침, 아니면 새 탭 추가
                if (PreviewWindow.IsOpen)
                    PreviewWindow.RefreshIfOpen(evt.FilePath);
                else
                    TryShowPreview(evt.FilePath);

                // 새 파일이면 항상 표시
                if (!PreviewWindow.IsOpen)
                    TryShowPreview(evt.FilePath);
            }
        }
    }
}
