# -*- coding: utf-8 -*-
"""
Clouvel MCP Server v1.1.0
바이브코딩 프로세스를 강제하는 MCP 서버

v1.1.0: Clouvel Pro (Shovel 통합)
"""

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent

from .analytics import log_tool_call, get_stats, format_stats
from .tools import (
    # core
    can_code, scan_docs, analyze_docs, init_docs, REQUIRED_DOCS,
    # docs
    get_prd_template, write_prd_section, get_prd_guide, get_verify_checklist, get_setup_guide,
    # setup
    init_clouvel, setup_cli,
    # rules (v0.5)
    init_rules, get_rule, add_rule,
    # verify (v0.5)
    verify, gate, handoff,
    # planning (v0.6)
    init_planning, save_finding, refresh_goals, update_progress,
    # agents (v0.7)
    spawn_explore, spawn_librarian,
    # hooks (v0.8)
    hook_design, hook_verify,
    # pro (v1.1)
    install_shovel, sync_commands, activate_license,
)

server = Server("clouvel")


# ============================================================
# Tool Definitions
# ============================================================

TOOL_DEFINITIONS = [
    # === Core Tools ===
    Tool(
        name="can_code",
        description="코드 작성 전 반드시 호출. 문서 상태 확인 후 코딩 가능 여부 판단.",
        inputSchema={
            "type": "object",
            "properties": {"path": {"type": "string", "description": "프로젝트 docs 폴더 경로"}},
            "required": ["path"]
        }
    ),
    Tool(
        name="scan_docs",
        description="프로젝트 docs 폴더 스캔. 파일 목록 반환.",
        inputSchema={
            "type": "object",
            "properties": {"path": {"type": "string", "description": "docs 폴더 경로"}},
            "required": ["path"]
        }
    ),
    Tool(
        name="analyze_docs",
        description="docs 폴더 분석. 필수 문서 체크.",
        inputSchema={
            "type": "object",
            "properties": {"path": {"type": "string", "description": "docs 폴더 경로"}},
            "required": ["path"]
        }
    ),
    Tool(
        name="init_docs",
        description="docs 폴더 초기화 + 템플릿 생성.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "project_name": {"type": "string", "description": "프로젝트 이름"}
            },
            "required": ["path", "project_name"]
        }
    ),

    # === Docs Tools ===
    Tool(
        name="get_prd_template",
        description="PRD 템플릿 생성.",
        inputSchema={
            "type": "object",
            "properties": {
                "project_name": {"type": "string", "description": "프로젝트 이름"},
                "output_path": {"type": "string", "description": "출력 경로"}
            },
            "required": ["project_name", "output_path"]
        }
    ),
    Tool(
        name="write_prd_section",
        description="PRD 섹션별 작성 가이드.",
        inputSchema={
            "type": "object",
            "properties": {
                "section": {"type": "string", "enum": ["summary", "principles", "input_spec", "output_spec", "errors", "state_machine", "api_endpoints", "db_schema"]},
                "content": {"type": "string", "description": "섹션 내용"}
            },
            "required": ["section"]
        }
    ),
    Tool(name="get_prd_guide", description="PRD 작성 가이드.", inputSchema={"type": "object", "properties": {}}),
    Tool(name="get_verify_checklist", description="검증 체크리스트.", inputSchema={"type": "object", "properties": {}}),
    Tool(
        name="get_setup_guide",
        description="설치/설정 가이드.",
        inputSchema={
            "type": "object",
            "properties": {"platform": {"type": "string", "enum": ["desktop", "code", "vscode", "cursor", "all"]}}
        }
    ),
    Tool(
        name="get_analytics",
        description="도구 사용량 통계.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 경로"},
                "days": {"type": "integer", "description": "조회 기간 (기본: 30일)"}
            }
        }
    ),

    # === Setup Tools ===
    Tool(
        name="init_clouvel",
        description="Clouvel 온보딩. 플랫폼 선택 후 맞춤 설정.",
        inputSchema={
            "type": "object",
            "properties": {"platform": {"type": "string", "enum": ["desktop", "vscode", "cli", "ask"]}}
        }
    ),
    Tool(
        name="setup_cli",
        description="CLI 환경 설정. hooks, CLAUDE.md, pre-commit 생성.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "level": {"type": "string", "enum": ["remind", "strict", "full"]}
            },
            "required": ["path"]
        }
    ),

    # === Rules Tools (v0.5) ===
    Tool(
        name="init_rules",
        description="v0.5: 규칙 모듈화 초기화.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "template": {"type": "string", "enum": ["web", "api", "fullstack", "minimal"]}
            },
            "required": ["path"]
        }
    ),
    Tool(
        name="get_rule",
        description="v0.5: 경로 기반 규칙 로딩.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "파일 경로"},
                "context": {"type": "string", "enum": ["coding", "review", "debug", "test"]}
            },
            "required": ["path"]
        }
    ),
    Tool(
        name="add_rule",
        description="v0.5: 새 규칙 추가.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "rule_type": {"type": "string", "enum": ["never", "always", "prefer"]},
                "content": {"type": "string", "description": "규칙 내용"},
                "category": {"type": "string", "enum": ["api", "frontend", "database", "security", "general"]}
            },
            "required": ["path", "rule_type", "content"]
        }
    ),

    # === Verify Tools (v0.5) ===
    Tool(
        name="verify",
        description="v0.5: Context Bias 제거 검증.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "검증 대상 경로"},
                "scope": {"type": "string", "enum": ["file", "feature", "full"]},
                "checklist": {"type": "array", "items": {"type": "string"}}
            },
            "required": ["path"]
        }
    ),
    Tool(
        name="gate",
        description="v0.5: lint → test → build 자동화.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "steps": {"type": "array", "items": {"type": "string"}},
                "fix": {"type": "boolean"}
            },
            "required": ["path"]
        }
    ),
    Tool(
        name="handoff",
        description="v0.5: 의도 기록.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "feature": {"type": "string", "description": "완료한 기능"},
                "decisions": {"type": "string"},
                "warnings": {"type": "string"},
                "next_steps": {"type": "string"}
            },
            "required": ["path", "feature"]
        }
    ),

    # === Planning Tools (v0.6) ===
    Tool(
        name="init_planning",
        description="v0.6: 영속적 컨텍스트 초기화.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "task": {"type": "string", "description": "현재 작업"},
                "goals": {"type": "array", "items": {"type": "string"}}
            },
            "required": ["path", "task"]
        }
    ),
    Tool(
        name="save_finding",
        description="v0.6: 조사 결과 저장.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "topic": {"type": "string"},
                "question": {"type": "string"},
                "findings": {"type": "string"},
                "source": {"type": "string"},
                "conclusion": {"type": "string"}
            },
            "required": ["path", "topic", "findings"]
        }
    ),
    Tool(
        name="refresh_goals",
        description="v0.6: 목표 리마인드.",
        inputSchema={
            "type": "object",
            "properties": {"path": {"type": "string", "description": "프로젝트 루트 경로"}},
            "required": ["path"]
        }
    ),
    Tool(
        name="update_progress",
        description="v0.6: 진행 상황 업데이트.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "completed": {"type": "array", "items": {"type": "string"}},
                "in_progress": {"type": "string"},
                "blockers": {"type": "array", "items": {"type": "string"}},
                "next": {"type": "string"}
            },
            "required": ["path"]
        }
    ),

    # === Agent Tools (v0.7) ===
    Tool(
        name="spawn_explore",
        description="v0.7: 탐색 전문 에이전트.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "query": {"type": "string", "description": "탐색 질문"},
                "scope": {"type": "string", "enum": ["file", "folder", "project", "deep"]},
                "save_findings": {"type": "boolean"}
            },
            "required": ["path", "query"]
        }
    ),
    Tool(
        name="spawn_librarian",
        description="v0.7: 라이브러리언 에이전트.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "topic": {"type": "string", "description": "조사 주제"},
                "type": {"type": "string", "enum": ["library", "api", "migration", "best_practice"]},
                "depth": {"type": "string", "enum": ["quick", "standard", "thorough"]}
            },
            "required": ["path", "topic"]
        }
    ),

    # === Hook Tools (v0.8) ===
    Tool(
        name="hook_design",
        description="v0.8: 설계 훅 생성.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "trigger": {"type": "string", "enum": ["pre_code", "pre_feature", "pre_refactor", "pre_api"]},
                "checks": {"type": "array", "items": {"type": "string"}},
                "block_on_fail": {"type": "boolean"}
            },
            "required": ["path", "trigger"]
        }
    ),
    Tool(
        name="hook_verify",
        description="v0.8: 검증 훅 생성.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "trigger": {"type": "string", "enum": ["post_code", "post_feature", "pre_commit", "pre_push"]},
                "steps": {"type": "array", "items": {"type": "string"}},
                "parallel": {"type": "boolean"},
                "continue_on_error": {"type": "boolean"}
            },
            "required": ["path", "trigger"]
        }
    ),

    # === Pro Tools (v1.1) ===
    Tool(
        name="install_shovel",
        description="v1.1 Pro: Shovel .claude/ 구조 자동 설치. 라이선스 필요.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "project_type": {"type": "string", "enum": ["web", "api", "desktop", "fullstack"]},
                "license_key": {"type": "string", "description": "라이선스 키 (선택)"}
            },
            "required": ["path"]
        }
    ),
    Tool(
        name="sync_commands",
        description="v1.1 Pro: Clouvel MCP와 Shovel 커맨드 통합.",
        inputSchema={
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "프로젝트 루트 경로"},
                "mode": {"type": "string", "enum": ["merge", "overwrite", "skip"]}
            },
            "required": ["path"]
        }
    ),
    Tool(
        name="activate_license",
        description="v1.1 Pro: 라이선스 활성화.",
        inputSchema={
            "type": "object",
            "properties": {
                "license_key": {"type": "string", "description": "라이선스 키"}
            },
            "required": ["license_key"]
        }
    ),
]


