from __future__ import annotations

from typing import Any, Literal, NotRequired, TypedDict

SessionType = Literal["browser", "sandbox"]
PricingModel = Literal["free", "usage_based", "subscription"]
AccountRole = Literal["owner", "admin", "member"]


class Endpoints(TypedDict):
    control: str
    video: NotRequired[str]


class SessionInfo(TypedDict):
    id: str
    created_at: str
    status: str
    session_type: str
    endpoints: Endpoints
    workspace_id: NotRequired[str | None]
    active_connection_leases: NotRequired[int | None]
    persistence: NotRequired[bool | None]


class ListSessionsResponse(TypedDict):
    sessions: list[SessionInfo]
    total: int


class CreateSessionRequest(TypedDict, total=False):
    session_type: SessionType
    workspace: str
    ephemeral: bool
    image: str | None
    proxy: str | None
    github_repo: str | None
    env: dict[str, str]


class BrowserCdpVersionInfo(TypedDict, total=False):
    Browser: str
    Protocol_Version: str
    User_Agent: str
    V8_Version: str
    WebKit_Version: str
    webSocketDebuggerUrl: str


class BrowserCdpTargetInfo(TypedDict, total=False):
    id: str
    type: str
    title: str
    url: str
    webSocketDebuggerUrl: str


class SandboxExecResponse(TypedDict, total=False):
    kind: str
    status: str
    session_id: str
    workspace: str
    workspace_id: str
    ephemeral: bool
    command: str
    background: bool
    command_id: str
    pid: int
    exit_code: int
    output: str
    output_truncated: bool


class SessionRuntimeProxyInfo(TypedDict, total=False):
    all_proxy: str
    http_proxy: str
    https_proxy: str
    no_proxy: str


class SessionRuntimeToolsInfo(TypedDict, total=False):
    node: str
    python3: str
    git: str
    bun: str
    cargo: str
    rustc: str
    go: str


class SessionRuntimeToolVersionsInfo(TypedDict, total=False):
    node: str
    python3: str
    git: str
    bun: str
    cargo: str
    rustc: str
    go: str


class SessionRuntimeChaserInfo(TypedDict, total=False):
    session_id: str
    workspace_id: str
    workspace_root: str
    runtime_env: str
    agent_brief_path: str
    toolchain_root: str
    toolchain_attached: bool
    agent_impl: str
    image: str


class SessionRuntimeInfo(TypedDict, total=False):
    cwd: str
    home: str
    user: str
    shell: str
    path: str
    path_entries: list[str]
    term: str
    lang: str
    chaser_mode: str
    chaser_exec: bool
    chaser_agent: bool
    workspace_root_present: bool
    proxy: SessionRuntimeProxyInfo
    chaser: SessionRuntimeChaserInfo
    tools: SessionRuntimeToolsInfo
    tool_versions: SessionRuntimeToolVersionsInfo


class SessionSelfTestResponse(TypedDict, total=False):
    kind: str
    status: str
    session_id: str
    workspace_id: str
    runtime: SessionRuntimeInfo


class SessionCommandInfo(TypedDict, total=False):
    command_id: str
    session_id: str
    status: str
    pid: int
    exit_code: int
    command: str
    cwd: str
    user: str
    started_at_epoch: int
    finished_at_epoch: int
    output_bytes: int
    output: str
    output_truncated: bool


class UploadFileResponse(TypedDict):
    path: str
    size: int


class WorkspaceInfo(TypedDict, total=False):
    id: str
    name: str
    image: str
    template: bool
    source_workspace_id: str
    github_repo: str
    assistant_home: bool
    last_session_id: str
    active_session_id: str
    session_type: str
    status: str
    persistence: bool
    created_at: str
    node_endpoint: str


class WorkspaceNameResponse(TypedDict, total=False):
    id: str
    name: str | None


class WorkspaceTemplateResponse(TypedDict):
    id: str
    template: bool


class WorkspaceSnapshotInfo(TypedDict, total=False):
    id: str
    workspace_id: str
    used_bytes: int
    created_at: str
    restored_at: str


class GithubRepoInfo(TypedDict):
    name: str
    installation_id: int
    account_login: str


class GithubRepositoriesResponse(TypedDict, total=False):
    repositories: list[GithubRepoInfo]
    install_url: str | None


class CreateWorkspaceRequest(TypedDict, total=False):
    name: str | None
    session_type: SessionType | None
    image: str | None
    clone_from: str | None
    template: bool | None


class ImportWorkspaceRequest(TypedDict, total=False):
    repo: str
    name: str | None


class DevcontainerBootstrap(TypedDict, total=False):
    path: str
    image: str | None
    dockerfile: str | None
    workspace_folder: str | None
    post_create_command: str | None
    forward_ports: list[int]


class ImportWorkspaceResponse(TypedDict, total=False):
    workspace: WorkspaceInfo
    github_repo: str
    private: bool
    default_branch: str | None
    devcontainer: DevcontainerBootstrap | None


class BulkTerminateFailure(TypedDict):
    id: str
    code: str
    message: str


class BulkTerminateResponse(TypedDict):
    terminated: list[str]
    failed: list[BulkTerminateFailure]


class BulkTerminateRequest(TypedDict, total=False):
    ids: list[str]
    workspaces: list[str]
    all: bool
    session_type: SessionType
    force: bool


class BulkDeleteWorkspaceItem(TypedDict, total=False):
    id: str
    deleted: bool
    error: str


