#!/usr/bin/env python3
"""
image-skill-router.py
이미지 작업 유형/키워드를 입력받아 최적 이미지 생성 스킬을 추천하는 CLI 도구.

Usage:
    python3 tools/image-skill-router.py --type "광고 배너"
    python3 tools/image-skill-router.py --type "카드뉴스" --json
    python3 tools/image-skill-router.py --type "SNS 메인 이미지" --urgent
    python3 tools/image-skill-router.py --type "인포그래픽" --count 15
"""

import argparse
import json
import sys


# ---------------------------------------------------------------------------
# 라우팅 테이블
# ---------------------------------------------------------------------------

# 각 항목: (키워드_리스트, 추천_스킬, 이유, 대안_리스트)
ROUTING_TABLE = [
    (
        ["광고 배너", "meta 배너", "google 배너", "광고 소재"],
        "hybrid-image",
        "사진 배경 + 정확한 한글 텍스트 필수",
        ["gemini-image"],
    ),
    (
        ["카드뉴스", "인포그래픽", "비교표", "표/차트", "데이터 차트"],
        "satori-cardnews",
        "텍스트 중심, 초고속, $0",
        ["hybrid-image"],
    ),
    (
        ["sns 메인 이미지", "sns 홍보 이미지", "sns 이미지", "포토리얼", "사진 이미지"],
        "gemini-image",
        "포토리얼, 텍스트 최소",
        ["hybrid-image"],
    ),
    (
        ["블로그 썸네일"],
        "hybrid-image",
        "사진 + 제목 텍스트",
        ["satori-cardnews"],
    ),
    (
        ["블로그 대표 이미지+포토", "블로그 대표 이미지"],
        "hybrid-image",
        "사진 + 제목 텍스트",
        ["satori-cardnews"],
    ),
    (
        ["a/b 테스트 변형", "대량 생성", "배치"],
        "satori-cardnews",
        "대량 빠른 생성",
        [],
    ),
    (
        ["프리미엄 브랜딩", "브랜드 이미지"],
        "gemini-image",
        "최고 품질 포토리얼",
        ["hybrid-image"],
    ),
    (
        ["블로그 텍스트 배너", "블로그 cta"],
        "satori-cardnews",
        "텍스트 중심",
        [],
    ),
    (
        ["google 정적 배너", "150kb"],
        "satori-cardnews",
        "벡터 기반 가벼운 파일 (150KB 제한 충족)",
        [],
    ),
    (
        ["네이버 gfa smart channel", "네이버 gfa smart", "gfa smart", "smart channel"],
        "satori-cardnews",
        "PNG+150KB 제한 충족",
        [],
    ),
    (
        ["네이버 gfa feed", "gfa feed"],
        "satori-cardnews",
        "텍스트 중심일 때 satori 추천 (포토리얼이면 hybrid 고려)",
        ["hybrid-image"],
    ),
    (
        ["카카오 비즈보드", "비즈보드"],
        "satori-cardnews",
        "극도로 좁은 비율 대응",
        [],
    ),
    (
        ["meta 캐러셀 텍스트", "캐러셀 텍스트"],
        "satori-cardnews",
        "텍스트 중심 캐러셀",
        [],
    ),
    (
        ["meta 캐러셀 포토", "캐러셀 포토", "meta 캐러셀"],
        "hybrid-image",
        "포토리얼 배경 필요",
        ["gemini-image"],
    ),
]

# 금지 규칙 경고: (스킬, 위험_키워드_리스트, 경고_메시지)
PROHIBITION_RULES = [
    (
        "satori-cardnews",
        ["포토리얼", "사진 이미지", "sns 메인 이미지", "프리미엄 브랜딩", "브랜드 이미지"],
        "satori-cardnews는 포토리얼 배경 생성을 지원하지 않습니다. 배경이 단색/그라데이션으로 제한됩니다.",
    ),
    (
        "gemini-image",
        ["카드뉴스", "인포그래픽", "비교표", "표/차트", "데이터 차트", "데이터 시각화", "정확한 텍스트"],
        "gemini-image는 데이터 시각화 및 정확한 텍스트 렌더링이 어렵습니다. 한글 텍스트 깨짐 위험이 있습니다.",
    ),
]


# ---------------------------------------------------------------------------
# 핵심 라우팅 함수
# ---------------------------------------------------------------------------

