"""Tests for CLI."""

from __future__ import annotations

import tempfile
from pathlib import Path
from unittest.mock import patch

from typer.testing import CliRunner

from file_organizer.cli import app

runner = CliRunner()


class TestCLI:
    def test_version(self) -> None:
        result = runner.invoke(app, ["version"])
        assert result.exit_code == 0
        assert "file-organizer v" in result.stdout

    def test_organize_help(self) -> None:
        result = runner.invoke(app, ["organize", "--help"])
        assert result.exit_code == 0
        assert "organize" in result.stdout.lower()

    def test_organize_dry_run(self) -> None:
        with tempfile.TemporaryDirectory() as tmpdir:
            source = Path(tmpdir) / "test_dir"
            source.mkdir()
            (source / "photo.jpg").write_bytes(b"fake")
            (source / "doc.pdf").write_bytes(b"fake")

            result = runner.invoke(app, ["organize", str(source), "--by", "type", "--dry-run"])
            assert result.exit_code == 0
            assert "photo.jpg" in result.stdout
            assert "doc.pdf" in result.stdout
            assert "DRY RUN" in result.stdout

    def test_organize_by_date(self) -> None:
        with tempfile.TemporaryDirectory() as tmpdir:
            source = Path(tmpdir) / "test_dir"
            source.mkdir()
            (source / "file.txt").write_bytes(b"content")

            result = runner.invoke(app, ["organize", str(source), "--by", "date", "--dry-run"])
            assert result.exit_code == 0
            assert "file.txt" in result.stdout

    def test_organize_by_size(self) -> None:
        with tempfile.TemporaryDirectory() as tmpdir:
            source = Path(tmpdir) / "test_dir"
            source.mkdir()
            (source / "file.txt").write_bytes(b"content")

            result = runner.invoke(app, ["organize", str(source), "--by", "size", "--dry-run"])
            assert result.exit_code == 0
            assert "file.txt" in result.stdout

    def test_organize_nonexistent_dir(self) -> None:
        result = runner.invoke(app, ["organize", "/nonexistent/path"])
        assert result.exit_code != 0

    def test_config_show(self) -> None:
        result = runner.invoke(app, ["config", "--show"])
        assert result.exit_code == 0
        assert "Configuration" in result.stdout
        assert "organize" in result.stdout

    def test_config_set(self) -> None:
        with (
            tempfile.TemporaryDirectory() as tmpdir,
            patch("file_organizer.config.get_config_path") as mock_path,
        ):
            mock_path.return_value = Path(tmpdir) / "config.yaml"
            result = runner.invoke(app, ["config", "--set", "organize.default_mode=date"])
            assert result.exit_code == 0
            assert "Set organize.default_mode = date" in result.stdout

    def test_ignore_list(self) -> None:
        result = runner.invoke(app, ["ignore", "--list"])
        assert result.exit_code == 0
        assert "*.tmp" in result.stdout or "Ignore Patterns" in result.stdout

    def test_ignore_add(self) -> None:
        with (
            tempfile.TemporaryDirectory() as tmpdir,
            patch("file_organizer.config.get_config_path") as mock_path,
        ):
            mock_path.return_value = Path(tmpdir) / "config.yaml"
            result = runner.invoke(app, ["ignore", "--add", "*.bak"])
            assert result.exit_code == 0
            assert "Added ignore pattern: *.bak" in result.stdout

    def test_undo_no_log(self) -> None:
        with (
            tempfile.TemporaryDirectory() as tmpdir,
            patch("file_organizer.config.get_undo_log_path") as mock_path,
        ):
            mock_path.return_value = Path(tmpdir) / "undo_log.json"
            result = runner.invoke(app, ["undo"])
            assert result.exit_code == 0
            assert "No previous organization" in result.stdout

    def test_organize_empty_dir(self) -> None:
        with tempfile.TemporaryDirectory() as tmpdir:
            source = Path(tmpdir) / "empty"
            source.mkdir()

            result = runner.invoke(app, ["organize", str(source), "--dry-run"])
            assert result.exit_code == 0
            assert "No files to organize" in result.stdout
