"""TaskStore 持久化的单元测试。"""

import json

import pytest

from taskflow_cli.store import TaskStore
from taskflow_cli.tasks import Task


def make_store(tmp_path):
    return TaskStore(tmp_path / "data.json")


class TestLoad:
    def test_missing_file_returns_empty(self, tmp_path):
        assert make_store(tmp_path).load() == []
        assert make_store(tmp_path).load_error is None

    def test_corrupt_file_returns_empty_with_error(self, tmp_path):
        path = tmp_path / "data.json"
        path.write_text("{not json", encoding="utf-8")
        store = make_store(tmp_path)
        assert store.load() == []
        assert store.load_error is not None

    def test_missing_container_key(self, tmp_path):
        (tmp_path / "data.json").write_text(json.dumps({"foo": 1}), encoding="utf-8")
        store = make_store(tmp_path)
        assert store.load() == []
        assert store.load_error is not None

    def test_skips_single_bad_task_but_keeps_rest(self, tmp_path):
        path = tmp_path / "data.json"
        payload = {
            "version": 1,
            "next_id": 3,
            "tasks": [
                {"id": 1, "title": "好的"},
                {"title": "缺 id"},
                {"id": 3, "title": "也好"},
            ],
        }
        path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")
        store = make_store(tmp_path)
        tasks = store.load()
        assert [t.id for t in tasks] == [1, 3]
        assert store.load_error is not None

    def test_next_id_recovers_from_drift(self, tmp_path):
        """存储中 next_id 小于最大 id(如手工改过文件)时自动修复。"""
        path = tmp_path / "data.json"
        payload = {
            "version": 1,
            "next_id": 2,
            "tasks": [{"id": 7, "title": "x"}],
        }
        path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")
        store = make_store(tmp_path)
        store.load()
        assert store.next_id() == 8


class TestSave:
    def test_save_and_reload_round_trip(self, tmp_path):
        store = make_store(tmp_path)
        t = Task(id=1, title="写周报", priority="high", tags=["work"])
        store.next_id()
        store.save([t])

        reloaded = make_store(tmp_path).load()
        assert reloaded == [t]

    def test_save_is_atomic_no_temp_leftover(self, tmp_path):
        store = make_store(tmp_path)
        t = Task(id=1, title="x")
        store.next_id()
        store.save([t])
        leftovers = [p for p in tmp_path.iterdir() if p.name.startswith(".taskflow-")]
        assert leftovers == []

    def test_save_creates_parent_dirs(self, tmp_path):
        deep = tmp_path / "a" / "b" / "data.json"
        TaskStore(deep).save([])
        assert deep.exists()

    def test_saved_file_utf8_readable(self, tmp_path):
        store = make_store(tmp_path)
        store.next_id()
        store.save([Task(id=1, title="写周报")])
        text = (tmp_path / "data.json").read_text(encoding="utf-8")
        assert "写周报" in text  # ensure_ascii=False

    def test_next_id_monotonic(self, tmp_path):
        store = make_store(tmp_path)
        store.load()
        assert [store.next_id(), store.next_id(), store.next_id()] == [1, 2, 3]