"""Verify command implementation for the ICSD CLI."""

from __future__ import annotations

import json
from collections.abc import Mapping, Sequence
from pathlib import Path

from icsd.core.evidence import validate_evidence_payload

from ._shared import EXIT_OK, EXIT_TOOL_ERROR, emit_json, emit_stderr


def _verify_status_from_exit_code(exit_code: int) -> str:
    if exit_code == EXIT_OK:
        return "ok"
    return "error"


def _verify_report(
    *,
    evidence_path: Path,
    exit_code: int,
    errors: Sequence[str],
) -> dict[str, object]:
    return {
        "command": "verify",
        "path": str(evidence_path),
        "status": _verify_status_from_exit_code(exit_code),
        "exit_code": exit_code,
        "error_count": len(errors),
        "errors": list(errors),
    }


def _finalise_verify_result(
    *,
    evidence_path: Path,
    output_format: str,
    exit_code: int,
    errors: Sequence[str],
) -> int:
    if output_format == "json":
        emit_json(
            _verify_report(
                evidence_path=evidence_path,
                exit_code=exit_code,
                errors=errors,
            )
        )
        return exit_code
    for error in errors:
        emit_stderr(f"verify: {error}")
    return exit_code


def run_verify(evidence_json: str, *, output_format: str) -> int:
    """Run the verify command."""
    evidence_path = Path(evidence_json)
    if not evidence_path.exists():
        return _finalise_verify_result(
            evidence_path=evidence_path,
            output_format=output_format,
            exit_code=EXIT_TOOL_ERROR,
            errors=(f"path does not exist: {evidence_path}.",),
        )
    if not evidence_path.is_file():
        return _finalise_verify_result(
            evidence_path=evidence_path,
            output_format=output_format,
            exit_code=EXIT_TOOL_ERROR,
            errors=(f"path is not a file: {evidence_path}.",),
        )
    try:
        raw_payload = evidence_path.read_text(encoding="utf-8")
    except OSError as exc:
        return _finalise_verify_result(
            evidence_path=evidence_path,
            output_format=output_format,
            exit_code=EXIT_TOOL_ERROR,
            errors=(f"unable to read {evidence_path}: {exc}.",),
        )
    try:
        payload = json.loads(raw_payload)
    except json.JSONDecodeError as exc:
        return _finalise_verify_result(
            evidence_path=evidence_path,
            output_format=output_format,
            exit_code=EXIT_TOOL_ERROR,
            errors=(
                f"invalid JSON in {evidence_path}: {exc.msg} "
                f"(line {exc.lineno}, column {exc.colno}).",
            ),
        )
    if not isinstance(payload, Mapping):
        return _finalise_verify_result(
            evidence_path=evidence_path,
            output_format=output_format,
            exit_code=EXIT_TOOL_ERROR,
            errors=(f"evidence payload must be a JSON object in {evidence_path}.",),
        )
    errors = validate_evidence_payload(payload)
    if errors:
        return _finalise_verify_result(
            evidence_path=evidence_path,
            output_format=output_format,
            exit_code=EXIT_TOOL_ERROR,
            errors=errors,
        )
    return _finalise_verify_result(
        evidence_path=evidence_path,
        output_format=output_format,
        exit_code=EXIT_OK,
        errors=(),
    )
