from pathlib import Path
import tempfile
import unittest

from nightshift.artifacts import ArtifactStore
from nightshift.errors import ArtifactError
from nightshift.init import init_project
from nightshift.tasks import parse_task_file


class ArtifactStoreTests(unittest.TestCase):
    def test_initialize_run_creates_base_artifact_tree(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory)
            store = ArtifactStore(root, ".nightshift", run_id="test-run")

            store.initialize_run()

            self.assertTrue((root / ".nightshift").is_dir())
            self.assertTrue((root / ".nightshift" / "project-context.md").exists())
            self.assertTrue((root / ".nightshift" / "runs" / "test-run").is_dir())
            self.assertTrue((root / ".nightshift" / "runs" / "test-run" / "tasks").is_dir())
            self.assertTrue((root / ".nightshift" / "runs" / "test-run" / "run-summary.md").exists())

    def test_writes_config_task_stage_and_final_artifacts(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory)
            init_project(root)
            task = parse_task_file(root, "tasks.md")[0]
            store = ArtifactStore(root, ".nightshift", run_id="test-run")

            config_path = store.write_config_snapshot(root / "nightshift.yaml")
            task_path = store.write_task_snapshot(task)
            stage_path = store.write_stage_output(task.id, "plan.md", "# Plan\n")
            command_path = store.write_command_output(task.id, "test-output.txt", "ok\n")
            notes_path = store.write_final_task_notes(task.id, "# Notes\n")

            self.assertTrue(config_path.exists())
            self.assertIn("project:", config_path.read_text(encoding="utf-8"))
            self.assertTrue(task_path.exists())
            self.assertIn(task.id, task_path.read_text(encoding="utf-8"))
            self.assertEqual(stage_path.read_text(encoding="utf-8"), "# Plan\n")
            self.assertEqual(command_path.read_text(encoding="utf-8"), "ok\n")
            self.assertEqual(notes_path.read_text(encoding="utf-8"), "# Notes\n")

    def test_stage_output_cannot_escape_task_directory(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory)
            store = ArtifactStore(root, ".nightshift", run_id="test-run")

            with self.assertRaisesRegex(ArtifactError, "escapes task directory"):
                store.write_stage_output("TASK-001", "../leak.txt", "nope")

    def test_run_id_and_task_id_must_be_safe_path_segments(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory)

            with self.assertRaisesRegex(ArtifactError, "run id contains unsafe"):
                ArtifactStore(root, ".nightshift", run_id="../run")

            store = ArtifactStore(root, ".nightshift", run_id="safe-run")
            with self.assertRaisesRegex(ArtifactError, "task id contains unsafe"):
                store.create_task_dir("../TASK-001")


if __name__ == "__main__":
    unittest.main()