def route_skill(task_type: str, urgent: bool = False, count: int = 1) -> dict:
    """
    작업 유형 문자열을 입력받아 최적 스킬 추천 결과를 반환.

    Args:
        task_type: 이미지 작업 유형 (예: "광고 배너", "카드뉴스")
        urgent: 긴급 플래그. True 시 satori-cardnews 강제
        count: 생성 수량. 10 이상이면 satori-cardnews 강제

    Returns:
        {
            "recommended_skill": str,
            "reason": str,
            "alternatives": list[str],
            "warnings": list[str],
            "input_type": str,
        }
    """
    task_lower = task_type.lower().strip()
    warnings = []
    matched_skill = None
    matched_reason = None
    matched_alternatives = []

    # 키워드 매칭 (라우팅 테이블 순서대로 최초 매칭 우선)
    for keywords, skill, reason, alternatives in ROUTING_TABLE:
        for kw in keywords:
            if kw in task_lower:
                matched_skill = skill
                matched_reason = reason
                matched_alternatives = list(alternatives)
                break
        if matched_skill:
            break

    # 매칭 실패
    if not matched_skill:
        return {
            "recommended_skill": None,
            "reason": "키워드가 라우팅 테이블과 일치하지 않습니다.",
            "alternatives": ["hybrid-image", "satori-cardnews", "gemini-image"],
            "warnings": ["매칭 실패: 수동으로 스킬을 선택하거나 더 구체적인 키워드를 입력하세요."],
            "input_type": task_type,
        }

    # 금지 규칙 경고 체크
    for skill, danger_keywords, warning_msg in PROHIBITION_RULES:
        if matched_skill == skill:
            for dkw in danger_keywords:
                if dkw in task_lower:
                    warnings.append(f"[금지 규칙 경고] {warning_msg}")
                    break

    # 수량 강제 규칙 (count >= 10)
    if count >= 10:
        if matched_skill != "satori-cardnews":
            warnings.append(
                f"[SLA 보호] 수량 {count}개 >= 10개: satori-cardnews로 강제 전환합니다. "
                f"원래 추천: {matched_skill}"
            )
            if matched_skill not in matched_alternatives:
                matched_alternatives.insert(0, matched_skill)
            matched_skill = "satori-cardnews"
            matched_reason = f"대량 생성 ({count}개) - SLA 보호를 위한 강제 전환"

    # 긴급 플래그 강제 규칙 (urgent=True 시 마지막 적용)
    if urgent:
        if matched_skill != "satori-cardnews":
            warnings.append(
                f"[긴급 모드] --urgent 옵션 감지: satori-cardnews로 강제 전환합니다. "
                f"원래 추천: {matched_skill}"
            )
            if matched_skill not in matched_alternatives:
                matched_alternatives.insert(0, matched_skill)
            matched_skill = "satori-cardnews"
            matched_reason = "긴급 모드 강제 전환 (초고속 생성)"
        else:
            warnings.append("[긴급 모드] --urgent 옵션 감지: 이미 satori-cardnews가 추천됩니다.")

    return {
        "recommended_skill": matched_skill,
        "reason": matched_reason,
        "alternatives": matched_alternatives,
        "warnings": warnings,
        "input_type": task_type,
    }


# ---------------------------------------------------------------------------
# dispatch.py 연동용 함수
# ---------------------------------------------------------------------------

def get_skill_recommendation(task_desc: str) -> str:
    """
    작업 설명에서 키워드를 추출하여 추천 스킬 이름을 반환.
    dispatch.py에서 design 팀 위임 시 프롬프트에 포함할 용도.

    Args:
        task_desc: 자유 형식의 작업 설명 문자열

    Returns:
        추천 스킬 이름 (str). 매칭 실패 시 "hybrid-image" 반환 (안전 기본값).
    """
    result = route_skill(task_desc)
    recommended = result.get("recommended_skill")
    if recommended:
        return recommended
    # 매칭 실패 시 안전 기본값
    return "hybrid-image"


# ---------------------------------------------------------------------------
# CLI 출력 헬퍼
# ---------------------------------------------------------------------------

def print_human_readable(result: dict) -> None:
    """사람이 읽기 쉬운 형식으로 결과를 출력."""
    skill = result["recommended_skill"]
    if skill is None:
        print("❌ 매칭 실패: 라우팅 테이블에 해당 키워드가 없습니다.")
        print(f"   입력: {result['input_type']}")
    else:
        print(f"✅ 추천: {skill}")
        print(f"📝 이유: {result['reason']}")

    alternatives = result.get("alternatives", [])
    if alternatives:
        print(f"🔄 대안: {', '.join(alternatives)}")
    else:
        print("🔄 대안: 없음")

    warnings = result.get("warnings", [])
    if warnings:
        for w in warnings:
            print(f"⚠️  {w}")


# ---------------------------------------------------------------------------
# 메인 진입점
# ---------------------------------------------------------------------------

def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="image-skill-router",
        description="이미지 작업 유형/키워드를 입력받아 최적 이미지 생성 스킬을 추천합니다.",
    )
    parser.add_argument(
        "--type",
        dest="task_type",
        required=True,
        metavar="TASK_TYPE",
        help='이미지 작업 유형 (예: "광고 배너", "카드뉴스", "SNS 메인 이미지")',
    )
    parser.add_argument(
        "--urgent",
        action="store_true",
        default=False,
        help="긴급 플래그: satori-cardnews 강제 전환 (초고속 생성)",
    )
    parser.add_argument(
        "--count",
        type=int,
        default=1,
        metavar="N",
        help="생성 수량. N >= 10이면 satori-cardnews 강제 전환 (SLA 보호)",
    )
    parser.add_argument(
        "--json",
        dest="output_json",
        action="store_true",
        default=False,
        help="JSON 형식으로만 출력 (프로그래매틱 사용)",
    )
    return parser


def main() -> int:
    parser = build_parser()
    args = parser.parse_args()

    result = route_skill(
        task_type=args.task_type,
        urgent=args.urgent,
        count=args.count,
    )

    if args.output_json:
        print(json.dumps(result, ensure_ascii=False, indent=2))
    else:
        print_human_readable(result)

    # exit code: 성공 0, 매칭 실패 1
    if result["recommended_skill"] is None:
        return 1
    return 0


if __name__ == "__main__":
    sys.exit(main())
