from __future__ import annotations

import contextlib
import io
import json
import tempfile
import unittest
from pathlib import Path

from src.cli import main
from src.ingest.ingest import ingest_inbox


class TestIngest(unittest.TestCase):
    def test_dry_run_does_not_write_manifest(self) -> None:
        inbox = _fixture_inbox()
        with tempfile.TemporaryDirectory() as tmp:
            out_dir = Path(tmp) / "out"
            out_dir.mkdir(parents=True, exist_ok=True)

            result = ingest_inbox(inbox_dir=inbox, out_dir=out_dir, dry_run=True)

            self.assertFalse((out_dir / "manifest.json").exists())
            self.assertEqual(result.files_found, 5)
            self.assertEqual(result.files_eligible, 4)
            self.assertEqual(result.files_new, 3)
            self.assertEqual(result.files_skipped_existing, 0)
            self.assertEqual(result.files_skipped_duplicate_in_run, 1)

    def test_run_writes_manifest_and_is_idempotent(self) -> None:
        inbox = _fixture_inbox()
        with tempfile.TemporaryDirectory() as tmp:
            out_dir = Path(tmp) / "out"

            first = ingest_inbox(inbox_dir=inbox, out_dir=out_dir, dry_run=False)
            self.assertEqual(first.files_new, 3)

            manifest_path = out_dir / "manifest.json"
            self.assertTrue(manifest_path.exists())

            manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
            self.assertEqual(manifest["schema_version"], 1)
            self.assertEqual(len(manifest["files"]), 3)

            second = ingest_inbox(inbox_dir=inbox, out_dir=out_dir, dry_run=False)
            self.assertEqual(second.files_new, 0)
            self.assertEqual(second.files_skipped_existing, 3)
            self.assertEqual(second.files_skipped_duplicate_in_run, 1)

    def test_cli_fails_closed_on_missing_inbox(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            out_dir = Path(tmp) / "out"
            with contextlib.redirect_stderr(io.StringIO()):
                code = main(
                    [
                        "ingest",
                        "--inbox",
                        str(Path(tmp) / "does-not-exist"),
                        "--out",
                        str(out_dir),
                        "--dry-run",
                    ]
                )
            self.assertEqual(code, 2)


def _fixture_inbox() -> Path:
    return Path(__file__).resolve().parent / "fixtures" / "inbox"
