from pathlib import Path

import pytest

from govcrawler.config import registry
from govcrawler.config.toggle import list_sites, set_enabled


SEED = """\
# leading comment preserved
site_id: demo
site_name: demo site
base_url: https://demo.example.com
enabled: true   # inline comment
respect_robots: true
columns:
  - column_id: c1
    name: 栏目一
    list_url: https://demo.example.com/a/
    detail:
      title: h1::text
      publish_time: span.time::text
      source: ""
      content: div.content
    schedule: "0 2 * * *"
    enabled: true
  - column_id: c2
    name: 栏目二
    list_url: https://demo.example.com/b/
    detail:
      title: h1::text
      publish_time: span.time::text
      source: ""
      content: div.content
    schedule: "0 3 * * *"
    enabled: true
"""


@pytest.fixture
def site_root(tmp_path, monkeypatch):
    root = tmp_path / "sites"
    root.mkdir()
    (root / "demo.yaml").write_text(SEED, encoding="utf-8")
    monkeypatch.setattr(registry, "DEFAULT_CONFIG_DIR", root)
    registry.reload()
    # toggle module reads DEFAULT_CONFIG_DIR at call time
    from govcrawler.config import toggle as toggle_mod
    monkeypatch.setattr(toggle_mod, "DEFAULT_CONFIG_DIR", root)
    yield root


def test_toggle_site_disable_writes_yaml(site_root):
    path = set_enabled("demo", enabled=False, root=site_root)
    text = Path(path).read_text(encoding="utf-8")
    assert "enabled: false" in text
    # comments preserved
    assert "leading comment preserved" in text
    assert "inline comment" in text


def test_toggle_site_reload_registry_reflects_change(site_root):
    set_enabled("demo", enabled=False, root=site_root)
    cfg = registry.get_site_config("demo")
    assert cfg is not None
    assert cfg.enabled is False


def test_toggle_column_only_flips_target(site_root):
    set_enabled("demo", column_id="c2", enabled=False, root=site_root)
    cfg = registry.get_site_config("demo")
    c1 = cfg.get_column("c1")
    c2 = cfg.get_column("c2")
    assert c1.enabled is True
    assert c2.enabled is False
    # site itself still enabled
    assert cfg.enabled is True


def test_toggle_reenable_roundtrip(site_root):
    set_enabled("demo", column_id="c1", enabled=False, root=site_root)
    set_enabled("demo", column_id="c1", enabled=True, root=site_root)
    assert registry.get_site_config("demo").get_column("c1").enabled is True


def test_toggle_unknown_site_raises(site_root):
    with pytest.raises(FileNotFoundError):
        set_enabled("does_not_exist", enabled=False, root=site_root)


def test_toggle_unknown_column_raises(site_root):
    with pytest.raises(KeyError):
        set_enabled("demo", column_id="c99", enabled=False, root=site_root)


def test_list_sites_reports_status(site_root):
    set_enabled("demo", column_id="c2", enabled=False, root=site_root)
    summary = list_sites(root=site_root)
    assert len(summary) == 1
    site = summary[0]
    assert site["site_id"] == "demo"
    assert site["enabled"] is True
    cols = {c["column_id"]: c["enabled"] for c in site["columns"]}
    assert cols == {"c1": True, "c2": False}


def test_scheduler_skips_disabled_column(site_root, monkeypatch):
    """After disabling a column, build_scheduler registers only enabled jobs."""
    set_enabled("demo", column_id="c2", enabled=False, root=site_root)
    from govcrawler import scheduler

    sched = scheduler.build_scheduler(lambda s, c: None)
    job_ids = {j.id for j in sched.get_jobs()}
    assert "demo.c1" in job_ids
    assert "demo.c2" not in job_ids


def test_scheduler_skips_disabled_site(site_root, monkeypatch):
    set_enabled("demo", enabled=False, root=site_root)
    from govcrawler import scheduler

    sched = scheduler.build_scheduler(lambda s, c: None)
    assert all(not j.id.startswith("demo.") for j in sched.get_jobs())
