from __future__ import annotations

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

from click.testing import CliRunner


SRC_ROOT = Path(__file__).resolve().parents[2] / "src"

if str(SRC_ROOT) not in sys.path:
    sys.path.insert(0, str(SRC_ROOT))


from ffx import cli  # noqa: E402


class _FakeMediaDescriptor:
    def getVideoTracks(self):
        return []

    def getAudioTracks(self):
        return []

    def getSubtitleTracks(self):
        return []

    def getAttachmentTracks(self):
        return []


class _FakeFileProperties:
    def __init__(self, context, source_path):
        self.source_path = source_path

    def getShowId(self):
        return -1

    def getSeason(self):
        return -1

    def getEpisode(self):
        return -1

    def getMediaDescriptor(self):
        return _FakeMediaDescriptor()

    def getPattern(self):
        return None


class _FakeShiftedSeasonController:
    def __init__(self, context):
        self.context = context

    def shiftSeason(self, show_id, season, episode):
        return season, episode


class _FakeFfxController:
    def __init__(self, *args, **kwargs):
        pass

    def runJob(self, *args, **kwargs):
        raise AssertionError("runJob should not be called for --rename-only")


class RenameOnlyCliTests(unittest.TestCase):
    def setUp(self):
        self.tempdir = tempfile.TemporaryDirectory()
        self.home_dir = Path(self.tempdir.name) / "home"
        self.home_dir.mkdir()
        self.database_path = Path(self.tempdir.name) / "test.db"
        self.source_dir = Path(self.tempdir.name) / "source"
        self.source_dir.mkdir()
        self.output_dir = Path(self.tempdir.name) / "output"
        self.output_dir.mkdir()
        self.source_path = self.source_dir / "episode.mkv"
        self.source_bytes = b"rename-only-source"
        self.source_path.write_bytes(self.source_bytes)

    def tearDown(self):
        self.tempdir.cleanup()

    def test_rename_only_moves_source_file_into_output_directory(self):
        runner = CliRunner()

        with (
            patch("ffx.file_properties.FileProperties", _FakeFileProperties),
            patch("ffx.ffx_controller.FfxController", _FakeFfxController),
            patch(
                "ffx.shifted_season_controller.ShiftedSeasonController",
                _FakeShiftedSeasonController,
            ),
        ):
            result = runner.invoke(
                cli.ffx,
                [
                    "--database-file",
                    str(self.database_path),
                    "convert",
                    "--no-tmdb",
                    "--no-pattern",
                    "--rename-only",
                    "--output-directory",
                    str(self.output_dir),
                    str(self.source_path),
                ],
                env={**os.environ, "HOME": str(self.home_dir)},
            )

        self.assertEqual(0, result.exit_code, result.output)

        target_path = self.output_dir / "out_episode.mkv"
        self.assertFalse(self.source_path.exists())
        self.assertTrue(target_path.exists())
        self.assertEqual(self.source_bytes, target_path.read_bytes())


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