@server.list_tools()
async def list_tools() -> list[Tool]:
    return TOOL_DEFINITIONS


# ============================================================
# Tool Handlers
# ============================================================

TOOL_HANDLERS = {
    # Core
    "can_code": lambda args: can_code(args.get("path", "")),
    "scan_docs": lambda args: scan_docs(args.get("path", "")),
    "analyze_docs": lambda args: analyze_docs(args.get("path", "")),
    "init_docs": lambda args: init_docs(args.get("path", ""), args.get("project_name", "")),

    # Docs
    "get_prd_template": lambda args: get_prd_template(args.get("project_name", ""), args.get("output_path", "")),
    "write_prd_section": lambda args: write_prd_section(args.get("section", ""), args.get("content", "")),
    "get_prd_guide": lambda args: get_prd_guide(),
    "get_verify_checklist": lambda args: get_verify_checklist(),
    "get_setup_guide": lambda args: get_setup_guide(args.get("platform", "all")),

    # Setup
    "init_clouvel": lambda args: init_clouvel(args.get("platform", "ask")),
    "setup_cli": lambda args: setup_cli(args.get("path", ""), args.get("level", "remind")),

    # Rules (v0.5)
    "init_rules": lambda args: init_rules(args.get("path", ""), args.get("template", "minimal")),
    "get_rule": lambda args: get_rule(args.get("path", ""), args.get("context", "coding")),
    "add_rule": lambda args: add_rule(args.get("path", ""), args.get("rule_type", "always"), args.get("content", ""), args.get("category", "general")),

    # Verify (v0.5)
    "verify": lambda args: verify(args.get("path", ""), args.get("scope", "file"), args.get("checklist", [])),
    "gate": lambda args: gate(args.get("path", ""), args.get("steps", ["lint", "test", "build"]), args.get("fix", False)),
    "handoff": lambda args: handoff(args.get("path", ""), args.get("feature", ""), args.get("decisions", ""), args.get("warnings", ""), args.get("next_steps", "")),

    # Planning (v0.6)
    "init_planning": lambda args: init_planning(args.get("path", ""), args.get("task", ""), args.get("goals", [])),
    "save_finding": lambda args: save_finding(args.get("path", ""), args.get("topic", ""), args.get("question", ""), args.get("findings", ""), args.get("source", ""), args.get("conclusion", "")),
    "refresh_goals": lambda args: refresh_goals(args.get("path", "")),
    "update_progress": lambda args: update_progress(args.get("path", ""), args.get("completed", []), args.get("in_progress", ""), args.get("blockers", []), args.get("next", "")),

    # Agents (v0.7)
    "spawn_explore": lambda args: spawn_explore(args.get("path", ""), args.get("query", ""), args.get("scope", "project"), args.get("save_findings", True)),
    "spawn_librarian": lambda args: spawn_librarian(args.get("path", ""), args.get("topic", ""), args.get("type", "library"), args.get("depth", "standard")),

    # Hooks (v0.8)
    "hook_design": lambda args: hook_design(args.get("path", ""), args.get("trigger", "pre_code"), args.get("checks", []), args.get("block_on_fail", True)),
    "hook_verify": lambda args: hook_verify(args.get("path", ""), args.get("trigger", "post_code"), args.get("steps", ["lint", "test", "build"]), args.get("parallel", False), args.get("continue_on_error", False)),

    # Pro (v1.1)
    "install_shovel": lambda args: install_shovel(args.get("path", ""), args.get("project_type", "web"), args.get("license_key", None)),
    "sync_commands": lambda args: sync_commands(args.get("path", ""), args.get("mode", "merge")),
    "activate_license": lambda args: activate_license(args.get("license_key", "")),
}


