from __future__ import annotations

import contextlib
import io
import os
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch

from src.cli import main


class TestOrganize(unittest.TestCase):
    def test_preview_outputs_expected_path(self) -> None:
        stdout = io.StringIO()
        with contextlib.redirect_stdout(stdout):
            code = main(
                [
                    "organize",
                    "preview",
                    "--region",
                    "Noord-Holland",
                    "--place",
                    "Amsterdam",
                    "--venue",
                    "Venue X",
                    "--date",
                    "2026-01-01",
                ]
            )
        self.assertEqual(code, 0)
        self.assertEqual(stdout.getvalue().strip(), "Noord-Holland/Amsterdam/Venue X/2026/01/")

    def test_dry_run_does_not_create_directories_or_copy(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp) / "out"
            src = Path(tmp) / "a.txt"
            src.write_text("hello", encoding="utf-8")

            stdout = io.StringIO()
            with contextlib.redirect_stdout(stdout):
                code = main(
                    [
                        "organize",
                        "run",
                        "--root",
                        str(root),
                        "--region",
                        "Noord-Holland",
                        "--place",
                        "Amsterdam",
                        "--venue",
                        "Venue X",
                        "--date",
                        "2026-01-01",
                        "--paths",
                        str(src),
                        "--dry-run",
                    ]
                )

            dest_dir = root / "Noord-Holland" / "Amsterdam" / "Venue X" / "2026" / "01"
            self.assertEqual(code, 0)
            self.assertFalse(dest_dir.exists())
            self.assertFalse((dest_dir / "a.txt").exists())

    def test_run_creates_directory_and_copies_file(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp) / "out"
            src = Path(tmp) / "a.txt"
            src.write_text("hello", encoding="utf-8")

            stdout = io.StringIO()
            with contextlib.redirect_stdout(stdout):
                code = main(
                    [
                        "organize",
                        "run",
                        "--root",
                        str(root),
                        "--region",
                        "Noord-Holland",
                        "--place",
                        "Amsterdam",
                        "--venue",
                        "Venue X",
                        "--date",
                        "2026-01-01",
                        "--strategy",
                        "copy",
                        "--paths",
                        str(src),
                    ]
                )

            dest_dir = root / "Noord-Holland" / "Amsterdam" / "Venue X" / "2026" / "01"
            dest_file = dest_dir / "a.txt"
            self.assertEqual(code, 0)
            self.assertTrue(dest_file.exists())
            self.assertEqual(dest_file.read_text(encoding="utf-8"), "hello")

    def test_run_fails_closed_without_root(self) -> None:
        stderr = io.StringIO()
        with patch.dict(os.environ, {}, clear=True), contextlib.redirect_stderr(stderr):
            code = main(
                [
                    "organize",
                    "run",
                    "--region",
                    "Noord-Holland",
                    "--place",
                    "Amsterdam",
                    "--venue",
                    "Venue X",
                    "--date",
                    "2026-01-01",
                    "--dry-run",
                ]
            )
        self.assertEqual(code, 2)
        self.assertIn("Missing root directory", stderr.getvalue())
