from __future__ import annotations

from pathlib import Path

from fastapi.testclient import TestClient

from argus.service.app import create_app


def _write_config(tmp_path: Path) -> Path:
    p = tmp_path / "cfg.yaml"
    p.write_text(
        """
ray:
  address: "http://127.0.0.1:8265"
  shared_root: "/private"
  entrypoint_num_cpus: 1
  entrypoint_resources: { worker_node: 1 }
  runtime_env: { env_vars: { PYTHONUNBUFFERED: "1" } }
service:
  api: { host: "127.0.0.1", port: 8080 }
  auth: { token_env: "MVP_INTERNAL_TOKEN" }
  sqlite: { db_path: "%(db)s" }
data:
  user_root: "%(users)s"
  sftpgo: { enabled: false }
  retention: { jobs_trash_after_days: 3, jobs_purge_after_days: 7, janitor_interval_s: 3600 }
"""
        % {"db": str(tmp_path / "mvp.sqlite3"), "users": str(tmp_path / "users")}
    )
    return p


def test_ui_routes_render_200(tmp_path, monkeypatch):
    cfg = _write_config(tmp_path)
    monkeypatch.setenv("MVP_INTERNAL_TOKEN", "admin-token")
    app = create_app(str(cfg))
    c = TestClient(app)

    for path in (
        "/ui",
        "/ui/login",
        "/ui/tasks",
        "/ui/tasks/new",
        "/ui/serving",
        "/ui/serving/new",
        "/ui/data",
        "/ui/admin",
        "/ui/tasks/any-task-id",
        "/ui/tasks/any-task-id/logs",
        "/ui/serving/any-model-key",
    ):
        r = c.get(path, allow_redirects=True)
        assert r.status_code == 200
        assert "<html" in r.text.lower()


def test_ui_contains_sidebar_links(tmp_path, monkeypatch):
    cfg = _write_config(tmp_path)
    monkeypatch.setenv("MVP_INTERNAL_TOKEN", "admin-token")
    app = create_app(str(cfg))
    c = TestClient(app)

    r = c.get("/ui/tasks")
    assert r.status_code == 200
    for link in ("/ui/tasks", "/ui/tasks/new", "/ui/serving", "/ui/data", "/ui/login", "/ui/admin"):
        assert link in r.text
    assert "Ray Dashboard" in r.text


def test_ui_task_detail_shows_ids(tmp_path, monkeypatch):
    cfg = _write_config(tmp_path)
    monkeypatch.setenv("MVP_INTERNAL_TOKEN", "admin-token")
    app = create_app(str(cfg))
    c = TestClient(app)

    task_id = "mvp3-ppo-20250101-000000-aaaa"
    r = c.get(f"/ui/tasks/{task_id}")
    assert r.status_code == 200
    assert task_id in r.text
    assert f"/ui/tasks/{task_id}/logs" in r.text
    assert "TaskSpec (YAML)" in r.text
    assert "/api/v2/tasks/" in r.text


def test_ui_new_task_contains_advanced_example_snippet(tmp_path, monkeypatch):
    cfg = _write_config(tmp_path)
    monkeypatch.setenv("MVP_INTERNAL_TOKEN", "admin-token")
    app = create_app(str(cfg))
    c = TestClient(app)

    r = c.get("/ui/tasks/new")
    assert r.status_code == 200
    # Ensure Advanced example includes required PPO micro batch override (common failure mode if omitted).
    assert "kind: advanced" in r.text
    # workload is not needed for advanced in v3.5.
    assert "# workload:" not in r.text
    assert "actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu" in r.text
    # v3.7: default rollout backend switches from sglang -> vllm.
    assert "actor_rollout_ref.rollout.name=vllm" in r.text
    # v3.6: Advanced example uses platform-injected env vars so users don't need to edit W&B project/run.
    assert "trainer.logger=${MVP_TRAINER_LOGGER}" in r.text
    assert "trainer.project_name=${MVP_WANDB_PROJECT}" in r.text
    assert "trainer.experiment_name=${MVP_WANDB_RUN}" in r.text
    assert "Model merge example" in r.text
    assert "verl.model_merger" in r.text


def test_ui_new_task_contains_evaluation_example(tmp_path, monkeypatch):
    cfg = _write_config(tmp_path)
    monkeypatch.setenv("MVP_INTERNAL_TOKEN", "admin-token")
    app = create_app(str(cfg))
    c = TestClient(app)

    r = c.get("/ui/tasks/new")
    assert r.status_code == 200
    assert "Evaluation example" in r.text
    assert "verl.trainer.main_eval" in r.text
    assert "data.path=$HOME/jobs/<RAY_SUBMISSION_ID>/outputs/<EVAL_PARQUET>.parquet" in r.text
    assert "+ray_kwargs.ray_init.address=auto" in r.text


def test_ui_login_contains_wandb_section(tmp_path, monkeypatch):
    cfg = _write_config(tmp_path)
    monkeypatch.setenv("MVP_INTERNAL_TOKEN", "admin-token")
    app = create_app(str(cfg))
    c = TestClient(app)

    r = c.get("/ui/login")
    assert r.status_code == 200
    assert "W&amp;B" in r.text
    assert "Open W&amp;B" in r.text
