# base.py — BaseAgentAdapter abstract base class, SpawnSpec, and DiscoveryContext

import os, json, sqlite3
from typing import Optional, Dict, Any, List
from lib_py.paths import resolve_home
from lib_py.verify_session import verify_session_uuid, workspace_key

class SpawnSpec:
    def __init__(self, agent_name: str, session_name: str, command: str, env: Optional[Dict[str, str]] = None):
        self.agent_name = agent_name
        self.session_name = session_name
        self.command = command
        self.env = env or {}

class DiscoveryContext:
    def __init__(self, workspace: str, agent_name: str = "", home_dir: Optional[str] = None,
                 claude_dir: Optional[str] = None, epoch: int = 0,
                 row: Optional[Dict[str, Any]] = None, mode: str = "discover"):
        self.workspace = workspace
        self.agent_name = agent_name
        self.home_dir = resolve_home(home_dir)
        self.claude_dir = claude_dir or os.environ.get("CLAUDE_PROJECT_DIR", f"{self.home_dir}/.claude/projects")
        self.epoch = epoch
        self.row = row or {}
        self.mode = mode

    @property
    def ws_key(self) -> str:
        return workspace_key(self.workspace)

    @property
    def cwd(self) -> str:
        return (self.row.get("pane", {}).get("cwd", "") if isinstance(self.row, dict) else "") or self.workspace

class BaseAgentAdapter:
    @property
    def name(self) -> str:
        raise NotImplementedError

    @property
    def own_key(self) -> str:
        raise NotImplementedError

    @property
    def ready_tokens(self) -> str:
        raise NotImplementedError

    @property
    def exit_key(self) -> str:
        raise NotImplementedError

    @property
    def delegate_agent_key(self) -> str:
        raise NotImplementedError

    @property
    def identity_cache_fields(self) -> tuple:
        """agent_identities 캐시의 에이전트별 필드명.
        B-10(Option A)로 캐시 읽기 경로가 제거되어 현재 생산 소비자는 0건이지만,
        캐시 쓰기 경로가 도입되면 즉시 필요한 유일한 스키마 기술이므로 존치한다.
        임의 삭제 금지 — 삭제 시 4개 어댑터에 필드명을 다시 흩뿌려야 한다."""
        raise NotImplementedError

    @property
    def input_prompt(self) -> Optional[str]:
        return None

    @property
    def input_placeholder(self) -> Optional[str]:
        return None

    @property
    def input_rule_pattern(self) -> Optional[str]:
        return None

    @property
    def modal_tokens(self) -> Optional[str]:
        return None

    @property
    def strong_ready_tokens(self) -> str:
        return self.ready_tokens

    @property
    def weak_ready_tokens(self) -> str:
        return ''

    def derive_session_name(self, slug: str, role: str = "creator") -> str:
        r = role.lower()
        return f"{slug}-{r}-{self.name}"

    def matches_session_name(self, session_name: str) -> bool:
        for r in ('creator', 'planner', 'reviewer'):
            if session_name.endswith(f"-{r}-{self.name}"):
                return True
        return session_name.endswith(f"-{self.name}")

    def verify_session(self, ws: str, uuid: str, row: Optional[Dict[str, Any]] = None, mode: str = "discover") -> bool:
        return verify_session_uuid(ws, self.name, uuid, row=row, mode=mode)

    def artifact_path(self, uuid: str, ctx: DiscoveryContext) -> str:
        raise NotImplementedError

    def verify_artifact(self, uuid: str, ctx: DiscoveryContext) -> bool:
        raise NotImplementedError

    def purge_artifacts(self, uuid: str, ctx: DiscoveryContext) -> list:
        raise NotImplementedError

    def spawn_spec(self, binary: str, session_uuid: str = "", use_wrapper: bool = False) -> str:
        raise NotImplementedError

    def resume_spec(self, binary: str, session_uuid: str, materialized: bool = False) -> str:
        raise NotImplementedError

    def auth_ok(self, run_cmd: Optional[Any] = None) -> bool:
        raise NotImplementedError

    def discover(self, ctx: DiscoveryContext) -> list:
        raise NotImplementedError
