from __future__ import annotations

from collections.abc import Mapping
from dataclasses import dataclass, fields
from typing import Any

from agents.exceptions import UserError


@dataclass(frozen=True)
class CodexOptions:
    # Optional absolute path to the codex CLI binary.
    codex_path_override: str | None = None
    # Override OpenAI base URL for the Codex CLI process.
    base_url: str | None = None
    # API key passed to the Codex CLI (CODEX_API_KEY).
    api_key: str | None = None
    # Environment variables for the Codex CLI process (do not inherit os.environ).
    env: Mapping[str, str] | None = None
    # StreamReader byte limit used for Codex subprocess stdout/stderr pipes.
    codex_subprocess_stream_limit_bytes: int | None = None


def coerce_codex_options(
    options: CodexOptions | Mapping[str, Any] | None,
) -> CodexOptions | None:
    if options is None or isinstance(options, CodexOptions):
        return options
    if not isinstance(options, Mapping):
        raise UserError("CodexOptions must be a CodexOptions or a mapping.")

    allowed = {field.name for field in fields(CodexOptions)}
    unknown = set(options.keys()) - allowed
    if unknown:
        raise UserError(f"Unknown CodexOptions field(s): {sorted(unknown)}")

    return CodexOptions(**dict(options))
