namespace AxCopilot.Services.Agent;

/// <summary>
/// 사용 가능한 에이전트 도구/스킬을 관리하는 레지스트리.
/// 도구 목록을 LLM function calling에 전달하고, 이름으로 도구를 찾습니다.
/// </summary>
public class ToolRegistry : IDisposable
{
    private readonly Dictionary<string, IAgentTool> _tools = new(StringComparer.OrdinalIgnoreCase);

    /// <summary>등록된 모든 도구 목록.</summary>
    public IReadOnlyCollection<IAgentTool> All => _tools.Values;

    /// <summary>Phase 18-A: 백그라운드 에이전트 서비스 (AgentCompleted 이벤트 구독용).</summary>
    public BackgroundAgentService? BackgroundAgentService { get; private set; }

    /// <summary>도구를 이름으로 찾습니다.</summary>
    public IAgentTool? Get(string name) =>
        _tools.TryGetValue(name, out var tool) ? tool : null;

    /// <summary>도구를 등록합니다.</summary>
    public void Register(IAgentTool tool) => _tools[tool.Name] = tool;

    /// <summary>비활성 도구를 제외한 활성 도구 목록을 반환합니다.</summary>
    public IReadOnlyCollection<IAgentTool> GetActiveTools(IEnumerable<string>? disabledNames = null)
    {
        if (disabledNames == null) return All;
        var disabled = new HashSet<string>(disabledNames, StringComparer.OrdinalIgnoreCase);
        if (disabled.Count == 0) return All;
        return _tools.Values.Where(t => !disabled.Contains(t.Name)).ToList().AsReadOnly();
    }

    /// <summary>
    /// Phase 23: 비활성 도구 + IConditionalTool 자가 판단을 모두 적용한 활성 도구 목록.
    /// </summary>
    public IReadOnlyCollection<IAgentTool> GetActiveTools(
        IEnumerable<string>? disabledNames,
        ToolEnvironmentContext env)
    {
        var disabled = disabledNames != null
            ? new HashSet<string>(disabledNames, StringComparer.OrdinalIgnoreCase)
            : new HashSet<string>(StringComparer.OrdinalIgnoreCase);

        return _tools.Values
            .Where(t => !disabled.Contains(t.Name))
            .Where(t => t is not IConditionalTool cond || cond.IsEnabled(env))
            .ToList()
            .AsReadOnly();
    }

    /// <summary>IDisposable 도구를 모두 해제합니다.</summary>
    public void Dispose()
    {
        foreach (var tool in _tools.Values)
        {
            if (tool is IDisposable disposable)
                disposable.Dispose();
        }
        _tools.Clear();
    }

    /// <summary>기본 도구 + 내장 스킬을 모두 등록한 레지스트리를 생성합니다.</summary>
    public static ToolRegistry CreateDefault()
    {
        var registry = new ToolRegistry();

        // 기본 도구 (파일/검색/프로세스)
        registry.Register(new FileReadTool());
        registry.Register(new FileWriteTool());
        registry.Register(new FileEditTool());
        registry.Register(new GlobTool());
        registry.Register(new GrepTool());
        registry.Register(new ProcessTool());
        registry.Register(new FolderMapTool());
        registry.Register(new DocumentReaderTool());

        // 내장 스킬 (문서 생성)
        registry.Register(new ExcelSkill());
        registry.Register(new DocxSkill());
        registry.Register(new CsvSkill());
        registry.Register(new MarkdownSkill());
        registry.Register(new HtmlSkill());
        registry.Register(new ChartSkill());
        registry.Register(new BatchSkill());
        registry.Register(new PptxSkill());

        // 멀티패스 문서 엔진
        registry.Register(new DocumentPlannerTool());
        registry.Register(new DocumentAssemblerTool());

        // 문서 품질 검증 & 포맷 변환
        registry.Register(new DocumentReviewTool());
        registry.Register(new FormatConvertTool());

        // Code 탭: 개발 환경 감지 & 빌드/테스트 & Git
        registry.Register(new DevEnvDetectTool());
        registry.Register(new BuildRunTool());
        registry.Register(new GitTool());
        registry.Register(new LspTool());
        registry.Register(new SubAgentTool());
        registry.Register(new WaitAgentsTool());
        registry.Register(new CodeSearchTool());
        registry.Register(new TestLoopTool());

        // 코드 리뷰 + 프로젝트 규칙
        registry.Register(new CodeReviewTool());
        registry.Register(new ProjectRuleTool());

        // 스킬 시스템
        registry.Register(new SkillManagerTool());

        // 에이전트 메모리
        registry.Register(new MemoryTool());

        // 데이터 처리 + 시스템 유틸리티
        registry.Register(new JsonTool());
        registry.Register(new RegexTool());
        registry.Register(new DiffTool());
        registry.Register(new ClipboardTool());
        registry.Register(new NotifyTool());
        registry.Register(new EnvTool());
        registry.Register(new ZipTool());
        registry.Register(new HttpTool());
        registry.Register(new SqlTool());
        registry.Register(new Base64Tool());
        registry.Register(new HashTool());
        registry.Register(new DateTimeTool());

        // 코드 품질
        registry.Register(new SnippetRunnerTool());

        // 데이터 분석 + 문서 자동화
        registry.Register(new DataPivotTool());
        registry.Register(new TemplateRenderTool());
        registry.Register(new TextSummarizeTool());

        // 파일 모니터링 + 이미지 분석
        registry.Register(new FileWatchTool());
        registry.Register(new ImageAnalyzeTool());

        // 파일 관리 + 메타데이터 + 멀티리드
        registry.Register(new FileManageTool());
        registry.Register(new FileInfoTool());
        registry.Register(new MultiReadTool());

        // 사용자 질문
        registry.Register(new UserAskTool());

        // 외부 열기 + 수학 + XML + 인코딩
        registry.Register(new OpenExternalTool());
        registry.Register(new MathTool());
        registry.Register(new XmlTool());
        registry.Register(new EncodingTool());

        // 태스크 추적
        registry.Register(new TaskTrackerTool());

        // 워크플로우 도구
        registry.Register(new SuggestActionsTool());
        registry.Register(new DiffPreviewTool());
        registry.Register(new CheckpointTool());
        registry.Register(new PlaybookTool());

        // Phase 18-A: 위임 에이전트 (멀티에이전트 오케스트레이션)
        var memoryRepo = new AgentTypeMemoryRepository();
        var bgService = new BackgroundAgentService(memoryRepo);
        var worktreeMgr = new WorktreeManager();   // Phase 18-A2: worktree 격리
        registry.BackgroundAgentService = bgService;  // ChatWindow에서 AgentCompleted 구독
        registry.Register(new DelegateAgentTool(bgService, memoryRepo, worktreeMgr));

        return registry;
    }
}
