import os, json, glob, shutil
from typing import Optional, Any
from urllib.parse import quote
from lib_py.agents.base import BaseAgentAdapter, DiscoveryContext
from lib_py.verify_session import workspace_key


class GrokAgentAdapter(BaseAgentAdapter):
    @property
    def name(self) -> str:
        return 'grok'

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

    @property
    def ready_tokens(self) -> str:
        return 'Grok|xAI|Assistant|❯|>>>'

    @property
    def exit_key(self) -> str:
        return '/exit'

    @property
    def delegate_agent_key(self) -> str:
        return 'grok-build'

    @property
    def identity_cache_fields(self) -> tuple:
        return ('session_id', 'session_jsonl')

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

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

    @property
    def input_rule_pattern(self) -> str:
        return '─{10,}'

    def _ws_dir(self, ctx: DiscoveryContext) -> str:
        return quote(os.path.realpath(ctx.cwd), safe='')

    def artifact_path(self, uuid: str, ctx: DiscoveryContext) -> str:
        return f"{ctx.home_dir}/.grok/sessions/{self._ws_dir(ctx)}/{uuid}/chat_history.jsonl"

    def verify_artifact(self, uuid: str, ctx: DiscoveryContext) -> bool:
        path = self.artifact_path(uuid, ctx)
        if not os.path.exists(path):
            return False
        if ctx.epoch and os.path.getmtime(path) < ctx.epoch:
            return False
        try:
            valid_session = False
            found_cwd = None
            with open(path) as f:
                for _ in range(50):
                    line = f.readline()
                    if not line:
                        break
                    line = line.strip()
                    if not line:
                        continue
                    try:
                        payload = json.loads(line)
                        if payload.get("session_id") == uuid or payload.get("sessionId") == uuid:
                            valid_session = True
                        if payload.get("cwd"):
                            found_cwd = payload.get("cwd")
                            break
                    except Exception:
                        pass
            if not valid_session and found_cwd is None:
                # Directory path itself encodes the workspace and session UUID
                valid_session = os.path.isdir(os.path.dirname(path))
            if not valid_session:
                return False
            if found_cwd and workspace_key(found_cwd) != workspace_key(ctx.cwd):
                return False
        except Exception:
            return False
        return True

    def purge_artifacts(self, uuid: str, ctx: DiscoveryContext) -> list:
        purged = []
        sess_dir = os.path.dirname(self.artifact_path(uuid, ctx))
        if os.path.isdir(sess_dir):
            shutil.rmtree(sess_dir, ignore_errors=True)
            purged.append(sess_dir)
        elif os.path.exists(self.artifact_path(uuid, ctx)):
            os.remove(self.artifact_path(uuid, ctx))
            purged.append(self.artifact_path(uuid, ctx))
        return purged

    def spawn_spec(self, binary: str, session_uuid: str = "", use_wrapper: bool = False) -> str:
        if session_uuid:
            return f"{binary} --session-id {session_uuid} --permission-mode bypassPermissions"
        return f"{binary} --permission-mode bypassPermissions"

    def resume_spec(self, binary: str, session_uuid: str, materialized: bool = False) -> str:
        if materialized and session_uuid:
            return f"{binary} --resume {session_uuid} --permission-mode bypassPermissions"
        if session_uuid:
            return f"{binary} --session-id {session_uuid} --permission-mode bypassPermissions"
        return f"{binary} --permission-mode bypassPermissions"

    def auth_ok(self, run_cmd: Optional[Any] = None) -> bool:
        if os.environ.get("XAI_API_KEY"):
            return True
        home = os.environ.get("HOME_DIR") or os.environ.get("HOME") or os.path.expanduser("~")
        return os.path.exists(f"{home}/.grok/auth.json")

    def discover(self, ctx: DiscoveryContext) -> list:
        root = f"{ctx.home_dir}/.grok/sessions/{self._ws_dir(ctx)}"
        if not os.path.isdir(root):
            return []
        entries = [d for d in glob.glob(f"{root}/*") if os.path.isdir(d)]
        entries.sort(key=os.path.getmtime, reverse=True)
        candidates = []
        for d in entries:
            cand = os.path.basename(d)
            if cand and self.verify_artifact(cand, ctx):
                candidates.append(cand)
        return candidates
