#!/usr/bin/env python3
# File: src/noveler/domain/value_objects/element_verification_result.py
# Purpose: プロット要素検証結果を表現する値オブジェクト（LLMベース検証対応）
# Context: SPEC-PLOT-ADHERENCE-001 の改善版実装

"""プロット要素検証結果値オブジェクト

LLMベースのプロット要素検証結果を表現する不変の値オブジェクト。
検証状態、エビデンス（引用箇所）、信頼度スコアを保持。

Purpose:
    プロット要素が原稿内で実装されているかの検証結果を構造化。
    従来の単語マッチングから意味的検証への改善により、
    エビデンスと信頼度スコアを追加。

Side Effects:
    None - 純粋な値オブジェクト
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal

VerificationStatus = Literal["IMPLEMENTED", "PARTIAL", "MISSING"]


@dataclass(frozen=True)
class ElementVerificationResult:
    """プロット要素検証結果値オブジェクト

    Attributes:
        status: 検証状態（IMPLEMENTED=実装済み, PARTIAL=部分実装, MISSING=未実装）
        evidence: 原稿からの引用（根拠となるテキスト）
        evidence_start: 引用開始位置（文字オフセット）
        evidence_end: 引用終了位置（文字オフセット）
        confidence: 信頼度スコア（0.0-1.0、LLM判定の確信度）
        reason: 判定理由（人間可読な説明）
    """

    status: VerificationStatus
    confidence: float
    reason: str
    evidence: str | None = None
    evidence_start: int | None = None
    evidence_end: int | None = None

    def __post_init__(self) -> None:
        """値の妥当性検証"""
        if not 0.0 <= self.confidence <= 1.0:
            msg = f"confidenceは0.0-1.0の範囲である必要があります: {self.confidence}"
            raise ValueError(msg)

        if self.status not in ("IMPLEMENTED", "PARTIAL", "MISSING"):
            msg = f"statusは IMPLEMENTED/PARTIAL/MISSING のいずれかである必要があります: {self.status}"
            raise ValueError(msg)

        # evidenceがある場合は start/end も必須
        if self.evidence and (self.evidence_start is None or self.evidence_end is None):
            # 警告のみ（位置情報がないエビデンスも許容）
            pass

        # start/end の整合性チェック
        if (
            self.evidence_start is not None
            and self.evidence_end is not None
            and self.evidence_start > self.evidence_end
        ):
            msg = f"evidence_start ({self.evidence_start}) は evidence_end ({self.evidence_end}) 以下である必要があります"
            raise ValueError(msg)

    def is_implemented(self) -> bool:
        """完全実装判定

        Returns:
            bool: 完全に実装されている場合 True
        """
        return self.status == "IMPLEMENTED"

    def is_partial(self) -> bool:
        """部分実装判定

        Returns:
            bool: 部分的に実装されている場合 True
        """
        return self.status == "PARTIAL"

    def is_missing(self) -> bool:
        """未実装判定

        Returns:
            bool: 実装されていない場合 True
        """
        return self.status == "MISSING"

    def has_high_confidence(self, threshold: float = 0.8) -> bool:
        """高信頼度判定

        Args:
            threshold: 信頼度閾値（デフォルト: 0.8）

        Returns:
            bool: 信頼度が閾値以上の場合 True
        """
        return self.confidence >= threshold

    def has_evidence(self) -> bool:
        """エビデンス存在判定

        Returns:
            bool: エビデンス（引用）が存在する場合 True
        """
        return self.evidence is not None and len(self.evidence.strip()) > 0

    def to_dict(self) -> dict:
        """辞書形式に変換

        Returns:
            dict: 検証結果の辞書表現
        """
        return {
            "status": self.status,
            "confidence": self.confidence,
            "reason": self.reason,
            "evidence": self.evidence,
            "evidence_start": self.evidence_start,
            "evidence_end": self.evidence_end,
        }

    @classmethod
    def create_implemented(
        cls,
        evidence: str,
        confidence: float,
        reason: str,
        evidence_start: int | None = None,
        evidence_end: int | None = None,
    ) -> ElementVerificationResult:
        """完全実装結果を生成

        Args:
            evidence: 根拠となる引用
            confidence: 信頼度スコア
            reason: 判定理由
            evidence_start: 引用開始位置
            evidence_end: 引用終了位置

        Returns:
            ElementVerificationResult: 完全実装の検証結果
        """
        return cls(
            status="IMPLEMENTED",
            confidence=confidence,
            reason=reason,
            evidence=evidence,
            evidence_start=evidence_start,
            evidence_end=evidence_end,
        )

    @classmethod
    def create_partial(
        cls,
        reason: str,
        confidence: float,
        evidence: str | None = None,
        evidence_start: int | None = None,
        evidence_end: int | None = None,
    ) -> ElementVerificationResult:
        """部分実装結果を生成

        Args:
            reason: 判定理由
            confidence: 信頼度スコア
            evidence: 根拠となる引用（任意）
            evidence_start: 引用開始位置
            evidence_end: 引用終了位置

        Returns:
            ElementVerificationResult: 部分実装の検証結果
        """
        return cls(
            status="PARTIAL",
            confidence=confidence,
            reason=reason,
            evidence=evidence,
            evidence_start=evidence_start,
            evidence_end=evidence_end,
        )

    @classmethod
    def create_missing(cls, reason: str, confidence: float = 0.9) -> ElementVerificationResult:
        """未実装結果を生成

        Args:
            reason: 判定理由
            confidence: 信頼度スコア（デフォルト: 0.9）

        Returns:
            ElementVerificationResult: 未実装の検証結果
        """
        return cls(
            status="MISSING",
            confidence=confidence,
            reason=reason,
            evidence=None,
            evidence_start=None,
            evidence_end=None,
        )
