"""프롬프트·설정 파일 관리 — 자동 탭(Gemini)용.

Step 3 지침 = 프로젝트 루트 `숏폼_편집_지침서_v13.7_capcut2연동판.md` (사용자 소유,
reset 대상 아님). Step 1 프롬프트·모델 설정 = `프롬프트/` 폴더(없으면 기본값 생성).
UI(⚙ 지침 수정)에서든 메모장에서든 고치면 다음 분석부터 반영된다.
"""
from __future__ import annotations

import json
import os
from typing import Optional

_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROMPT_DIR = os.path.join(_ROOT, "프롬프트")
STEP1_PATH = os.path.join(PROMPT_DIR, "하이라이트_선정.md")
CONFIG_PATH = os.path.join(PROMPT_DIR, "설정.json")
STEP3_PATH = os.path.join(_ROOT, "숏폼_편집_지침서_v13.7_capcut2연동판.md")
RECOMMEND_PATH = os.path.join(PROMPT_DIR, "댓글_추천.md")

# 오팔 Step 1 원문 이식. 원문 JSON 예시의 오타(start_time 중복, end_time 누락)는 수정.
DEFAULT_STEP1 = """당신은 유튜브 영상에서 쇼츠(Shorts)로 제작했을 때 가장 터질 만한 구간을 찾아내는 '바이럴 분석가'입니다. 제공된 영상을 분석해 아래 규칙에 따라 5개의 하이라이트 후보 구간을 선정하세요.

1. 각 구간의 길이는 최소 1분 30초에서 최대 3분 사이로 설정할 것. (최종 편집을 위한 원천 소스 구간임)
2. 시청자의 시선을 끌 수 있는 갈등, 웃음, 반전, 혹은 핵심 정보가 포함된 구간을 우선순위로 둘 것.
3. 결과물은 반드시 아래의 JSON 형식으로만 출력할 것. (다른 설명 금지)

{
  "candidates": [
    {
      "id": 1,
      "start_time": "MM:SS",
      "end_time": "MM:SS",
      "reason": "구간 선정 이유 요약"
    },
    ... (총 5개)
  ]
}
"""

# 컷별 댓글 추천(자동 탭). {cuts} {comments} {k} 를 채워 쓴다.
DEFAULT_RECOMMEND = """너는 숏폼 편집자다. 컷마다 화면 아래에 띄울 유튜브 댓글을 고른다.

규칙:
- 컷 자막의 **내용과 의미가 통하는** 댓글만 고른다. 억지로 채우지 마라.
- 어울리는 게 없으면 그 컷은 picks 를 빈 배열로 둔다. 빈 채로 두는 게 엉뚱한 것보다 낫다.
- 한 댓글은 한 컷에만 쓴다. 여러 컷에 어울리면 가장 잘 맞는 컷 하나에만 넣어라.
- 아래 목록에 있는 댓글 번호만 쓴다. 없는 번호를 지어내지 마라.
- 컷마다 최대 {k}개까지.

컷 목록:
{cuts}

댓글 후보 (번호. 👍좋아요 / 본문):
{comments}

각 컷마다 {{"cut": 컷번호, "picks": [댓글번호…]}} 를 JSON 배열로만 출력."""

DEFAULT_CONFIG = {
    "model": "gemini-3.5-flash",
    "model_step1": "",
    "fps_step1": 0.2,
    "fps_step3": 1.0,
}


def load_step1() -> str:
    if not os.path.isfile(STEP1_PATH):
        os.makedirs(PROMPT_DIR, exist_ok=True)
        with open(STEP1_PATH, "w", encoding="utf-8") as f:
            f.write(DEFAULT_STEP1)
    with open(STEP1_PATH, encoding="utf-8") as f:
        return f.read()


def load_step3() -> str:
    if not os.path.isfile(STEP3_PATH):
        raise RuntimeError(f"Step 3 지침 파일이 없습니다: {STEP3_PATH}")
    with open(STEP3_PATH, encoding="utf-8") as f:
        return f.read()


def load_recommend() -> str:
    """컷별 댓글 추천 프롬프트. 없으면 기본값으로 파일을 만들고 읽는다(메모장 수정 가능)."""
    if not os.path.isfile(RECOMMEND_PATH):
        os.makedirs(PROMPT_DIR, exist_ok=True)
        with open(RECOMMEND_PATH, "w", encoding="utf-8") as f:
            f.write(DEFAULT_RECOMMEND)
    with open(RECOMMEND_PATH, encoding="utf-8") as f:
        return f.read()


def load_config() -> dict:
    """설정 로드. 파일이 없거나 깨졌으면 기본값(파일은 첫 save 때 생성)."""
    cfg = dict(DEFAULT_CONFIG)
    try:
        with open(CONFIG_PATH, encoding="utf-8") as f:
            loaded = json.load(f)
        if isinstance(loaded, dict):
            cfg.update(loaded)
    except (OSError, json.JSONDecodeError, ValueError):
        pass
    return cfg


def save(*, step1: Optional[str] = None, step3: Optional[str] = None,
         config: Optional[str] = None) -> None:
    """전달된 것만 저장. config 는 JSON 문자열 — 형식 오류는 예외로 올린다."""
    os.makedirs(PROMPT_DIR, exist_ok=True)
    if config is not None:                      # 검증 먼저(실패 시 아무것도 안 씀)
        cfg = json.loads(config)
        if not isinstance(cfg, dict):
            raise ValueError("설정은 JSON 객체({…})여야 합니다.")
        merged = dict(DEFAULT_CONFIG)
        merged.update(cfg)
        with open(CONFIG_PATH, "w", encoding="utf-8") as f:
            json.dump(merged, f, ensure_ascii=False, indent=1)
    if step1 is not None:
        with open(STEP1_PATH, "w", encoding="utf-8") as f:
            f.write(step1)
    if step3 is not None:
        with open(STEP3_PATH, "w", encoding="utf-8") as f:
            f.write(step3)


def reset() -> None:
    """Step 1 프롬프트·설정을 기본값으로. Step 3(지침서)는 사용자 파일이라 불변."""
    os.makedirs(PROMPT_DIR, exist_ok=True)
    with open(STEP1_PATH, "w", encoding="utf-8") as f:
        f.write(DEFAULT_STEP1)
    with open(CONFIG_PATH, "w", encoding="utf-8") as f:
        json.dump(DEFAULT_CONFIG, f, ensure_ascii=False, indent=1)
