"""Tests for job YAML loader and saver."""

from datetime import datetime, timezone

from fliiq.runtime.scheduler.loader import (
    delete_job,
    load_job,
    load_jobs,
    save_job,
    update_job_state,
)
from fliiq.runtime.scheduler.models import (
    JobDefinition,
    JobState,
    TriggerConfig,
)

SAMPLE_YAML = """\
name: daily-summary
trigger:
  type: cron
  schedule: "0 9 * * *"
prompt: Summarize my emails
enabled: true
"""

SAMPLE_YAML_WITH_STATE = """\
name: daily-summary
trigger:
  type: cron
  schedule: "0 9 * * *"
prompt: Summarize my emails
_state:
  last_run_at: "2026-02-08T09:00:00+00:00"
  last_status: success
  run_count: 5
"""

INVALID_YAML = "not: [valid: job"


def test_load_job_from_yaml(tmp_path):
    path = tmp_path / "daily-summary.yaml"
    path.write_text(SAMPLE_YAML)

    job = load_job(path)
    assert job.name == "daily-summary"
    assert job.trigger.type == "cron"
    assert job.trigger.schedule == "0 9 * * *"
    assert job.prompt == "Summarize my emails"
    assert job.enabled is True


def test_save_and_load_roundtrip(tmp_path):
    job = JobDefinition(
        name="test-roundtrip",
        trigger=TriggerConfig(type="every", schedule="1h"),
        prompt="Check something",
        skills=["shell"],
    )
    save_job(job, tmp_path)
    loaded = load_job(tmp_path / "test-roundtrip.yaml")

    assert loaded.name == job.name
    assert loaded.trigger.type == job.trigger.type
    assert loaded.trigger.schedule == job.trigger.schedule
    assert loaded.prompt == job.prompt
    assert loaded.skills == job.skills


def test_state_yaml_roundtrip(tmp_path):
    state = JobState(
        last_run_at=datetime(2026, 2, 8, 9, 0, tzinfo=timezone.utc),
        last_status="success",
        run_count=5,
    )
    job = JobDefinition(
        name="stateful-job",
        trigger=TriggerConfig(type="cron", schedule="0 9 * * *"),
        prompt="Run daily",
        state=state,
    )
    save_job(job, tmp_path)
    loaded = load_job(tmp_path / "stateful-job.yaml")

    assert loaded.state.last_status == "success"
    assert loaded.state.run_count == 5
    assert loaded.state.last_run_at is not None


def test_load_jobs_directory(tmp_path):
    for i in range(3):
        name = f"job-{i:02d}"
        job = JobDefinition(
            name=name,
            trigger=TriggerConfig(type="cron", schedule="0 9 * * *"),
            prompt=f"Job {i}",
        )
        save_job(job, tmp_path)

    jobs = load_jobs(tmp_path)
    assert len(jobs) == 3


def test_load_jobs_skips_invalid(tmp_path):
    # Two valid jobs
    for i in range(2):
        name = f"valid-{i:02d}"
        job = JobDefinition(
            name=name,
            trigger=TriggerConfig(type="cron", schedule="0 9 * * *"),
            prompt=f"Job {i}",
        )
        save_job(job, tmp_path)

    # One invalid YAML
    (tmp_path / "broken.yaml").write_text(INVALID_YAML)

    jobs = load_jobs(tmp_path)
    assert len(jobs) == 2


def test_delete_job(tmp_path):
    job = JobDefinition(
        name="to-delete",
        trigger=TriggerConfig(type="cron", schedule="0 9 * * *"),
        prompt="Temporary",
    )
    save_job(job, tmp_path)
    assert (tmp_path / "to-delete.yaml").exists()

    result = delete_job("to-delete", tmp_path)
    assert result is True
    assert not (tmp_path / "to-delete.yaml").exists()

    # Delete non-existent returns False
    assert delete_job("to-delete", tmp_path) is False


def test_update_job_state(tmp_path):
    job = JobDefinition(
        name="updatable",
        trigger=TriggerConfig(type="cron", schedule="0 9 * * *"),
        prompt="Original prompt",
    )
    save_job(job, tmp_path)

    new_state = JobState(
        last_run_at=datetime(2026, 2, 9, 9, 0, tzinfo=timezone.utc),
        last_status="success",
        run_count=1,
    )
    update_job_state("updatable", tmp_path, new_state)

    loaded = load_job(tmp_path / "updatable.yaml")
    assert loaded.state.last_status == "success"
    assert loaded.state.run_count == 1
    assert loaded.prompt == "Original prompt"  # Prompt unchanged


def test_load_jobs_empty_dir(tmp_path):
    jobs = load_jobs(tmp_path)
    assert jobs == []


def test_load_jobs_nonexistent_dir(tmp_path):
    jobs = load_jobs(tmp_path / "nonexistent")
    assert jobs == []
