"""품질 검증기 - 생성된 이미지가 기준을 충족하는지 자동 검사한다."""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

import numpy as np

try:
    import cv2
    from PIL import Image
except ImportError as e:
    raise ImportError("opencv-python, Pillow이 필요합니다: pip install opencv-python Pillow") from e


@dataclass
class ValidationResult:
    passed: bool
    score: float            # 0.0 ~ 1.0 종합 품질 점수
    resolution_ok: bool
    sharpness_ok: bool
    color_diversity_ok: bool
    messages: list[str]

    @property
    def summary(self) -> str:
        status = "PASS" if self.passed else "FAIL"
        return f"[{status}] score={self.score:.2f} | " + " | ".join(self.messages)


class QualityValidator:
    """이미지 품질을 자동으로 검증한다."""

    def __init__(
        self,
        min_resolution: int = 2048,
        sharpness_threshold: float = 100.0,
        color_diversity_threshold: float = 0.15,
    ):
        self.min_resolution = min_resolution
        self.sharpness_threshold = sharpness_threshold
        self.color_diversity_threshold = color_diversity_threshold

    def validate(self, image_path: Path) -> ValidationResult:
        if not image_path.exists():
            return ValidationResult(
                passed=False, score=0.0,
                resolution_ok=False, sharpness_ok=False, color_diversity_ok=False,
                messages=["파일이 존재하지 않음"],
            )

        img_pil = Image.open(image_path).convert("RGB")
        img_cv = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)

        resolution_ok, res_msg = self._check_resolution(img_pil)
        sharpness_ok, sharp_score, sharp_msg = self._check_sharpness(img_cv)
        color_ok, color_msg = self._check_color_diversity(img_cv)

        scores = [
            1.0 if resolution_ok else 0.0,
            min(sharp_score / (self.sharpness_threshold * 3), 1.0),
            1.0 if color_ok else 0.3,
        ]
        overall_score = float(np.mean(scores))
        passed = resolution_ok and sharpness_ok and color_ok

        return ValidationResult(
            passed=passed,
            score=overall_score,
            resolution_ok=resolution_ok,
            sharpness_ok=sharpness_ok,
            color_diversity_ok=color_ok,
            messages=[res_msg, sharp_msg, color_msg],
        )

    def _check_resolution(self, img: Image.Image):
        w, h = img.size
        ok = w >= self.min_resolution and h >= self.min_resolution
        msg = f"해상도={w}x{h} {'OK' if ok else f'(최소 {self.min_resolution} 필요)'}"
        return ok, msg

    def _check_sharpness(self, img_cv):
        gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
        lap_var = cv2.Laplacian(gray, cv2.CV_64F).var()
        ok = lap_var >= self.sharpness_threshold
        msg = f"선명도={lap_var:.1f} {'OK' if ok else f'(임계값 {self.sharpness_threshold})'}"
        return ok, float(lap_var), msg

    def _check_color_diversity(self, img_cv):
        """색상 다양성 검사 - 단색 평면 출력을 탐지한다."""
        hsv = cv2.cvtColor(img_cv, cv2.COLOR_BGR2HSV)
        s_channel = hsv[:, :, 1].astype(np.float32) / 255.0
        mean_saturation = float(s_channel.mean())
        ok = mean_saturation >= self.color_diversity_threshold
        msg = f"색상다양성={mean_saturation:.3f} {'OK' if ok else f'(임계값 {self.color_diversity_threshold})'}"
        return ok, msg
