"""CLI for ORO SDK — submit agents to the ORO Bittensor Subnet.

Usage:
    oro submit --agent-name "my-agent" --agent-file agent.py
    oro submit --wallet-name my-miner --agent-name "v2" --agent-file agent.py
"""

from __future__ import annotations

import argparse
import os
import sys
from pathlib import Path

DEFAULT_BASE_URL = "https://api.oroagents.com"


def _submit(args: argparse.Namespace) -> None:
    """Handle the 'submit' subcommand."""
    try:
        from bittensor_wallet import Wallet
    except ImportError:
        print(
            "Error: bittensor-wallet is required for submission.\nInstall it with: pip install oro-sdk[bittensor]",
            file=sys.stderr,
        )
        sys.exit(1)

    from .api.miner import submit_agent
    from .bittensor_auth import BittensorAuthClient
    from .chutes_auth import ChutesAuthError, load_cached_tokens, start_auth_flow
    from .models.body_submit_agent import BodySubmitAgent
    from .models.submit_agent_response import SubmitAgentResponse
    from .types import UNSET, File

    agent_file: Path = args.agent_file
    if not agent_file.exists():
        print(f"Error: Agent file not found: {agent_file}", file=sys.stderr)
        sys.exit(1)

    # Load wallet and verify hotkey is accessible
    try:
        wallet = Wallet(name=args.wallet_name, hotkey=args.wallet_hotkey)
        hotkey_address = wallet.hotkey.ss58_address
    except Exception as e:
        print(f"Error loading wallet '{args.wallet_name}': {e}", file=sys.stderr)
        print(
            "\nMake sure you have a Bittensor wallet set up:\n"
            "  btcli wallet new_coldkey --wallet.name default\n"
            "  btcli wallet new_hotkey --wallet.name default --wallet.hotkey default",
            file=sys.stderr,
        )
        sys.exit(1)

    print(f"Wallet:  {wallet.name} ({hotkey_address})")
    print(f"Agent:   {args.agent_name}")
    print(f"File:    {agent_file} ({agent_file.stat().st_size:,} bytes)")
    print(f"Backend: {args.base_url}")
    print()

    # Resolve Chutes refresh token (required for miner-funded inference).
    # Resolution order: --chutes-token flag > cached ~/.oro/chutes_tokens.json > interactive OAuth
    chutes_refresh_token = None
    if args.chutes_token:
        chutes_refresh_token = args.chutes_token
    else:
        cached = load_cached_tokens()
        if cached and cached.get("refresh_token"):
            chutes_refresh_token = cached["refresh_token"]
            print("Using cached Chutes token from ~/.oro/chutes_tokens.json")
        else:
            try:
                tokens = start_auth_flow()
            except ChutesAuthError as e:
                print(f"Error: {e}", file=sys.stderr)
                sys.exit(1)
            chutes_refresh_token = tokens.get("refresh_token")

    if not chutes_refresh_token:
        print("Error: Failed to obtain Chutes refresh token.", file=sys.stderr)
        sys.exit(1)

    print("Chutes: token will be included in submission")
    print()

    client = BittensorAuthClient(base_url=args.base_url, wallet=wallet)

    body = BodySubmitAgent(
        agent_name=args.agent_name,
        file=File(
            payload=agent_file.read_bytes(),
            file_name=agent_file.name,
            mime_type="text/x-python",
        ),
        chutes_refresh_token=chutes_refresh_token,
    )

    response = submit_agent.sync_detailed(client=client, body=body)
    result = response.parsed

    if isinstance(result, SubmitAgentResponse):
        print(f"Status:  {result.admission_status.value}")
        if not isinstance(result.agent_version_id, type(UNSET)) and result.agent_version_id:
            print(f"Version: {result.agent_version_id}")
        if not isinstance(result.message, type(UNSET)) and result.message:
            print(f"Message: {result.message}")
        if not isinstance(result.admission_reason, type(UNSET)) and result.admission_reason:
            print(f"Reason:  {result.admission_reason.value}")
        if not isinstance(result.next_allowed_at, type(UNSET)) and result.next_allowed_at:
            print(f"Next allowed at: {result.next_allowed_at}")
    elif result is not None:
        # Parsed error model from the SDK (400, 413, 422, 429, 503)
        detail = getattr(result, "detail", None) or getattr(result, "message", None) or str(result)
        print(f"Error: {detail}", file=sys.stderr)
        sys.exit(1)
    else:
        # Unparsed error (401, 403, etc.) — try to extract detail from raw response
        import json

        try:
            body = json.loads(response.content)
            detail = body.get("detail", body.get("message", response.content.decode()))
        except (json.JSONDecodeError, UnicodeDecodeError):
            detail = response.content.decode(errors="replace")
        print(f"Error (HTTP {response.status_code}): {detail}", file=sys.stderr)
        sys.exit(1)


def main() -> None:
    parser = argparse.ArgumentParser(
        prog="oro",
        description="ORO SDK CLI — tools for the ORO Bittensor Subnet",
    )
    subparsers = parser.add_subparsers(dest="command")

    # oro submit
    submit_parser = subparsers.add_parser(
        "submit",
        help="Submit an agent for evaluation",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""\
Examples:
    oro submit --agent-name "my-agent" --agent-file agent.py
    oro submit --wallet-name my-miner --agent-name "v2" --agent-file agent.py
    oro submit --base-url http://localhost:8000 --agent-name "test" --agent-file agent.py
""",
    )
    submit_parser.add_argument(
        "--wallet-name",
        default="default",
        help="Bittensor wallet name (default: 'default')",
    )
    submit_parser.add_argument(
        "--wallet-hotkey",
        default="default",
        help="Bittensor hotkey name (default: 'default')",
    )
    submit_parser.add_argument(
        "--agent-name",
        required=True,
        help="Name for the agent (unique per miner)",
    )
    submit_parser.add_argument(
        "--agent-file",
        required=True,
        type=Path,
        help="Path to the agent Python file",
    )
    submit_parser.add_argument(
        "--base-url",
        default=os.environ.get("ORO_API_URL", DEFAULT_BASE_URL),
        help=f"Backend API URL (default: $ORO_API_URL or {DEFAULT_BASE_URL})",
    )
    submit_parser.add_argument(
        "--chutes-token",
        default=None,
        help="Explicit Chutes OAuth refresh token (skips interactive auth)",
    )

    args = parser.parse_args()

    if args.command is None:
        parser.print_help()
        sys.exit(1)

    if args.command == "submit":
        _submit(args)


if __name__ == "__main__":
    main()