@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    # Analytics 기록
    project_path = arguments.get("path", None)
    if name != "get_analytics":
        try:
            log_tool_call(name, success=True, project_path=project_path)
        except Exception:
            pass

    # get_analytics 특별 처리
    if name == "get_analytics":
        return await _get_analytics(arguments.get("path", None), arguments.get("days", 30))

    # 핸들러 실행
    handler = TOOL_HANDLERS.get(name)
    if handler:
        return await handler(arguments)

    return [TextContent(type="text", text=f"Unknown tool: {name}")]


async def _get_analytics(path: str, days: int) -> list[TextContent]:
    """도구 사용량 통계"""
    stats = get_stats(days=days, project_path=path)
    return [TextContent(type="text", text=format_stats(stats))]


# ============================================================
# Server Entry Points
# ============================================================

async def run_server():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream, server.create_initialization_options())


def main():
    import sys
    import asyncio
    import argparse
    from pathlib import Path

    parser = argparse.ArgumentParser(description="Clouvel - 바이브코딩 프로세스 강제 도구")
    subparsers = parser.add_subparsers(dest="command")

    init_parser = subparsers.add_parser("init", help="프로젝트 초기화")
    init_parser.add_argument("-p", "--path", default=".", help="프로젝트 경로")
    init_parser.add_argument("-l", "--level", choices=["remind", "strict", "full"], default="strict")

    args = parser.parse_args()

    if args.command == "init":
        from .tools.setup import setup_cli as sync_setup
        import asyncio
        result = asyncio.run(sync_setup(args.path, args.level))
        print(result[0].text)
    else:
        asyncio.run(run_server())


if __name__ == "__main__":
    main()
