"""Runs resource (includes checkpoints, resume, and fork)."""

from __future__ import annotations

from typing import TYPE_CHECKING

from .._base import BaseResource
from ..connectors import Exporter, Importer
from ..types import (
    CheckpointResponse,
    ExportConnectorSpec,
    ImportConnectorSpec,
    Run,
    RunCreate,
    RunResumeRequest,
    RunStatusResponse,
)

if TYPE_CHECKING:
    import requests

    from .._auth import Authenticator
    from .sandboxes import SandboxesResource

_SCOPE_CREATE = "AgentOrchestrator:runs:create"
_SCOPE_LIST = "AgentOrchestrator:runs:list"
_SCOPE_GET = "AgentOrchestrator:runs:get"
_SCOPE_GET_STATUS = "AgentOrchestrator:runs:get_status"
_SCOPE_GET_CHECKPOINT_CHAIN = "AgentOrchestrator:runs:get_checkpoint_chain"
_SCOPE_GET_CHECKPOINT = "AgentOrchestrator:runs:get_checkpoint"
_SCOPE_RESUME = "AgentOrchestrator:runs:resume"


class RunsResource(BaseResource):

    def __init__(
        self,
        session: requests.Session,
        base_url: str,
        sandboxes: SandboxesResource,
        authenticator: Authenticator | None = None,
    ) -> None:
        super().__init__(session, base_url, authenticator)
        self._sandboxes = sandboxes

    def _bind(self, run: Run) -> Run:
        run._resource = self
        return run

    def _convert_imports(self, imports: list[Importer]) -> list[ImportConnectorSpec]:
        return [i._to_wire() for i in imports]

    def _convert_exports(self, exports: list[Exporter]) -> list[ExportConnectorSpec]:
        return [e._to_wire() for e in exports]

    def create(
        self,
        sandbox: str,
        prompt: str,
        *,
        model: str = "gpt-5.4",
        timeout_seconds: int = 3600,
        imports: list[Importer] | None = None,
        exports: list[Exporter] | None = None,
    ) -> Run:
        agent_id = self._sandboxes._resolve_agent_id(sandbox)
        if agent_id is None:
            from ..exceptions import NotFoundError
            raise NotFoundError(f"Sandbox not found: {sandbox}")

        body = RunCreate(
            agent_id=agent_id,
            prompt=prompt,
            model=model,
            timeout_seconds=timeout_seconds,
            import_connectors=self._convert_imports(imports or []),
            export_connectors=self._convert_exports(exports or []),
        )
        resp = self._post("/runs", scope=_SCOPE_CREATE, data=body.model_dump_json())
        return self._bind(Run.model_validate(resp.json()))

    def list(self, sandbox: str | None = None) -> list[Run]:
        params: dict[str, str] = {}
        if sandbox is not None:
            agent_id = self._sandboxes._resolve_agent_id(sandbox)
            if agent_id is not None:
                params["agent_id"] = agent_id
        resp = self._get("/runs", scope=_SCOPE_LIST, params=params)
        return [self._bind(Run.model_validate(r)) for r in resp.json()]

    def get(self, run_id: str) -> Run:
        resp = self._get(f"/runs/{run_id}", scope=_SCOPE_GET)
        return self._bind(Run.model_validate(resp.json()))

    def get_status(self, run_id: str) -> RunStatusResponse:
        resp = self._get(f"/runs/{run_id}/status", scope=_SCOPE_GET_STATUS)
        return RunStatusResponse.model_validate(resp.json())

    def get_checkpoint_chain(self, run_id: str) -> list[CheckpointResponse]:
        resp = self._get(f"/runs/{run_id}/checkpoint-chain", scope=_SCOPE_GET_CHECKPOINT_CHAIN)
        return [CheckpointResponse.model_validate(c) for c in resp.json()]

    def get_checkpoint(self, run_id: str, checkpoint_id: str) -> CheckpointResponse:
        resp = self._get(f"/runs/{run_id}/checkpoints/{checkpoint_id}", scope=_SCOPE_GET_CHECKPOINT)
        return CheckpointResponse.model_validate(resp.json())

    def _fork(
        self,
        run_id: str,
        prompt: str,
        *,
        imports: list[Importer] | None = None,
        exports: list[Exporter] | None = None,
        model: str = "gpt-5.4",
        timeout_seconds: int = 3600,
    ) -> Run:
        body = RunResumeRequest(
            prompt=prompt,
            model=model,
            timeout_seconds=timeout_seconds,
            import_connectors=self._convert_imports(imports or []),
            export_connectors=self._convert_exports(exports or []),
        )
        resp = self._post(f"/runs/{run_id}/resume", scope=_SCOPE_RESUME, data=body.model_dump_json())
        return self._bind(Run.model_validate(resp.json()))
