"""Per-plan evidence aggregation for Avatar vision (0.2.2)."""

from __future__ import annotations

import hashlib
import json
from dataclasses import dataclass, field
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

from iuve_connect_agents.shared.evidence_bundle import EvidenceArtifact, EvidenceBundle, StepEvidence


DEFAULT_BUNDLE_ROOT = Path.home() / ".local" / "share" / "iuve-connect" / "evidence-bundles"


@dataclass
class EvidenceCollector:
    plan_id: str
    goal_summary: str
    steps: list[StepEvidence] = field(default_factory=list)
    collected_at: str = ""

    def __post_init__(self) -> None:
        if not self.collected_at:
            self.collected_at = datetime.now(timezone.utc).isoformat()

    def record_step(
        self,
        *,
        step_id: str,
        command_type: str,
        status: str,
        artifacts: list[dict[str, Any] | EvidenceArtifact] | None = None,
        capability_id: str = "",
        exit_code: int | None = None,
        duration_ms: int = 0,
    ) -> None:
        parsed_artifacts: list[EvidenceArtifact] = []
        for raw in artifacts or []:
            if isinstance(raw, EvidenceArtifact):
                parsed_artifacts.append(raw)
                continue
            parsed_artifacts.append(
                EvidenceArtifact(
                    kind=str(raw.get("kind") or ""),
                    path=str(raw.get("path") or ""),
                    sha256=str(raw.get("sha256") or ""),
                    size_bytes=int(raw.get("size_bytes") or 0),
                    mime=str(raw.get("mime") or ""),
                    redacted=bool(raw.get("redacted", False)),
                    display_server=str(raw.get("display_server") or ""),
                    capture_backend=str(raw.get("capture_backend") or ""),
                )
            )
        self.steps.append(
            StepEvidence(
                step_id=step_id,
                command_type=command_type,
                capability_id=capability_id,
                status=status,
                artifacts=parsed_artifacts,
                exit_code=exit_code,
                duration_ms=duration_ms,
            )
        )

    def latest_screenshot(self, step_id: str | None = None) -> EvidenceArtifact | None:
        ordered = list(self.steps)
        if step_id:
            ordered = [step for step in ordered if step.step_id == step_id]
        for step in reversed(ordered):
            for artifact in reversed(step.artifacts):
                if artifact.kind == "screenshot":
                    return artifact
        return None

    def record_verify_outcome(
        self,
        *,
        step_id: str,
        command_type: str,
        status: str,
        evidence: dict[str, Any],
        capability_id: str = "agent.screen.verify",
        duration_ms: int = 0,
    ) -> None:
        artifacts: list[dict[str, Any]] = []
        screenshot_path = str(evidence.get("screenshot_path") or "")
        screenshot_sha256 = str(evidence.get("screenshot_sha256") or "")
        if screenshot_path:
            artifacts.append(
                {
                    "kind": "screenshot",
                    "path": screenshot_path,
                    "sha256": screenshot_sha256,
                }
            )
        verifier_result = evidence.get("verifier_result")
        if isinstance(verifier_result, dict):
            artifacts.append({"kind": "verifier_result", **verifier_result})
        artifacts.append(dict(evidence))
        self.record_step(
            step_id=step_id,
            command_type=command_type,
            status=status,
            artifacts=artifacts,
            capability_id=capability_id,
            duration_ms=duration_ms,
        )

    def to_bundle(self) -> dict[str, Any]:
        bundle = EvidenceBundle(
            plan_id=self.plan_id,
            goal_summary=self.goal_summary,
            collected_at=self.collected_at,
            steps=list(self.steps),
        )
        return bundle.to_dict()

    def persist(self, path: Path | None = None) -> str:
        root = path or DEFAULT_BUNDLE_ROOT
        root.mkdir(parents=True, exist_ok=True)
        bundle_id = hashlib.sha256(
            f"{self.plan_id}:{self.collected_at}:{len(self.steps)}".encode("utf-8")
        ).hexdigest()[:16]
        target = root / f"{_safe_segment(self.plan_id)}_{bundle_id}.json"
        target.write_text(json.dumps(self.to_bundle(), ensure_ascii=True, indent=2) + "\n", encoding="utf-8")
        return bundle_id


def _safe_segment(value: str) -> str:
    cleaned = "".join(ch if ch.isalnum() or ch in {"-", "_", "."} else "_" for ch in str(value).strip())
    return cleaned or "plan"
