import sys
import json
import pytest
from unittest.mock import MagicMock, patch
from pathlib import Path

from notilens import cli
from notilens.config import save_agent


@pytest.fixture(autouse=True)
def setup(tmp_path, monkeypatch):
    monkeypatch.setattr("notilens.config.CONFIG_FILE", tmp_path / ".notilens_config.json")
    monkeypatch.setattr("notilens.cli._emitter_cache", {})
    # prevent real HTTP delivery
    monkeypatch.setattr("notilens.emitter.NotiLensEmitter._deliver", MagicMock())
    yield


@pytest.fixture
def configured_agent(tmp_path, monkeypatch):
    save_agent("my-agent", "tok", "sec")


def run_cli(*args):
    with patch.object(sys, "argv", ["notilens", *args]):
        cli.main()


def test_init_saves_agent(tmp_path, monkeypatch):
    run_cli("init", "--agent", "my-agent", "--token", "tok", "--secret", "sec")
    from notilens.config import get_agent_config
    conf = get_agent_config("my-agent")
    assert conf["token"] == "tok"
    assert conf["secret"] == "sec"


def test_init_missing_args_exits():
    with pytest.raises(SystemExit):
        run_cli("init", "--agent", "my-agent")


def test_agents_command(configured_agent, capsys):
    run_cli("agents")
    out = capsys.readouterr().out
    assert "my-agent" in out


def test_remove_agent(configured_agent, capsys):
    run_cli("remove-agent", "my-agent")
    from notilens.config import get_agent_config
    assert get_agent_config("my-agent") is None


def test_task_start(configured_agent, tmp_path, monkeypatch, capsys):
    monkeypatch.setattr("notilens.state.get_state_file",
                        lambda ag, tid: tmp_path / f"{ag}_{tid}.json")
    run_cli("task.start", "--agent", "my-agent", "--task", "job1")
    out = capsys.readouterr().out
    assert "job1" in out


def test_task_complete(configured_agent, tmp_path, monkeypatch):
    sf = tmp_path / "my-agent_job1.json"
    monkeypatch.setattr("notilens.cli.get_state_file", lambda ag, tid: sf)
    from notilens.state import write_state
    write_state(sf, {"start_time": 0, "retry_count": 0, "loop_count": 0})
    run_cli("task.complete", "All done", "--agent", "my-agent", "--task", "job1")
    assert not sf.exists()


def test_task_fail_deletes_state(configured_agent, tmp_path, monkeypatch):
    sf = tmp_path / "my-agent_job1.json"
    monkeypatch.setattr("notilens.cli.get_state_file", lambda ag, tid: sf)
    from notilens.state import write_state
    write_state(sf, {"start_time": 0, "retry_count": 0, "loop_count": 0})
    run_cli("task.fail", "Crashed", "--agent", "my-agent", "--task", "job1")
    assert not sf.exists()


def test_emit_custom_event(configured_agent, tmp_path, monkeypatch):
    sf = tmp_path / "my-agent_t1.json"
    monkeypatch.setattr("notilens.state.get_state_file", lambda ag, tid: sf)
    run_cli("emit", "order.placed", "Order #1", "--agent", "my-agent", "--task", "t1")


def test_missing_agent_exits(configured_agent):
    with pytest.raises(SystemExit):
        run_cli("task.start")


def test_unconfigured_agent_exits():
    with pytest.raises(SystemExit):
        run_cli("task.start", "--agent", "ghost", "--task", "t1")


def test_version(capsys):
    run_cli("version")
    out = capsys.readouterr().out
    assert "NotiLens" in out


def test_unknown_command_prints_usage(capsys):
    run_cli("unknown_command")
    out = capsys.readouterr().out
    assert "Usage" in out


def test_parse_flags_meta():
    flags = cli.parse_flags(["--agent", "a", "--task", "t1", "--meta", "key=val"])
    assert flags["meta"]["key"] == "val"


def test_parse_flags_confidence():
    flags = cli.parse_flags(["--agent", "a", "--confidence", "0.9"])
    assert flags["confidence_score"] == pytest.approx(0.9)
