"""
Per-repo fix cache. Records selector corrections learned during run_and_fix_tests
so future test generations can reuse known-working selectors.

Cache location: ~/.maeris/repos/<repo_hash>/fix_cache.json
"""
import hashlib
import json
import os
import time
from dataclasses import dataclass, field, asdict
from pathlib import Path
from typing import Optional
import structlog

logger = structlog.get_logger()

_CACHE_VERSION = 1


@dataclass
class SelectorFix:
    broken: str
    working: str
    action: str
    context: str  # step description / name
    page_url: str = ""
    confirmed_passes: int = 1
    fixed_at: float = field(default_factory=time.time)


@dataclass
class FixCacheEntry:
    version: int = _CACHE_VERSION
    repo_hash: str = ""
    selector_fixes: list = field(default_factory=list)  # list of SelectorFix dicts


class RepoFixCache:
    def __init__(self, repo_root: str):
        self.repo_root = os.path.abspath(repo_root)
        self._hash = hashlib.sha256(self.repo_root.encode()).hexdigest()[:16]
        self._cache_path = Path.home() / ".maeris" / "repos" / self._hash / "fix_cache.json"
        self._entry: Optional[FixCacheEntry] = None

    def load(self) -> FixCacheEntry:
        if self._entry is not None:
            return self._entry
        try:
            if self._cache_path.exists():
                data = json.loads(self._cache_path.read_text(encoding="utf-8"))
                if data.get("version") == _CACHE_VERSION:
                    self._entry = FixCacheEntry(
                        version=data["version"],
                        repo_hash=data.get("repo_hash", ""),
                        selector_fixes=data.get("selector_fixes", []),
                    )
                    logger.info("fix_cache.loaded", fixes=len(self._entry.selector_fixes))
                    return self._entry
        except Exception as e:
            logger.warning("fix_cache.load_failed", error=str(e))
        self._entry = FixCacheEntry(version=_CACHE_VERSION, repo_hash=self._hash)
        return self._entry

    def save(self) -> None:
        if self._entry is None:
            return
        try:
            self._cache_path.parent.mkdir(parents=True, exist_ok=True)
            self._cache_path.write_text(
                json.dumps(asdict(self._entry), indent=2), encoding="utf-8"
            )
            logger.info("fix_cache.saved", fixes=len(self._entry.selector_fixes))
        except Exception as e:
            logger.warning("fix_cache.save_failed", error=str(e))

    def record_fix(
        self,
        broken: str,
        working: str,
        action: str,
        context: str,
        page_url: str = "",
    ) -> None:
        """Record a selector fix. Increments confirmed_passes if already known."""
        entry = self.load()
        for fix in entry.selector_fixes:
            if fix.get("broken") == broken and fix.get("working") == working:
                fix["confirmed_passes"] = fix.get("confirmed_passes", 1) + 1
                fix["fixed_at"] = time.time()
                self.save()
                return
        entry.selector_fixes.append(asdict(SelectorFix(
            broken=broken,
            working=working,
            action=action,
            context=context,
            page_url=page_url,
        )))
        self.save()
        logger.info("fix_cache.new_fix", broken=broken[:50], working=working[:50])

    def get_prompt_block(self) -> str:
        """Return a prompt block of verified/broken selectors for injection into generation."""
        entry = self.load()
        if not entry.selector_fixes:
            return ""
        lines = [
            "=== VERIFIED SELECTOR FIXES FROM PREVIOUS TEST RUNS ===",
            "These selectors are confirmed working. Use them exactly — do NOT modify.",
            "",
        ]
        for fix in entry.selector_fixes:
            working = fix.get("working", "")
            broken = fix.get("broken", "")
            action = fix.get("action", "")
            context = fix.get("context", "")
            page = fix.get("page_url", "")
            passes = fix.get("confirmed_passes", 1)
            lines.append(
                f"  WORKING: {working}  →  {action}  ({context})"
                + (f" @ {page}" if page else "")
                + f"  [passes: {passes}]"
            )
            if broken:
                lines.append(f"  BROKEN (do not use): {broken}")
            lines.append("")
        lines.append("=== END VERIFIED SELECTORS ===")
        return "\n".join(lines)
