"""씬 이미지 검증 서비스 — W5 F22 Phase B.6.

SceneImageService에서 T2I 검증 로직을 이관. 공개 API는 facade가 유지하고
본 서비스는 구현을 담당.

Phase 4 iter 7 follow-up B1 (cost policy): scene_lvm_validation_mode
default = "off" 라 본 서비스의 legacy validator (LVM 2) 도 default disabled.
mode == "full" 일 때만 ImageValidator 인스턴스 생성. 이 정책은 자동 batch
경로 (SceneGenerationCoordinator) 에 적용되며, image_review_service 등
운영자가 명시적으로 trigger 하는 review API 는 별도 (cost policy 범위 밖).

공개 API (SceneImageService facade가 delegation):
- `create_validator()` — mode/key 가드 통과 시 ImageValidator, 아니면 None.
- `validate_scene(validator, file_path, scene_info, entity_names, status, review_notes)`
  T2I로 생성된 씬 이미지가 visible_entities를 실제 포함하는지 OpenAI LVM으로 검증.
  score < 60이면 status='needs_fix'로 마킹.
"""
from __future__ import annotations

import json
import logging
from pathlib import Path
from typing import Any, Dict, List, Optional

from sqlalchemy.orm import Session as OrmSession

from app.core.config import settings
from app.modules.image_validator import ImageValidator

logger = logging.getLogger(__name__)


class SceneValidationService:
    """T2I 이미지 검증 전담 서비스 (W5 F22 Phase B.6)."""

    def __init__(self, db: OrmSession, project_id: str) -> None:
        self._db = db
        self._project_id = project_id

    def create_validator(self) -> Optional[ImageValidator]:
        """ImageValidator 생성. None 반환 조건:
        1) openai_api_key 미설정.
        2) scene_lvm_validation_mode != "full" (Phase 4 iter 7 follow-up B1).

        W5 F22 Phase B.7: scene_image_service._create_validator에서 이관됨.

        Phase 4 iter 7 follow-up B1: scene_image_pipeline 의 _call_gpt_lvm
        (LVM 1) 외에 SceneGenerationCoordinator 가 별도 ImageValidator (LVM 2,
        image_validator.py) 를 호출하는 경로가 있어, mode="off" 인데도 OpenAI
        vision 호출이 모든 shot 마다 일어나 cost policy 가 절반만 적용됐음
        (Codex review B1 + 사용자 cost 정책). LVM 1 과 같은 mode 로 통합.
        mode="full" 만 legacy validator 활성. targeted/sample 에서도 deactivate
        — 운영자가 LVM 을 "선택적 활성" 하려는 의도이지 legacy 까지 항상 켜는
        것이 아님 (cost 절감 정합).
        """
        mode = settings.scene_lvm_validation_mode
        if mode != "full":
            logger.info(
                "Skipping legacy scene image validation — scene_lvm_validation_mode=%s "
                "(LVM 2 disabled by cost policy; only mode='full' enables it).",
                mode,
            )
            return None
        from app.core.openai_keys import has_openai_key
        if not has_openai_key():
            logger.info("Skipping image validation -- OpenAI API key not configured.")
            return None
        return ImageValidator()

    def validate_scene(
        self,
        validator: ImageValidator,
        file_path: str,
        scene_info: Dict[str, Any],
        entity_names: List[str],
        status: str,
        review_notes: str,
    ) -> tuple:
        """T2I 씬 이미지 LVM 검증.

        Returns: (score, result_json, updated_status, updated_review_notes)
        - 파일 미존재: (None, None, status, review_notes)
        - score < 60: status='needs_fix', review_notes에 이슈 삽입
        - 예외 발생: (None, None, status, review_notes) + warning log
        """
        try:
            fp = Path(file_path)
            if not fp.exists():
                return None, None, status, review_notes
            image_bytes = fp.read_bytes()
            result = validator.validate_scene_image(image_bytes, scene_info, entity_names)
            score = result.get("score", 0)
            result_json = json.dumps(result, ensure_ascii=False)
            if score < 60:
                issues = result.get("issues", [])
                issue_text = "; ".join(issues) if issues else "Low validation score"
                status = "needs_fix"
                review_notes = f"[auto-validation] score={score}: {issue_text}"
            logger.info("Scene image validated: score=%d, passed=%s", score, result.get("passed"))
            return score, result_json, status, review_notes
        except Exception as exc:
            logger.warning("Scene image validation failed: %s", exc)
            return None, None, status, review_notes
