# -*- coding: utf-8 -*-
"""Step 5: 혼성어 판정 프롬프트 템플릿"""

import json
import re

BLEND_JUDGMENT_PROMPT = """당신은 한국어 혼성어(blend word) 판정 전문가입니다.

**혼성어(blend word)의 정의:**
혼성어란 두 개 이상의 구성 요소 중 하나 이상을 절단한 뒤 결합함으로써 새로운 형태와 의미를 만든 단어이다. 어근과 어근의 결합인 합성어나, 어근과 접사의 결합인 파생어와는 구별된다.
  - 예: 호캉스 = 호텔(hotel) + 바캉스(vacance) → '호텔'을 '호'로, '바캉스'를 '캉스'로 각각 절단한 뒤 결합
  - 비교(합성어): 손목시계 = 손목 + 시계 → 어근과 어근이 결합한 합성어이므로 혼성어가 아님
  - 비교(파생어): 풋사랑 = 풋- + 사랑 → 어근과 접사가 결합한 파생어이므로 혼성어가 아님
  - 비교(두음절어): 두쫀쿠 = 두바이 쫀득 쿠키 → 각 단어의 첫 음절만 따온 두음절어이므로 혼성어가 아님

아래 '판정 대상 어절'을 분석하여 다음 절차를 수행하십시오.

**절차:**
1) 해당 어절에 혼성어가 포함되어 있는지 판단
2) 혼성어가 포함되어 있다면, 혼성어 어형만 추출 (조사·어미 제거)
3) 혼성어의 원어 X + Y를 각각 복원하고, 각 원어의 원어(한국어/영어/일본어 등)와 어종(고유어/한자어/외래어)을 판단

**주의:** 동형어가 많을 수 있으므로, 말뭉치 용례만으로 판단하지 말고 당신의 내부 지식도 적극 활용하십시오. 용례가 없거나 모호한 경우에도 어절 자체와 패턴 정보로 판단할 수 있습니다.

---

판정 대상 어절: {word}
형태소 분석: {morphs}
매칭 패턴: {pattern}

{examples_section}

구성 요소 복원 예시 (혼성어 → 파편 분리 → 원어 복원):

[3음절]
  갓무직 → 파편: 갓+무직 → 복원: X=갓(god, 외래어(영어)), Y=사무직(事務職, 한자어)
  펫캉스 → 파편: 펫+캉스 → 복원: X=펫(pet, 외래어(영어)), Y=바캉스(vacance, 외래어(프랑스어))
  호캉스 → 파편: 호+캉스 → 복원: X=호텔(hotel, 외래어(영어)), Y=바캉스(vacance, 외래어(프랑스어))

[4음절]
  브렉시트 → 파편: 브+렉시트 → 복원: X=브리튼(Britain, 외래어(영어)), Y=엑시트(exit, 외래어(영어))
  소셜슈머 → 파편: 소셜+슈머 → 복원: X=소셜(social, 외래어(영어)), Y=컨슈머(consumer, 외래어(영어))
  할매니얼 → 파편: 할매+니얼 → 복원: X=할매(고유어), Y=밀레니얼(millennial, 외래어(영어))

[5음절]
  아이렉시트 → 파편: 아이+렉시트 → 복원: X=아일랜드(Ireland, 외래어(영어)), Y=엑시트(exit, 외래어(영어))
  인포데믹스 → 파편: 인포+데믹스 → 복원: X=인포메이션(information, 외래어(영어)), Y=에피데믹스(epidemics, 외래어(영어))
  컬쳐플렉스 → 파편: 컬쳐+플렉스 → 복원: X=컬쳐(culture, 외래어(영어)), Y=컴플렉스(complex, 외래어(영어))

[6음절]
  인스타그래니 → 파편: 인스타+그래니 → 복원: X=인스타그램(Instagram, 외래어(영어)), Y=그래니(granny, 외래어(영어))
  트럼프노믹스 → 파편: 트럼프+노믹스 → 복원: X=트럼프(Trump, 외래어(영어)), Y=이코노믹스(economics, 외래어(영어))
  포크플레이션 → 파편: 포크+플레이션 → 복원: X=포크(pork, 외래어(영어)), Y=인플레이션(inflation, 외래어(영어))

---

[포함] 혼성어로 판정하는 기준:

[포함1] 두 개 이상의 원어를 절단·결합하여 새 의미를 만든 단어
  - 예: 펫캉스(펫+바캉스), 쓰저씨(쓰레기+아저씨), 엘린이(엘지+어린이)
  - (A+B) 형태의 설명이 용례에 나타나면 강한 근거

[포함2] 기존 혼성어 목록의 패턴(X+린이, X+캉스, X+슈머, X+플레이션 등)을 활용하여 생성된 새 단어
  - 예: 큠린이(키움+어린이), 알캉스(알바+바캉스), 보이슈머(보이+컨슈머)

[포함3] '일명', '신조어', '합성어', '줄임말' 등 화용 표지와 함께 출현하는 경우

---

[배제] 혼성어가 아닌 것:

[배제1] 인명+조사: 한국인 이름에 조사(-이, -의, -에게 등)가 결합된 어형
  - 예: 효린이(효린+이), 예린이(예린+이)
  - 단, 해당 어형이 실제 인명이 아닌 일반명사인 경우(예: 뷰린이=뷰티+어린이)는 혼성어로 판정. 내부 지식을 적극 활용하여 인명 여부를 확인할 것.

[배제2] 외래어·외국 고유명사의 단순 음차: 외국 지명, 인명, 브랜드명 등을 그대로 한글로 음차한 것
  - 예: 브랸스크(러시아 지명), 꾸르스크(러시아 지명), 투스크(인명), 스크류(screw)
  - 단, 고유명사가 포함되더라도 단어 형성법 자체가 혼성이면 혼성어로 판정 (예: 유느님(유재석+하느님), 맥세권(맥도날드+역세권), 트럼프노믹스(트럼프+이코노믹스))

[배제3] 단순 차용어(loanword): 원어 하나를 그대로 한글로 옮긴 것
  - 예: 더스크(dusk), 컨택트(contact), 스크래처(scratcher)
  - 단, 원어 자체가 혼성어인 경우(예: 브런치=brunch(breakfast+lunch), 스모그=smog(smoke+fog))는 혼성어로 판정

[배제4] 패턴이 우연히 일치하는 무관한 단어
  - 예: 스피또(복권 브랜드), 캉스푸(중국 기업명)

---

출력 규칙:
- 반드시 JSON만 출력
- 판정 결과가 "혼성어"인 경우 모든 필드를 채울 것
- 판정 결과가 "비혼성어" 또는 "판정 불가"인 경우 혼성어_어형, 원어X~어종Y는 빈 문자열

출력 JSON 키:
  판정 결과: "혼성어" / "비혼성어" / "판정 불가"
  판정 기준: "포함1", "배제2" 등
  판정 근거: 한 문장으로 간결하게. 말뭉치 용례 기반이면 "용례 기반", 모델 내부 지식 기반이면 "내부 지식 기반"을 문두에 명시
  혼성어_어형: 조사·어미를 제거한 혼성어 자체 (예: "펫캉스")
  원어X: 첫 번째 구성 요소의 절단 전 전체 단어 (예: "펫" ← 펫캉스에서 '펫'은 절단 없이 그대로 사용, "호텔" ← 호캉스에서 '호'로 절단되었으므로 원래 단어 '호텔'을 복원)
  원어X_원어: 원어의 원형 (예: "pet", "hotel")
  원어X_어종: "고유어" / "한자어" / "외래어(영어)" / "외래어(프랑스어)" / "외래어(독일어)" / "외래어(일본어)" / "외래어(이탈리아어)" / "외래어(스페인어)" / "외래어(그리스어)" / "외래어(라틴어)" / "외래어(중국어)" 등 — 해당 언어명을 구체적으로 기재
  원어Y: 두 번째 구성 요소의 절단 전 전체 단어 (예: "바캉스" ← '캉스'로 절단되었으므로 원래 단어 '바캉스'를 복원. 절단된 파편이 아닌 반드시 전체 단어를 기재할 것)
  원어Y_원어: 원어의 원형 (예: "vacance")
  원어Y_어종: 원어X_어종과 동일 형식 — 해당 언어명을 구체적으로 기재

출력 예시:
{{
  "판정 결과": "혼성어",
  "판정 기준": "포함1",
  "판정 근거": "'펫'(pet)과 '바캉스'(vacance)를 절단·결합하여 반려동물과 함께하는 휴가라는 새 의미를 만든 혼성어이다.",
  "혼성어_어형": "펫캉스",
  "원어X": "펫",
  "원어X_원어": "pet",
  "원어X_어종": "외래어(영어)",
  "원어Y": "바캉스",
  "원어Y_원어": "vacance",
  "원어Y_어종": "외래어(프랑스어)"
}}
"""

