"""인계에 사용할 최신 검증 실행과 준비 당시 대상의 연결을 확인한다."""
from pathlib import Path

from .final_report_paths import final_report_data_path
from .json_boundary import JsonBoundaryError, load_owned_object
from .paths import RunRef, next_run_seq, resolve_under_root
from .release_gate import release_handoff_allowed
from .verification_target import read_verification_target


class VerificationEvidenceError(ValueError):
    """검증 증거가 없거나 최신 실행·대상과 불일치한다."""


def load_latest_verification(run_dir: Path) -> tuple[Path, dict, dict]:
    """보고서 번호가 아닌 실행 명세서 번호로 최신 실행을 선택한다."""
    ref = RunRef.from_run_dir(Path(run_dir).resolve())
    seq = next_run_seq(ref.run_dir / "manifests", ref.task_type) - 1
    latest = RunRef.from_task_root(ref.task_root, ref.task_type, seq=seq, stage=ref.stage)
    try:
        manifest = load_owned_object(latest.manifest, artifact="verification run")
        if manifest.get("taskType") != "final-verification":
            raise VerificationEvidenceError(f"not a final-verification run: {latest.manifest}")
        root = Path(str(manifest.get("projectRoot") or "")).resolve()
        report = resolve_under_root(root, str(manifest.get("expectedReportRecordPath") or ""))
        if report is None or report.parent != ref.reports_dir:
            raise VerificationEvidenceError(f"report outside verification run: {latest.manifest}")
        data = load_owned_object(report, artifact="verification report")
    except JsonBoundaryError as exc:
        raise VerificationEvidenceError(f"latest verification unavailable: {latest.manifest}: {exc}") from exc
    validate_verification_target(ref, manifest, data)
    return report, manifest, data


def validate_verification_target(ref: RunRef, manifest: dict, data: dict) -> None:
    """준비 당시 범위·단계·커밋을 원본 보고서와 대조한다."""
    root = Path(str(manifest.get("projectRoot") or "")).resolve()
    relative = str(manifest.get("verificationTargetPath") or "")
    target_path = resolve_under_root(root, relative)
    if not relative or target_path is None or not target_path.is_relative_to(ref.task_root):
        raise VerificationEvidenceError("verification target missing or outside task; re-run final-verification")
    target = read_verification_target(root, relative)
    if target is None:
        raise VerificationEvidenceError("verification target missing or digest mismatch; re-run final-verification")
    scope = "single-stage" if ref.stage is not None else "whole-task"
    source = (data.get("finalVerification") or {}).get("sourceImplementationReport") or {}
    if ((data.get("header") or {}).get("taskType") != "final-verification"
            or data.get("verificationScope") != scope or target["scope"] != scope):
        raise VerificationEvidenceError("verification scope mismatch")
    for key, field in (("head", "capturedHeadSha"), ("base", "implementationBaseRef"), ("worktree", "worktreePath")):
        if not target[key] or source.get(field) != target[key]:
            raise VerificationEvidenceError(f"verification {key} missing or mismatched")
    stages = {row.get("stage") for row in (data.get("finalVerification") or {}).get("stageReports", [])}
    if not stages or stages != target["stages"] or (ref.stage is not None and stages != {ref.stage}):
        raise VerificationEvidenceError("verification stages mismatch")


def require_finished_verification(manifest: dict, data: dict) -> None:
    """작성 중인 보고서나 계약 검증 실패는 인계 근거로 사용하지 않는다."""
    if (manifest.get("validation") or {}).get("status") != "passed":
        raise VerificationEvidenceError("latest verification is unfinished or validation failed; re-run final-verification")
    if not release_handoff_allowed(data):
        raise VerificationEvidenceError("latest verification blocks release-handoff")


def verification_row_is_current(row: dict) -> bool:
    """저장한 승인 행이 같은 단계의 최신 완료 검증을 가리키는지 확인한다."""
    try:
        report = final_report_data_path(Path(str(row.get("report_path") or "")))
        ref = RunRef.from_report_path(report.resolve())
        latest, manifest, data = load_latest_verification(ref.run_dir)
        require_finished_verification(manifest, data)
        return (latest == report.resolve()
                and ref.stage == row.get("stage")
                and manifest.get("taskKey") == row.get("impl_task_key")
                and (data.get("finalVerification") or {}).get("sourceImplementationReport", {}).get("capturedHeadSha") == row.get("head_commit")
                and data.get("finalVerdict") == row.get("final_verdict"))
    except (ValueError, JsonBoundaryError):
        # expected-miss: 이전 형식·재검증 중인 행에는 현재 인계 자격이 없다.
        return False
