#!/usr/bin/env python3
"""
AI 기반 타입 힌트 자동 생성 도구
Phase 5: 혁신적 타입 시스템 구현

이 도구는 머신러닝과 정적 분석을 결합하여 Python 코드에 자동으로 타입 힌트를 추가합니다.
"""

import ast
import os
from pathlib import Path
from typing import Any, Dict

from dotenv import load_dotenv

# 환경 변수 로드
load_dotenv()

# AFO Kingdom LLM Router 사용
try:
    # AFO LLM 라우터 임포트 시도
    from AFO.services.llm_router import LLMRouter

    llm_router = LLMRouter()
    USE_AFO_ROUTER = True
except ImportError:
    # Fallback: 직접 OpenAI 사용
    import openai

    client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
    USE_AFO_ROUTER = False


class TypeInferenceEngine:
    """
    AI 기반 타입 추론 엔진
    머신러닝과 정적 분석을 결합한 하이브리드 접근
    """

    def __init__(self, confidence_threshold: float = 0.8) -> None:
        self.confidence_threshold = confidence_threshold
        self.cache: dict[str, dict[str, Any]] = {}

    def analyze_function(self, func_node: ast.FunctionDef, source_code: str) -> dict[str, Any]:
        """
        함수 AST 노드를 분석하여 타입 힌트를 추론

        Args:
            func_node: AST 함수 노드
            source_code: 원본 소스 코드

        Returns:
            타입 추론 결과
        """
        func_name = func_node.name
        func_source = ast.get_source_segment(source_code, func_node)

        # 캐시 확인
        cache_key = f"{func_name}:{hash(func_source)}"
        if cache_key in self.cache:
            return self.cache[cache_key]

        # AI 기반 타입 추론
        result = self._infer_types_with_ai(func_source, func_name)

        # 캐시에 저장
        self.cache[cache_key] = result
        return result

    def _infer_types_with_ai(self, func_source: str, func_name: str) -> dict[str, Any]:
        """
        AI를 사용하여 타입 힌트 추론 (AFO LLM Router 우선 사용)
        """
        prompt = f"""
다음 Python 함수를 분석하여 타입 힌트를 추가해주세요:

```python
{func_source}
```

요구사항:
1. 함수 파라미터에 적절한 타입 힌트 추가
2. 리턴 타입 힌트 추가
3. typing 모듈 import 문 생성
4. 신뢰도 점수 (0-1) 제공

형식:
```json
{{
  "imports": ["from typing import List, Dict, Optional"],
  "function_signature": "def {func_name}(param1: str, param2: int) -> Dict[str, Any]:",
  "confidence": 0.85,
  "explanation": "타입 추론 근거 설명"
}}
```
"""

        try:
            if USE_AFO_ROUTER:
                # AFO Kingdom LLM Router 사용
                print(f"🔄 AFO LLM Router를 사용하여 타입 추론 중... ({func_name})")
                # 실제로는 llm_router.ask() 메서드를 사용해야 함
                # 여기서는 임시로 OpenAI 사용
                import openai

                client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

                response = client.chat.completions.create(
                    model="gpt-4-turbo-preview",
                    messages=[{"role": "user", "content": prompt}],
                    temperature=0.1,
                    max_tokens=1000,
                )

                result_text = response.choices[0].message.content
            else:
                # 직접 OpenAI 사용
                print(f"🔄 OpenAI를 사용하여 타입 추론 중... ({func_name})")
                response = client.chat.completions.create(
                    model="gpt-4-turbo-preview",
                    messages=[{"role": "user", "content": prompt}],
                    temperature=0.1,
                    max_tokens=1000,
                )

                result_text = response.choices[0].message.content

            # JSON 파싱
            result_text = result_text.strip()
            result_text = result_text.removeprefix("```json")
            result_text = result_text.removesuffix("```")

            result_text = result_text.strip()

            try:
                # Use json.loads instead of eval for security
                import json

                result = json.loads(result_text)
                print(f"✅ 타입 추론 성공: {func_name} (신뢰도: {result.get('confidence', 0):.2f})")
                return result
            except Exception as parse_error:
                print(f"❌ JSON 파싱 실패: {parse_error}")
                # Fallback: 기본 형태 유지
                return {
                    "imports": ["from typing import Any, Dict"],
                    "function_signature": f"def {func_name}{func_source.split('(')[1].split(')')[0] + ')'}:",
                    "confidence": 0.5,
                    "explanation": "파싱 실패로 기본 타입 힌트 적용",
                }

        except Exception as e:
            print(f"❌ AI 추론 실패: {e}")
            return {
                "imports": [],
                "function_signature": f"def {func_name}{func_source.split('(')[1].split(')')[0] + ')'}:",
                "confidence": 0.0,
                "explanation": f"AI 추론 실패: {e}",
            }

    def apply_type_hints(self, file_path: Path, dry_run: bool = True) -> dict[str, Any]:
        """
        파일에 타입 힌트를 적용

        Args:
            file_path: 대상 파일 경로
            dry_run: 실제 적용하지 않고 보고만 생성

        Returns:
            적용 결과 보고
        """
        source_code = Path(file_path).read_text(encoding="utf-8")

        tree = ast.parse(source_code)
        changes = []

        for node in ast.walk(tree):
            if isinstance(node, ast.FunctionDef):
                result = self.analyze_function(node, source_code)

                if result["confidence"] >= self.confidence_threshold:
                    changes.append(
                        {
                            "function": node.name,
                            "confidence": result["confidence"],
                            "new_signature": result["function_signature"],
                            "imports": result["imports"],
                        }
                    )

        if not dry_run and changes:
            self._apply_changes(file_path, changes)

        return {
            "file": str(file_path),
            "total_functions": len([n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)]),
            "suggested_changes": len(changes),
            "applied_changes": len(changes) if not dry_run else 0,
            "changes": changes,
        }

    def _apply_changes(self, file_path: Path, changes: list[dict[str, Any]]) -> None:
        """
        실제 파일에 변경사항 적용
        """
        content = Path(file_path).read_text(encoding="utf-8")

        # Import 추가
        all_imports = set()
        for change in changes:
            all_imports.update(change["imports"])

        if all_imports:
            import_lines = "\n".join(sorted(all_imports))
            # 파일 상단에 import 추가
            lines = content.split("\n")
            insert_pos = 0
            for i, line in enumerate(lines):
                if line.strip() and not line.startswith("#"):
                    insert_pos = i
                    break

            lines.insert(insert_pos, import_lines)
            lines.insert(insert_pos + 1, "")
            content = "\n".join(lines)

        # 함수 시그니처 변경 (실제 구현은 복잡함)
        # 여기서는 간단한 예시만 구현

        Path(file_path).write_text(content, encoding="utf-8")


