import json
import google.generativeai as genai
from google.api_core import exceptions as google_exceptions
from app.config import settings

if settings.GEMINI_API_KEY:
    genai.configure(api_key=settings.GEMINI_API_KEY)

_text_model = genai.GenerativeModel("gemini-3-flash-preview")


class GeminiError(Exception):
    pass


def _call_gemini(prompt: str) -> str:
    """Gemini 텍스트 생성 + 에러 핸들링"""
    try:
        response = _text_model.generate_content(prompt)
        return response.text
    except google_exceptions.ResourceExhausted:
        raise GeminiError("API 요청 횟수 초과 (Rate Limit). 잠시 후 다시 시도해주세요.")
    except google_exceptions.DeadlineExceeded:
        raise GeminiError("API 응답 시간 초과 (Timeout). 잠시 후 다시 시도해주세요.")


def _parse_json(text: str) -> dict:
    """Gemini 응답에서 JSON 추출 (```json 블록 포함 처리)"""
    text = text.strip()
    if text.startswith("```"):
        text = text.split("```")[1]
        if text.startswith("json"):
            text = text[4:]
    return json.loads(text.strip())


# ─────────────────────────────────────
# 이력서 파싱
# ─────────────────────────────────────
def parse_resume(resume_text: str) -> dict:
    """
    이력서 텍스트 → 구조화된 정보
    반환: {"name", "email", "phone", "skills", "experience_years", "education"}
    """
    prompt = f"""다음 이력서 텍스트를 분석하여 구조화된 JSON 데이터로 추출하세요.
    반드시 아래 JSON 포맷을 정확히 지켜야 하며, 다른 설명 텍스트는 포함하지 마세요.

    {{
        "name": "이름 (없으면 '이름 미상')",
        "email": "이메일 (없으면 null)",
        "phone": "전화번호 (없으면 null)",
        "portfolio_url": "포트폴리오, GitHub, 블로그 등 URL (없으면 null)",
        "desired_salary": "희망연봉 (없으면 null)",
        "desired_position": "희망직무 (없으면 null)",
        "skills": ["기술스택1", "기술스택2", ...],
        "experience_years": 총 경력 연수 (숫자, 신입이면 0),
        "education": "최종학력 요약 (예: 한국대학교 컴퓨터공학과 졸업)",
        "summary": "후보자의 핵심 역량과 경력을 3~5문장으로 요약 (전문적인 톤앤매너)",
        "parsed_data": {{
            "careers": [
                {{
                    "company": "회사명",
                    "role": "직무/직책",
                    "period": "근무기간 (YYYY.MM - YYYY.MM)",
                    "description": "주요 업무 및 성과"
                }}
            ],
            "educations": [
                {{
                    "school": "학교명",
                    "major": "전공",
                    "status": "졸업/중퇴/재학"
                }}
            ],
            "certificates": ["자격증1", "자격증2"]
        }}
    }}

    이력서 텍스트:
    {resume_text}"""

    raw = _call_gemini(prompt)
    try:
        return _parse_json(raw)
    except json.JSONDecodeError:
        raise GeminiError("이력서 파싱 실패: 올바른 JSON 응답을 받지 못했습니다.")


# ─────────────────────────────────────
# JD 분석
# ─────────────────────────────────────
def analyze_jd(jd_text: str) -> dict:
    """
    채용공고 텍스트 → 핵심 요구사항 추출
    반환: {"title", "required_skills", "preferred_skills", "experience_min_years", "education_required", "summary"}
    """
    prompt = f"""다음 채용공고에서 핵심 요구사항을 추출하여 JSON으로 반환하세요.
반드시 아래 형식의 JSON만 답변하세요. 다른 텍스트는 포함하지 마세요.

{{
    "title": "직책명",
    "required_skills": ["필수 기술1", "필수 기술2"],
    "preferred_skills": ["우대 기술1"],
    "experience_min_years": 최소 경험 연수 (숫자, 없으면 0),
    "education_required": "학력 요구사항 (없으면 null)",
    "summary": "공고 요약 (1-2문장)"
}}

채용공고:
{jd_text}"""

    raw = _call_gemini(prompt)
    try:
        return _parse_json(raw)
    except json.JSONDecodeError:
        raise GeminiError("JD 분석 실패: 올바른 JSON 응답을 받지 못했습니다.")


# ─────────────────────────────────────
# 임베딩 생성
# ─────────────────────────────────────
def create_embedding(text: str) -> list[float]:
    """텍스트 → 벡터 임베딩 (768차원, text-embedding-004)"""
    try:
        result = genai.embed_content(
            model="models/text-embedding-004",
            content=text,
        )
        return result["embedding"]
    except google_exceptions.ResourceExhausted:
        raise GeminiError("임베딩 API 요청 횟수 초과. 잠시 후 다시 시도해주세요.")
    except google_exceptions.DeadlineExceeded:
        raise GeminiError("임베딩 API 응답 시간 초과. 잠시 후 다시 시도해주세요.")


# ─────────────────────────────────────
# 매칭 사유 생성
# ─────────────────────────────────────
def generate_match_reasons(jd_title: str, jd_requirements: str, candidates: list[dict]) -> dict[str, str]:
    """
    후보자 목록 → 한 번의 Gemini 호출로 각각의 매칭 사유 생성
    candidates: [{"id": "1", "name": "홍길동", "skills": [...], "experience_years": 3}, ...]
    반환: {"1": "사유 문장", "2": "사유 문장", ...}
    """
    candidates_text = "\n".join([
        f"- ID {c['id']}: {c['name']}, 기술: {c.get('skills', [])}, 경험: {c.get('experience_years', 0)}년"
        for c in candidates
    ])

    prompt = f"""다음 채용공고와 후보자 목록을 보고, 각 후보자가 이 직책에 적합한 이유를 1문장으로 간결하게 작성하세요.
반드시 아래 형식의 JSON만 답변하세요. 다른 텍스트는 포함하지 마세요.

{{
    "<후보자 ID>": "매칭 사유 1문장",
    ...
}}

채용공고:
직책: {jd_title}
요구사항: {jd_requirements}

후보자:
{candidates_text}"""

    raw = _call_gemini(prompt)
    try:
        return _parse_json(raw)
    except json.JSONDecodeError:
        # 사유 생성 실패 시 빈 딕셔너리 반환 (매칭 자체는 유지)
        return {}
