# Manager Utils
# 헬퍼 함수들

import re
from typing import Dict, Any, List, Set

from .data import MANAGERS, CONTEXT_GROUPS, PHASE_ORDER


def _topological_sort(action_items: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
    """의존성 기반으로 액션 아이템을 위상 정렬합니다."""
    if not action_items:
        return []

    id_to_item = {item["id"]: item for item in action_items}
    in_degree = {item["id"]: 0 for item in action_items}

    for item in action_items:
        for dep in item.get("depends", []):
            if dep in in_degree:
                in_degree[item["id"]] += 1

    queue = [item_id for item_id, degree in in_degree.items() if degree == 0]
    result = []

    while queue:
        queue.sort(key=lambda x: (
            PHASE_ORDER.get(id_to_item[x].get("phase", "검증"), 5),
            x
        ))

        current_id = queue.pop(0)
        result.append(id_to_item[current_id])

        for item in action_items:
            if current_id in item.get("depends", []):
                in_degree[item["id"]] -= 1
                if in_degree[item["id"]] == 0:
                    queue.append(item["id"])

    remaining = [item for item in action_items if item not in result]
    remaining.sort(key=lambda x: PHASE_ORDER.get(x.get("phase", "검증"), 5))
    result.extend(remaining)

    return result


def _group_by_phase(action_items: List[Dict[str, Any]]) -> Dict[str, List[Dict[str, Any]]]:
    """액션 아이템을 Phase별로 그룹화합니다."""
    phases = {"준비": [], "설계": [], "구현": [], "검증": []}

    for item in action_items:
        phase = item.get("phase", "검증")
        if phase in phases:
            phases[phase].append(item)
        else:
            phases["검증"].append(item)

    return phases


def _analyze_context(context: str) -> List[str]:
    """컨텍스트에서 주요 토픽을 감지합니다."""
    context_lower = context.lower()
    detected = []

    topic_keywords = {
        "auth": ["login", "로그인", "auth", "인증", "session", "jwt", "token", "password", "비밀번호"],
        "payment": ["payment", "결제", "billing", "subscription", "구독", "price", "가격"],
        "api": ["api", "endpoint", "rest", "graphql", "request", "response"],
        "ui": ["ui", "component", "컴포넌트", "button", "input", "form", "style", "css"],
        "security": ["security", "보안", "encrypt", "암호화", "vulnerability", "취약점"],
        "performance": ["performance", "성능", "optimize", "최적화", "cache", "캐시"],
        "error": ["error", "에러", "exception", "예외", "bug", "버그", "fix"],
        "database": ["database", "db", "sql", "query", "migration", "schema"],
        "design": ["design", "디자인", "ux", "ui", "layout", "레이아웃"],
        "feature": ["feature", "기능", "implement", "구현", "add", "추가"],
        "launch": ["launch", "런칭", "deploy", "배포", "release", "릴리즈"]
    }

    for topic, keywords in topic_keywords.items():
        if any(kw in context_lower for kw in keywords):
            detected.append(topic)

    return detected if detected else ["feature"]


def _select_managers_by_context(context: str, detected_contexts: List[str]) -> List[str]:
    """컨텍스트에 맞는 매니저들을 선택합니다."""
    selected: Set[str] = set()

    for ctx in detected_contexts:
        if ctx in CONTEXT_GROUPS:
            selected.update(CONTEXT_GROUPS[ctx])

    context_lower = context.lower()
    for manager_key, manager_info in MANAGERS.items():
        for keyword in manager_info["keywords"]:
            if keyword in context_lower:
                selected.add(manager_key)
                break

    selected.add("PM")
    selected.add("CTO")

    priority_order = ["PM", "CTO", "QA", "CSO", "CDO", "CMO", "CFO", "ERROR"]
    return [m for m in priority_order if m in selected]


def _extract_feature_name(context: str) -> str:
    """컨텍스트에서 기능/작업명을 추출합니다."""
    patterns = [
        r'([\w가-힣]+)\s*(기능|페이지|화면|API|시스템)',
        r'(로그인|회원가입|결제|인증|대시보드|설정)',
        r'([\w가-힣]+)\s*(만들|구현|추가|수정)',
    ]

    for pattern in patterns:
        match = re.search(pattern, context)
        if match:
            return match.group(1)

    return context[:20].strip() if len(context) > 20 else context


def _check_pattern(pattern: str, context: str) -> bool:
    """특정 패턴이 컨텍스트에 있는지 체크합니다."""
    pattern_checks = {
        "하드코딩된 시크릿": r'["\'](?:sk_|api_key|secret|password)["\']?\s*[:=]\s*["\'][^"\']+["\']',
        "평문 비밀번호": r'password\s*[:=]\s*["\'][^"\']+["\']',
        "SQL 문자열 연결": r'(?:SELECT|INSERT|UPDATE|DELETE).*\+.*(?:str\(|f"|\')',
        "innerHTML 직접 할당": r'innerHTML\s*=',
    }

    regex = pattern_checks.get(pattern)
    if regex:
        return bool(re.search(regex, context, re.IGNORECASE))
    return False


def _generate_action_items(context: str, active_managers: List[str]) -> List[Dict[str, Any]]:
    """컨텍스트 기반으로 모든 활성 매니저의 액션 아이템을 생성합니다."""
    context_lower = context.lower()
    action_items = []

    for manager_key in active_managers:
        manager_info = MANAGERS.get(manager_key, {})
        templates = manager_info.get("action_templates", [])

        for template in templates:
            trigger = template.get("trigger", "")
            trigger_patterns = trigger.split("|")

            if any(pattern.lower() in context_lower for pattern in trigger_patterns):
                for action in template.get("actions", []):
                    action_item = {
                        **action,
                        "manager": manager_key,
                        "emoji": manager_info.get("emoji", "")
                    }
                    if not any(a["id"] == action_item["id"] for a in action_items):
                        action_items.append(action_item)

    return _topological_sort(action_items)


def _generate_recommendations(result: Dict) -> List[str]:
    """종합 추천 사항을 생성합니다."""
    recommendations = []

    if result["warnings"]:
        recommendations.append("🚨 보안 경고를 먼저 해결하세요")

    active_count = len(result["active_managers"])
    if active_count >= 5:
        recommendations.append("📋 복잡한 작업입니다. 단계별로 진행하세요")

    managers = result["active_managers"]
    if "CSO" in managers and "CTO" in managers:
        recommendations.append("🔐 보안 리뷰를 코드 리뷰와 함께 진행하세요")

    if "CFO" in managers:
        recommendations.append("💰 비용 영향을 문서화하세요")

    if "ERROR" in managers:
        recommendations.append("📝 에러 처리 로직과 복구 전략을 명시하세요")

    return recommendations


def list_managers() -> List[Dict[str, str]]:
    """사용 가능한 매니저 목록을 반환합니다."""
    return [
        {
            "key": key,
            "emoji": info["emoji"],
            "title": info["title"],
            "focus": ", ".join(info["focus"][:3])
        }
        for key, info in MANAGERS.items()
    ]
