from __future__ import annotations

import json
import sys
from io import StringIO
from unittest.mock import patch

from oasyce.cli import main


def run_cli(*argv: str):
    old_argv = sys.argv
    old_stdout = sys.stdout
    old_stderr = sys.stderr
    sys.stdout = StringIO()
    sys.stderr = StringIO()
    exit_code = 0
    try:
        sys.argv = ["oas"] + list(argv)
        main()
    except SystemExit as exc:
        exit_code = exc.code if isinstance(exc.code, int) else (1 if exc.code else 0)
    finally:
        stdout = sys.stdout.getvalue()
        stderr = sys.stderr.getvalue()
        sys.argv = old_argv
        sys.stdout = old_stdout
        sys.stderr = old_stderr
    return exit_code, stdout, stderr


def test_agent_quickstart_json_success():
    payload = {
        "ok": True,
        "running": True,
        "trust_level": 1,
        "auto_threshold": 10.0,
        "data_ingress": "datavault",
        "config": {
            "enabled": True,
            "interval_hours": 24,
            "scan_paths": ["~/Documents"],
            "auto_register": True,
            "auto_trade": False,
            "trade_tags": [],
            "trade_max_spend": 10.0,
        },
        "summary": {
            "mode": "autonomous_v1",
            "data_ingress": "datavault",
            "auto_register": True,
            "auto_trade": False,
            "scan_paths": ["~/Documents"],
            "trade_tags": [],
            "trade_max_spend": 10.0,
            "trust_level": 1,
            "auto_threshold": 10.0,
        },
    }
    with (
        patch("oasyce.cli._maybe_check_for_update"),
        patch("oasyce.cli._maybe_auto_update"),
        patch("oasyce.services.autonomy_service.quickstart_autonomy_payload", return_value=payload),
    ):
        code, out, err = run_cli(
            "agent",
            "quickstart",
            "--scan-paths",
            "~/Documents",
            "--json",
        )

    assert code == 0
    assert json.loads(out)["ok"] is True


def test_agent_quickstart_json_failure_exits_nonzero():
    with (
        patch("oasyce.cli._maybe_check_for_update"),
        patch("oasyce.cli._maybe_auto_update"),
        patch(
            "oasyce.services.autonomy_service.quickstart_autonomy_payload",
            return_value={"ok": False, "error": "Public beta gate failed."},
        ),
    ):
        code, out, err = run_cli(
            "agent",
            "quickstart",
            "--scan-paths",
            "~/Documents",
            "--json",
        )

    assert code == 1
    assert json.loads(out)["ok"] is False


def test_mandate_status_json():
    payload = {
        "current": {
            "profile": "balanced",
            "objective": "grow a durable, versioned portfolio under safe defaults",
            "review_mode": "sensitive_only",
            "trade_mode": "disabled",
            "trade_tags": [],
            "trade_max_spend": 10.0,
            "trust_level": 1,
            "auto_threshold": 10.0,
        },
        "available_profiles": [],
    }
    with (
        patch("oasyce.cli._maybe_check_for_update"),
        patch("oasyce.cli._maybe_auto_update"),
        patch("oasyce.services.mandate_service.mandate_payload", return_value=payload),
    ):
        code, out, err = run_cli("mandate", "status", "--json")

    assert code == 0
    assert json.loads(out)["current"]["profile"] == "balanced"


def test_mandate_apply_profile_json():
    with (
        patch("oasyce.cli._maybe_check_for_update"),
        patch("oasyce.cli._maybe_auto_update"),
        patch(
            "oasyce.services.mandate_service.set_mandate_profile",
            return_value=type(
                "_Mandate",
                (),
                {
                    "to_dict": lambda self: {
                        "profile": "cashflow",
                        "objective": "objective",
                        "review_mode": "sensitive_only",
                        "trade_mode": "budgeted",
                        "trade_tags": ["data"],
                        "trade_max_spend": 20.0,
                    },
                    "profile": "cashflow",
                    "objective": "objective",
                    "review_mode": "sensitive_only",
                    "trade_mode": "budgeted",
                    "trade_tags": ["data"],
                    "trade_max_spend": 20.0,
                },
            )(),
        ),
        patch("oasyce.services.scheduler.get_scheduler", return_value=object()),
        patch("oasyce.services.inbox.ConfirmationInbox", return_value=object()),
        patch(
            "oasyce.services.mandate_service.apply_mandate_to_runtime",
            return_value={
                "changed": True,
                "auto_trade": True,
                "trade_tags": ["data"],
                "trade_max_spend": 20.0,
                "trust_level": 1,
                "auto_threshold": 10.0,
            },
        ),
    ):
        code, out, err = run_cli("mandate", "apply-profile", "cashflow", "--json")

    assert code == 0
    assert json.loads(out)["current"]["profile"] == "cashflow"
