import shutil
import unittest
from pathlib import Path

from click.testing import CliRunner

from src.cli import cli


class TestBackupCLI(unittest.TestCase):
    def setUp(self):
        self.runner = CliRunner()
        self.test_source = Path("test_source")
        self.test_restore = Path("test_restore")
        self.test_backup = Path("test_backup.zst")
        self.empty_dir = Path("empty_source")

        self.test_source.mkdir(exist_ok=True)
        self.test_restore.mkdir(exist_ok=True)
        self.empty_dir.mkdir(exist_ok=True)

        self.create_dummy_files()

    def create_dummy_files(self):
        # Create a file in the root source directory
        self.test_file = self.test_source / "test_file.txt"
        with open(self.test_file, "w") as f:
            f.write("This is a test file.")

        # Create a subdirectory with additional test files
        self.sub_dir = self.test_source / "subdir"
        self.sub_dir.mkdir(exist_ok=True)

        self.sub_file = self.sub_dir / "sub_test_file.txt"
        with open(self.sub_file, "w") as f:
            f.write("This is a test file inside a subdirectory.")

    def tearDown(self):
        if Path(self.test_source).exists():
            shutil.rmtree(self.test_source)

        if Path(self.test_restore).exists():
            shutil.rmtree(self.test_restore)

        if Path(self.test_backup).exists():
            Path(self.test_backup).unlink()

        if Path("encryption.key").exists():
            Path("encryption.key").unlink()

        if self.empty_dir.exists():
            shutil.rmtree(self.empty_dir)

    def test_backup_restore_command(self):
        result = self.runner.invoke(cli, ["backup", str(self.test_source), str(self.test_backup)])
        self.assertIn("Creating backup", result.output)
        self.assertEqual(result.exit_code, 0)

        result = self.runner.invoke(cli, ["restore", str(self.test_backup), str(self.test_restore)])
        self.assertIn("Restoring backup", result.output)
        self.assertEqual(result.exit_code, 0)

    def test_empty_backup(self):
        """Test backup command with an empty source directory."""
        result = self.runner.invoke(cli, ["backup", str(self.empty_dir), str(self.test_backup)])
        self.assertIn("Error: The source directory is empty. Backup aborted.", result.output)
        self.assertNotEqual(result.exit_code, 0)
