"""Tests for the create_thumbnail() high-level API."""

import os
import tempfile
import unittest
from unittest.mock import MagicMock, patch

from PIL import Image


def _make_jpeg(path: str, width: int = 1920, height: int = 1080) -> str:
    img = Image.new("RGB", (width, height), color=(100, 150, 200))
    img.save(path, "JPEG")
    return path


class TestCreateThumbnailImageInput(unittest.TestCase):
    """create_thumbnail() with an image input (no ffmpeg required)."""

    def setUp(self):
        self.tmpdir = tempfile.mkdtemp()
        self.jpeg_path = os.path.join(self.tmpdir, "photo.jpg")
        _make_jpeg(self.jpeg_path)

    def tearDown(self):
        import shutil
        shutil.rmtree(self.tmpdir, ignore_errors=True)

    def _run(self, **kwargs):
        from video_thumbnail_creator.api import create_thumbnail

        kwargs.setdefault("output_path", os.path.join(self.tmpdir, "out.jpg"))

        with patch("video_thumbnail_creator.image_converter.is_wide_gamut_image", return_value=False), \
             patch("video_thumbnail_creator.session.ThumbnailSession._get_api_credentials", return_value=("fake-key", "claude-model")), \
             patch("video_thumbnail_creator.session.select_crop_with_ai", return_value=("center", "AI crop reasoning")):
            return create_thumbnail(self.jpeg_path, **kwargs)

    def test_output_file_created(self):
        output_path = os.path.join(self.tmpdir, "result.jpg")
        result = self._run(format="poster", output_path=output_path)
        self.assertTrue(os.path.isfile(output_path))

    def test_result_poster_path_is_absolute(self):
        output_path = os.path.join(self.tmpdir, "result.jpg")
        result = self._run(format="poster", output_path=output_path)
        self.assertTrue(os.path.isabs(result.poster_path))

    def test_result_source_is_image(self):
        output_path = os.path.join(self.tmpdir, "result.jpg")
        result = self._run(format="poster", output_path=output_path)
        self.assertEqual(result.source, "image")

    def test_result_frame_index_is_minus_one(self):
        output_path = os.path.join(self.tmpdir, "result.jpg")
        result = self._run(format="poster", output_path=output_path)
        self.assertEqual(result.frame_index, -1)

    def test_landscape_format_without_title(self):
        output_path = os.path.join(self.tmpdir, "landscape.jpg")
        result = self._run(format="landscape", output_path=output_path)
        self.assertTrue(os.path.isfile(output_path))
        self.assertEqual(result.format, "landscape")

    def test_landscape_format_with_title(self):
        output_path = os.path.join(self.tmpdir, "landscape_title.jpg")
        result = self._run(format="landscape", overlay_title="My Film", output_path=output_path)
        self.assertTrue(os.path.isfile(output_path))

    def test_auto_mode_image_skips_frame_selection(self):
        """For image input, no frame selection call should be made."""
        from video_thumbnail_creator.api import create_thumbnail

        output_path = os.path.join(self.tmpdir, "out.jpg")
        with patch("video_thumbnail_creator.image_converter.is_wide_gamut_image", return_value=False), \
             patch("video_thumbnail_creator.session.ThumbnailSession._get_api_credentials", return_value=("fake-key", "claude-model")), \
             patch("video_thumbnail_creator.session.select_crop_with_ai", return_value=("center", "crop reasoning")), \
             patch("video_thumbnail_creator.session.select_frame_with_ai") as mock_select_frame:
            create_thumbnail(self.jpeg_path, mode="auto", format="poster", output_path=output_path)

        mock_select_frame.assert_not_called()

    def test_explicit_crop_position_skips_ai_crop(self):
        """When crop_position is given, suggest_crop() should not be called."""
        from video_thumbnail_creator.api import create_thumbnail

        output_path = os.path.join(self.tmpdir, "out.jpg")
        with patch("video_thumbnail_creator.image_converter.is_wide_gamut_image", return_value=False), \
             patch("video_thumbnail_creator.session.ThumbnailSession._get_api_credentials", return_value=("fake-key", "claude-model")), \
             patch("video_thumbnail_creator.session.select_crop_with_ai") as mock_crop:
            create_thumbnail(
                self.jpeg_path, mode="auto", format="poster",
                crop_position="center-left", output_path=output_path
            )

        mock_crop.assert_not_called()

    def test_unsupported_mode_raises(self):
        from video_thumbnail_creator.api import create_thumbnail

        with self.assertRaises(ValueError) as ctx:
            create_thumbnail(self.jpeg_path, mode="manual")
        self.assertIn("auto", str(ctx.exception))

    def test_missing_input_raises(self):
        from video_thumbnail_creator.api import create_thumbnail

        with self.assertRaises(FileNotFoundError):
            create_thumbnail("/nonexistent/file.jpg")

    def test_result_reasoning_populated_from_crop_ai(self):
        from video_thumbnail_creator.api import create_thumbnail

        output_path = os.path.join(self.tmpdir, "out.jpg")
        with patch("video_thumbnail_creator.image_converter.is_wide_gamut_image", return_value=False), \
             patch("video_thumbnail_creator.session.ThumbnailSession._get_api_credentials", return_value=("fake-key", "claude-model")), \
             patch("video_thumbnail_creator.session.select_crop_with_ai", return_value=("center", "nice center")):
            result = create_thumbnail(self.jpeg_path, mode="auto", format="poster", output_path=output_path)

        self.assertIn("nice center", result.reasoning)

    def test_no_badges_suppresses_auto_detection(self):
        from video_thumbnail_creator.api import create_thumbnail

        output_path = os.path.join(self.tmpdir, "out.jpg")
        with patch("video_thumbnail_creator.image_converter.is_wide_gamut_image", return_value=False), \
             patch("video_thumbnail_creator.session.ThumbnailSession._get_api_credentials", return_value=("fake-key", "claude-model")), \
             patch("video_thumbnail_creator.session.select_crop_with_ai", return_value=("center", "ok")), \
             patch("video_thumbnail_creator.session.detect_badges") as mock_badges:
            create_thumbnail(
                self.jpeg_path, mode="auto", format="poster",
                no_badges=True, output_path=output_path
            )

        mock_badges.assert_not_called()

    def test_result_is_thumbnail_result(self):
        from video_thumbnail_creator.api import create_thumbnail
        from video_thumbnail_creator.session import ThumbnailResult

        output_path = os.path.join(self.tmpdir, "out.jpg")
        with patch("video_thumbnail_creator.image_converter.is_wide_gamut_image", return_value=False), \
             patch("video_thumbnail_creator.session.ThumbnailSession._get_api_credentials", return_value=("fake-key", "claude-model")), \
             patch("video_thumbnail_creator.session.select_crop_with_ai", return_value=("center", "ok")):
            result = create_thumbnail(self.jpeg_path, mode="auto", format="poster", output_path=output_path)

        self.assertIsInstance(result, ThumbnailResult)


class TestCreateThumbnailExport(unittest.TestCase):
    """create_thumbnail is exported from the top-level package."""

    def test_exported_from_package(self):
        from video_thumbnail_creator import create_thumbnail

        self.assertTrue(callable(create_thumbnail))


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