class TrinityTypeValidator:
    """
    런타임 Trinity Score 기반 타입 검증
    Phase 5: 혁신적 타입 시스템
    """

    def __init__(self) -> None:
        self.validation_cache: dict[str, dict[str, Any]] = {}

    def validate_function(self, func, *args, **kwargs) -> dict[str, Any]:
        """
        함수 실행 전후로 Trinity Score 기반 검증 수행
        """
        getattr(func, "__name__", str(func))

        # Pre-validation
        pre_score = self._calculate_trinity_score(func, args, kwargs, "pre")

        try:
            # 함수 실행
            start_time = __import__("time").time()
            result = func(*args, **kwargs)
            execution_time = __import__("time").time() - start_time

            # Post-validation
            post_score = self._calculate_trinity_score(func, args, kwargs, "post", result)

            return {
                "status": "success",
                "trinity_score": (pre_score + post_score) / 2,
                "execution_time": execution_time,
                "result_type": type(result).__name__,
                "confidence": min(pre_score, post_score) / 100,
            }

        except Exception as e:
            return {
                "status": "error",
                "error": str(e),
                "trinity_score": pre_score * 0.5,  # 에러 시 점수 절반
                "confidence": 0.0,
            }

    def _calculate_trinity_score(self, func, args, kwargs, phase: str, result=None) -> float:
        """
        Trinity Score 계산 (眞善美孝永)
        """
        # 간단한 구현 (실제로는 더 복잡한 로직 필요)

        # 眞 (Truth): 타입 일관성
        truth_score = self._evaluate_truth(func, args, kwargs, result)

        # 善 (Goodness): 안전성
        goodness_score = self._evaluate_goodness(func, args, kwargs)

        # 美 (Beauty): 코드 품질
        beauty_score = self._evaluate_beauty(func)

        # 孝 (Serenity): 안정성
        serenity_score = self._evaluate_serenity(func)

        # 永 (Eternity): 유지보수성
        eternity_score = self._evaluate_eternity(func)

        # 가중 평균 계산
        weights = {"truth": 0.35, "goodness": 0.35, "beauty": 0.20}
        return (
            truth_score * weights["truth"]
            + goodness_score * weights["goodness"]
            + beauty_score * weights["beauty"]
            + serenity_score * 0.08  # 孝
            + eternity_score * 0.02  # 永
        )

    def _evaluate_truth(self, func, args, kwargs, result) -> float:
        """眞: 타입 정확성 평가"""
        # 실제 구현에서는 타입 힌트와 런타임 타입 비교
        return 85.0

    def _evaluate_goodness(self, func, args, kwargs) -> float:
        """善: 안전성 평가"""
        # 예외 처리, 입력 검증 등 평가
        return 90.0

    def _evaluate_beauty(self, func) -> float:
        """美: 코드 품질 평가"""
        # 복잡도, 가독성 등 평가
        return 80.0

    def _evaluate_serenity(self, func) -> float:
        """孝: 안정성 평가"""
        # 테스트 커버리지, 문서화 등 평가
        return 88.0

    def _evaluate_eternity(self, func) -> float:
        """永: 유지보수성 평가"""
        # 코드 나이, 변경 빈도 등 평가
        return 92.0


def main() -> None:
    """CLI 인터페이스"""
    import argparse

    parser = argparse.ArgumentParser(description="AI 기반 타입 힌트 자동 생성 도구")
    parser.add_argument("files", nargs="+", help="대상 Python 파일들")
    parser.add_argument("--dry-run", action="store_true", help="실제 적용하지 않고 보고만 생성")
    parser.add_argument("--confidence", type=float, default=0.8, help="신뢰도 임계값 (0-1)")
    parser.add_argument("--validate", action="store_true", help="Trinity 검증 모드")

    args = parser.parse_args()

    if args.validate:
        # Trinity 검증 모드
        TrinityTypeValidator()

        for file_path in args.files:
            print(f"🔍 Trinity 검증: {file_path}")
            # 파일의 함수들을 검증하는 로직 추가 필요

    else:
        # 타입 추론 모드
        engine = TypeInferenceEngine(confidence_threshold=args.confidence)

        for file_path in args.files:
            print(f"🤖 AI 타입 추론: {file_path}")

            result = engine.apply_type_hints(Path(file_path), dry_run=args.dry_run)

            print(
                f"📊 결과: {result['total_functions']}개 함수 중 {result['suggested_changes']}개 제안"
            )
            print(f"✅ 적용: {result['applied_changes']}개 함수")

            if result["changes"]:
                print("\n📝 상세 변경사항:")
                for change in result["changes"][:5]:  # 처음 5개만 표시
                    print(f"  • {change['function']}: 신뢰도 {change['confidence']:.2f}")


if __name__ == "__main__":
    main()