class BulkDeleteWorkspacesResponse(TypedDict):
    requested: int
    deleted: int
    failed: int
    results: list[BulkDeleteWorkspaceItem]


class BulkDeleteWorkspacesRequest(TypedDict, total=False):
    ids: list[str]
    all: bool
    force: bool


class ApiKeyInfo(TypedDict, total=False):
    id: str
    key_prefix: str
    name: str
    scopes: list[str]
    full_access: bool
    created_at: str
    last_used_at: str
    revoked: str


class CreateApiKeyResponse(TypedDict, total=False):
    id: str
    key: str
    key_prefix: str
    name: str
    scopes: list[str]
    full_access: bool


class SshKeyInfo(TypedDict, total=False):
    id: str
    name: str
    public_key: str
    fingerprint: str
    created_at: str
    last_used_at: str


class AccountInfo(TypedDict):
    id: str
    kind: str
    name: str
    role: str
    personal: bool
    created_at: str


class AccountMemberInfo(TypedDict, total=False):
    user_id: str
    email: str
    name: str
    role: str
    owner: bool
    joined_at: str


class ServiceAccountInfo(TypedDict):
    id: str
    name: str
    created_by_user_id: str
    created_at: str
    updated_at: str
    disabled: bool


class ServiceAccountKeyInfo(TypedDict, total=False):
    id: str
    key_prefix: str
    name: str
    scopes: list[str]
    full_access: bool
    created_at: str
    last_used_at: str
    revoked: str


class CreateServiceAccountKeyResponse(TypedDict, total=False):
    service_account: ServiceAccountInfo
    id: str
    key: str
    key_prefix: str
    name: str
    scopes: list[str]
    full_access: bool


class BillingLimits(TypedDict, total=False):
    max_workspaces: int
    max_concurrency: int
    max_session_seconds: int
    allow_workspaces: bool


class BillingUsageWindow(TypedDict):
    seconds: int
    amount_micros_usd: int


class BillingSummaryResponse(TypedDict, total=False):
    pricing_model: str
    plan_code: str
    stripe_customer_id: str
    stripe_subscription_id: str
    limits: BillingLimits
    usage_price_per_hour_usd: float
    wallet_balance_micros_usd: int
    wallet_balance_usd: float
    topup_min_usd: float
    workspace_storage_used_bytes: int
    workspace_storage_cap_bytes: int
    workspace_storage_measured_workspaces: int
    workspace_storage_unresolved_workspaces: int
    usage_last_24h: BillingUsageWindow
    usage_last_30d: BillingUsageWindow


class CustomerWebhookInfo(TypedDict, total=False):
    id: str
    description: str
    url: str
    events: list[str]
    signing_secret_preview: str
    created_at: str
    updated_at: str


class CreateCustomerWebhookResponse(TypedDict):
    webhook: CustomerWebhookInfo
    signing_secret: str


class CustomerWebhookDeliveryInfo(TypedDict, total=False):
    id: str
    webhook_id: str
    event_id: str
    event_type: str
    resource_type: str
    resource_id: str
    target_url: str
    status: str
    attempts: int
    last_http_status: int
    last_error: str
    payload: Any
    delivered_at: str
    replayed_at: str
    discarded_at: str
    replayed_from_delivery_id: str
    created_at: str
    updated_at: str


class AuditEventInfo(TypedDict, total=False):
    id: str
    actor_type: str
    actor_id: str
    action: str
    resource_type: str
    resource_id: str
    status: str
    summary: str
    metadata: Any
    created_at: str


class JobInfo(TypedDict, total=False):
    id: str
    kind: str
    status: str
    input: Any
    result: Any
    created_at: str
    updated_at: str
    run_at: str
    idempotency_key: str
    error: str


class ListJobsPage(TypedDict, total=False):
    jobs: list[JobInfo]
    total: int
    limit: int
    offset: int
    has_more: bool


class JobKindSpecInfo(TypedDict, total=False):
    kind: str
    summary: str
    input_examples: list[Any]
    alias_fields: list[str]


class JobKindsInfo(TypedDict):
    worker_kinds: list[str]
    worker_kind_specs: list[JobKindSpecInfo]


class CreateJobRequest(TypedDict, total=False):
    kind: str
    input: Any
    run_at: str
    idempotency_key: str


class BrowserActionJobInput(TypedDict, total=False):
    session_id: str
    steps: list[Any]
    timeout_ms: int


class BrowserScrapeJobInput(TypedDict, total=False):
    session_id: str
    url: str
    selector: str
    all: bool
    timeout_ms: int


class SessionTerminateJobInput(TypedDict, total=False):
    session_id: str
    force: bool


class SessionBulkTerminateJobInput(TypedDict, total=False):
    ids: list[str]
    workspaces: list[str]
    all: bool
    session_type: SessionType
    force: bool


class WorkspaceDeleteJobInput(TypedDict, total=False):
    workspace: str
    force: bool


class WorkspaceBulkDeleteJobInput(TypedDict, total=False):
    ids: list[str]
    all: bool
    force: bool


class PipelineStepInput(TypedDict, total=False):
    name: str
    kind: str
    input: Any
    command: str
    timeout_ms: int


class PipelineRunJobInput(TypedDict, total=False):
    workspace: str
    steps: list[PipelineStepInput]


class GithubRunnerJobInput(TypedDict, total=False):
    repo: str
    installation_id: int
    workflow_job_id: int
    run_id: int
    labels: list[str]
    timeout_ms: int
