from __future__ import annotations

from pathlib import Path
from typing import Any

from ..utils.json_utils import read_json, write_json
from ..utils.time_utils import now_iso


class VerificationService:
    """Handles manual confirmation workflow against original evidence files."""

    def confirm_document(
        self,
        *,
        applicant_base: Path,
        document_path: str,
        verified_fields: list[str] | None = None,
        note: str = "",
        confirmed_by: str = "manual_reviewer",
    ) -> dict[str, Any]:
        doc_root = applicant_base / document_path
        manifest_path = doc_root / "meta" / "manifest.json"
        document_json_path = doc_root / "extracted" / "document.json"
        quality_json_path = doc_root / "extracted" / "quality.json"

        manifest = read_json(manifest_path, default=None)
        document_json = read_json(document_json_path, default=None)
        quality_json = read_json(quality_json_path, default=None)

        if manifest is None:
            raise ValueError(f"Manifest not found: {manifest_path}")
        if document_json is None:
            raise ValueError(f"document.json not found: {document_json_path}")
        if quality_json is None:
            raise ValueError(f"quality.json not found: {quality_json_path}")

        verified_fields = verified_fields or []
        evidence_rows = []
        for dotted_key in verified_fields:
            value = self._lookup_dotted(document_json, dotted_key)
            evidence_rows.append(
                {
                    "field": dotted_key,
                    "value": value,
                    "confirmed": value is not None,
                    "confirmed_at": now_iso(),
                    "confirmed_by": confirmed_by,
                }
            )

        if evidence_rows:
            existing = list(document_json.get("verified_evidence") or [])
            document_json["verified_evidence"] = existing + evidence_rows

        document_json["review_status"] = "confirmed"
        if note:
            suggestions = list(document_json.get("inferred_suggestions") or [])
            suggestions.append(f"Manual confirmation note: {note}")
            document_json["inferred_suggestions"] = suggestions
        document_json["confirmed_at"] = now_iso()
        document_json["confirmed_by"] = confirmed_by

        quality_json["verified"] = True
        quality_json["needs_manual_review"] = False
        quality_json["verified_at"] = now_iso()
        quality_json["verified_by"] = confirmed_by
        if note:
            notes = list(quality_json.get("issues") or [])
            notes.append(f"Manual confirmation note: {note}")
            quality_json["issues"] = notes

        manifest["status"] = "confirmed"
        manifest["confirmed_at"] = now_iso()
        manifest["confirmed_by"] = confirmed_by
        manifest["updated_at"] = now_iso()

        write_json(document_json_path, document_json)
        write_json(quality_json_path, quality_json)
        write_json(manifest_path, manifest)

        self._append_summary_confirmation(doc_root=doc_root, note=note, confirmed_by=confirmed_by, fields=evidence_rows)

        return {
            "document_path": str(doc_root),
            "status": manifest["status"],
            "confirmed_fields": evidence_rows,
        }

    @staticmethod
    def _lookup_dotted(payload: dict[str, Any], dotted_key: str) -> Any:
        current: Any = payload
        for part in dotted_key.split("."):
            if not isinstance(current, dict) or part not in current:
                return None
            current = current[part]
        return current

    @staticmethod
    def _append_summary_confirmation(
        *, doc_root: Path, note: str, confirmed_by: str, fields: list[dict[str, Any]]
    ) -> None:
        summary_path = doc_root / "summary" / "summary.md"
        base_text = summary_path.read_text(encoding="utf-8") if summary_path.exists() else "# Summary\n"

        lines = [
            "",
            "## Manual Confirmation",
            f"- Confirmed by: {confirmed_by}",
            f"- Confirmed at: {now_iso()}",
        ]
        if fields:
            lines.append("- Fields confirmed:")
            for row in fields:
                marker = "ok" if row.get("confirmed") else "missing"
                lines.append(f"  - [{marker}] {row['field']}: {row.get('value')}")
        if note:
            lines.append(f"- Note: {note}")

        summary_path.write_text(base_text.rstrip() + "\n" + "\n".join(lines) + "\n", encoding="utf-8")