RESULT_KEYS = [
    "판정 결과", "판정 기준", "판정 근거",
    "혼성어_어형",
    "원어X", "원어X_원어", "원어X_어종",
    "원어Y", "원어Y_원어", "원어Y_어종",
]

_EMPTY_RESULT = {k: "" for k in RESULT_KEYS}
_EMPTY_RESULT["판정 결과"] = "판정 불가"


def _build_examples_section(examples: list[str], n: int) -> str:
    """용례 N개 섹션을 동적으로 구성."""
    exs = list(examples[:n])
    exs.extend(["(없음)"] * (n - len(exs)))
    lines = [f"용례 {i + 1}: {ex if ex else '(없음)'}" for i, ex in enumerate(exs)]
    return "\n".join(lines)


def format_prompt(
    word: str,
    morphs: str,
    pattern: str,
    examples: list[str],
) -> str:
    """내부용 format_prompt (하위 호환). build_prompt 사용 권장."""
    return BLEND_JUDGMENT_PROMPT.format(
        word=word,
        morphs=morphs or "(없음)",
        pattern=pattern or "(없음)",
        examples_section=_build_examples_section(examples, 3),
    )


def build_prompt(
    word: str,
    pattern: str = "",
    examples: list[str] | None = None,
    *,
    morphs: str = "",
    n_examples: int = 3,
) -> str:
    """혼성어 판정용 LLM 프롬프트를 생성한다.

    후보 어절, 매칭 패턴, 말뭉치 용례를 조합하여
    LLM(GPT-4o 등)에 전달할 혼성어 판정 프롬프트를 구성한다.

    Parameters
    ----------
    word : str
        후보 어절 (예: "슬세권")
    pattern : str
        매칭 패턴 (예: "세권"). 없으면 "(없음)".
    examples : list[str] | None
        말뭉치 용례 리스트.
        None이면 용례 없이 프롬프트를 생성한다.
    morphs : str
        형태소 분석 결과 (선택). 없으면 "(없음)".
    n_examples : int
        프롬프트에 포함할 용례 수 (기본 3).
        examples가 이보다 적으면 "(없음)"으로 채운다.

    Returns
    -------
    str
        LLM에 전달할 프롬프트 문자열

    Examples
    --------
    >>> from wordextractor import build_prompt
    >>> prompt = build_prompt("슬세권", pattern="세권",
    ...     examples=["슬세권 아파트 인기", "슬세권(슬리퍼+역세권) 열풍"])
    >>> print(prompt[:50])
    당신은 한국어 혼성어(blend word) 판정 전문가입니다.

    >>> # 용례 5개로 프롬프트 생성
    >>> prompt = build_prompt("맥세권", pattern="세권",
    ...     examples=ex_list, n_examples=5)
    """
    if examples is None:
        examples = []

    return BLEND_JUDGMENT_PROMPT.format(
        word=word,
        morphs=morphs or "(없음)",
        pattern=pattern or "(없음)",
        examples_section=_build_examples_section(examples, n_examples),
    )


def parse_judgment_json(text: str) -> dict:
    """LLM 응답 JSON 파싱"""
    text = (text or "").strip()

    m = re.search(r"\{.*\}", text, re.S)
    if m:
        text = m.group(0)

    try:
        obj = json.loads(text)
    except json.JSONDecodeError:
        result = dict(_EMPTY_RESULT)
        result["판정 근거"] = "JSON 파싱 실패"
        return result

    result = {}
    for k in RESULT_KEYS:
        result[k] = (obj.get(k, "") or "").strip()

    if result["판정 결과"] not in ("혼성어", "비혼성어", "판정 불가"):
        result["판정 결과"] = "판정 불가"

    return result
