"""Tests for badge detection and rendering."""

import os
import tempfile
import unittest

from PIL import Image


class TestDetectBadges(unittest.TestCase):
    """Tests for badges.detect_badges()."""

    def setUp(self):
        from video_thumbnail_creator.badges import detect_badges
        self.detect = detect_badges

    def test_detect_badges_4k_hdr(self):
        props = {"is_4k": True, "is_hd": False, "is_hdr": True}
        result = self.detect(props)
        self.assertEqual(result, ["4k", "hdr"])

    def test_detect_badges_hd(self):
        props = {"is_4k": False, "is_hd": True, "is_hdr": False}
        result = self.detect(props)
        self.assertEqual(result, ["hd"])

    def test_detect_badges_sd(self):
        props = {"is_4k": False, "is_hd": False, "is_hdr": False}
        result = self.detect(props)
        self.assertEqual(result, [])

    def test_detect_badges_4k_only(self):
        props = {"is_4k": True, "is_hd": False, "is_hdr": False}
        result = self.detect(props)
        self.assertEqual(result, ["4k"])

    def test_detect_badges_hd_hdr(self):
        props = {"is_4k": False, "is_hd": True, "is_hdr": True}
        result = self.detect(props)
        self.assertEqual(result, ["hd", "hdr"])

    def test_detect_badges_empty_props(self):
        result = self.detect({})
        self.assertEqual(result, [])

    def test_4k_takes_priority_over_hd(self):
        # If both is_4k and is_hd are True, only 4k badge should appear
        props = {"is_4k": True, "is_hd": True, "is_hdr": False}
        result = self.detect(props)
        self.assertIn("4k", result)
        self.assertNotIn("hd", result)

    def test_detect_badges_4k_hfr_60fps(self):
        props = {"is_4k": True, "is_hd": False, "is_hdr": False, "fps": 60.0}
        result = self.detect(props)
        self.assertEqual(result, ["4k60"])

    def test_detect_badges_hd_hfr_48fps(self):
        props = {"is_4k": False, "is_hd": True, "is_hdr": False, "fps": 48.0}
        result = self.detect(props)
        self.assertEqual(result, ["hd48"])

    def test_detect_badges_hd_hfr_with_hdr(self):
        props = {"is_4k": False, "is_hd": True, "is_hdr": True, "fps": 60.0}
        result = self.detect(props)
        self.assertEqual(result, ["hd60", "hdr"])

    def test_detect_badges_no_hfr_below_48fps(self):
        props = {"is_4k": True, "is_hd": False, "is_hdr": False, "fps": 30.0}
        result = self.detect(props)
        self.assertEqual(result, ["4k"])


class TestGenerateBadge(unittest.TestCase):
    """Tests for badges._generate_badge()."""

    def test_generate_badge_4k_returns_rgba_image(self):
        from video_thumbnail_creator.badges import _generate_badge
        badge = _generate_badge("4k")
        self.assertIsInstance(badge, Image.Image)
        self.assertEqual(badge.mode, "RGBA")

    def test_generate_badge_hdr_returns_rgba_image(self):
        from video_thumbnail_creator.badges import _generate_badge
        badge = _generate_badge("hdr")
        self.assertIsInstance(badge, Image.Image)
        self.assertEqual(badge.mode, "RGBA")

    def test_generate_badge_hd_returns_rgba_image(self):
        from video_thumbnail_creator.badges import _generate_badge
        badge = _generate_badge("hd")
        self.assertIsInstance(badge, Image.Image)
        self.assertEqual(badge.mode, "RGBA")

    def test_generate_badge_hfr_4k60_returns_rgba_image(self):
        from video_thumbnail_creator.badges import _generate_badge
        badge = _generate_badge("4k60")
        self.assertIsInstance(badge, Image.Image)
        self.assertEqual(badge.mode, "RGBA")

    def test_generate_badge_hfr_hd48_returns_rgba_image(self):
        from video_thumbnail_creator.badges import _generate_badge
        badge = _generate_badge("hd48")
        self.assertIsInstance(badge, Image.Image)
        self.assertEqual(badge.mode, "RGBA")

    def test_generate_badge_has_correct_height(self):
        from video_thumbnail_creator.badges import _generate_badge
        badge = _generate_badge("4k")
        self.assertEqual(badge.height, 28)

    def test_generate_badge_unknown_type(self):
        from video_thumbnail_creator.badges import _generate_badge
        badge = _generate_badge("xyz")
        self.assertIsInstance(badge, Image.Image)
        self.assertEqual(badge.mode, "RGBA")


class TestRenderBadgesOnImage(unittest.TestCase):
    """Tests for badges.render_badges_on_image()."""

    def _make_image(self, width=200, height=100, color=(100, 150, 200)):
        return Image.new("RGB", (width, height), color=color)

    def test_render_badges_modifies_image(self):
        from video_thumbnail_creator.badges import render_badges_on_image
        img = self._make_image()
        original_pixel = img.getpixel((10, 50))
        render_badges_on_image(img, ["4k"], x_start=5, y_center=50,
                               max_width=100, badge_height=28)
        # Image should still be valid
        self.assertEqual(img.size, (200, 100))

    def test_render_badges_returns_consumed_width(self):
        from video_thumbnail_creator.badges import render_badges_on_image
        img = self._make_image()
        width = render_badges_on_image(img, ["4k"], x_start=5, y_center=50,
                                       max_width=150, badge_height=28)
        self.assertGreater(width, 0)

    def test_render_no_badges_returns_zero(self):
        from video_thumbnail_creator.badges import render_badges_on_image
        img = self._make_image()
        width = render_badges_on_image(img, [], x_start=5, y_center=50,
                                       max_width=150, badge_height=28)
        self.assertEqual(width, 0)

    def test_render_multiple_badges(self):
        from video_thumbnail_creator.badges import render_badges_on_image
        img = self._make_image(width=400, height=100)
        width = render_badges_on_image(img, ["4k", "hdr"], x_start=5, y_center=50,
                                       max_width=200, badge_height=28)
        self.assertGreater(width, 0)

    def test_render_badges_respects_max_width(self):
        from video_thumbnail_creator.badges import render_badges_on_image
        img = self._make_image(width=400, height=100)
        # Very small max_width — should not exceed it
        width = render_badges_on_image(img, ["4k", "hdr", "hd"], x_start=0, y_center=50,
                                       max_width=10, badge_height=28)
        self.assertLessEqual(width, 10)


class TestGetVideoProperties(unittest.TestCase):
    """Tests for utils.get_video_properties()."""

    def test_returns_dict_with_expected_keys(self):
        from video_thumbnail_creator.utils import get_video_properties
        # Use a nonexistent path — should return safe defaults
        props = get_video_properties("/nonexistent/video.mp4")
        self.assertIn("width", props)
        self.assertIn("height", props)
        self.assertIn("is_hdr", props)
        self.assertIn("is_4k", props)
        self.assertIn("is_hd", props)
        self.assertIn("fps", props)
        self.assertIn("is_hfr", props)

    def test_returns_safe_defaults_on_error(self):
        from video_thumbnail_creator.utils import get_video_properties
        props = get_video_properties("/nonexistent/video.mp4")
        self.assertEqual(props["width"], 0)
        self.assertEqual(props["height"], 0)
        self.assertFalse(props["is_hdr"])
        self.assertFalse(props["is_4k"])
        self.assertFalse(props["is_hd"])
        self.assertEqual(props["fps"], 0.0)
        self.assertFalse(props["is_hfr"])


class TestComposePosterWithBadges(unittest.TestCase):
    """Tests for compose_poster() with badges parameter."""

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

    def test_compose_poster_with_badges_produces_correct_dimensions(self):
        from video_thumbnail_creator.poster_composer import compose_poster, POSTER_WIDTH, POSTER_HEIGHT

        with tempfile.TemporaryDirectory() as tmpdir:
            frame = os.path.join(tmpdir, "frame.jpg")
            self._make_frame(frame)
            out = os.path.join(tmpdir, "poster.jpg")
            compose_poster(frame, "center", "My Title", out,
                           overlay_note="Episode 1", badges=["4k", "hdr"])
            with Image.open(out) as img:
                self.assertEqual(img.size, (POSTER_WIDTH, POSTER_HEIGHT))

    def test_compose_poster_with_hd_badge(self):
        from video_thumbnail_creator.poster_composer import compose_poster, POSTER_WIDTH, POSTER_HEIGHT

        with tempfile.TemporaryDirectory() as tmpdir:
            frame = os.path.join(tmpdir, "frame.jpg")
            self._make_frame(frame)
            out = os.path.join(tmpdir, "poster.jpg")
            compose_poster(frame, "center", "My Title", out, badges=["hd"])
            with Image.open(out) as img:
                self.assertEqual(img.size, (POSTER_WIDTH, POSTER_HEIGHT))

    def test_compose_poster_badges_without_note(self):
        from video_thumbnail_creator.poster_composer import compose_poster, POSTER_WIDTH, POSTER_HEIGHT

        with tempfile.TemporaryDirectory() as tmpdir:
            frame = os.path.join(tmpdir, "frame.jpg")
            self._make_frame(frame)
            out = os.path.join(tmpdir, "poster.jpg")
            compose_poster(frame, "center", "My Title", out, badges=["4k"])
            with Image.open(out) as img:
                self.assertEqual(img.size, (POSTER_WIDTH, POSTER_HEIGHT))

    def test_note_wrapping_with_badges(self):
        """Note text should wrap to multiple lines when badges consume horizontal space."""
        from video_thumbnail_creator.poster_composer import compose_poster, POSTER_WIDTH, POSTER_HEIGHT

        with tempfile.TemporaryDirectory() as tmpdir:
            frame = os.path.join(tmpdir, "frame.jpg")
            self._make_frame(frame)
            out = os.path.join(tmpdir, "poster.jpg")
            long_note = "This is a very long note that should wrap when badges are present"
            compose_poster(frame, "center", "My Title", out,
                           overlay_note=long_note, badges=["4k", "hdr"])
            # Should produce a valid poster without errors
            with Image.open(out) as img:
                self.assertEqual(img.size, (POSTER_WIDTH, POSTER_HEIGHT))


class TestCLINoBadgesFlag(unittest.TestCase):
    """Tests for the --no-badges CLI flag."""

    def _build_parser(self):
        from video_thumbnail_creator.cli import _build_parser
        return _build_parser()

    def test_no_badges_flag_default_false(self):
        parser = self._build_parser()
        args = parser.parse_args(["extract", "video.mp4"])
        self.assertFalse(args.no_badges)

    def test_no_badges_flag_set(self):
        parser = self._build_parser()
        args = parser.parse_args(["extract", "video.mp4", "--no-badges"])
        self.assertTrue(args.no_badges)


class TestBadgeTemplateDefaults(unittest.TestCase):
    """Tests for the badges section in the built-in template."""

    def test_builtin_template_has_badges_section(self):
        from video_thumbnail_creator.poster_template import _BUILTIN_TEMPLATE
        self.assertIn("badges", _BUILTIN_TEMPLATE)

    def test_badges_section_has_required_keys(self):
        from video_thumbnail_creator.poster_template import _BUILTIN_TEMPLATE
        badges = _BUILTIN_TEMPLATE["badges"]
        self.assertIn("enabled", badges)
        self.assertIn("height", badges)
        self.assertIn("spacing", badges)
        self.assertIn("margin_bottom", badges)
        self.assertIn("margin_left", badges)

    def test_badges_enabled_by_default(self):
        from video_thumbnail_creator.poster_template import _BUILTIN_TEMPLATE
        self.assertTrue(_BUILTIN_TEMPLATE["badges"]["enabled"])

    def test_badges_default_height(self):
        from video_thumbnail_creator.poster_template import _BUILTIN_TEMPLATE
        self.assertEqual(_BUILTIN_TEMPLATE["badges"]["height"], 36)


class TestConfigAllowedKeys(unittest.TestCase):
    """Tests for the badges config keys in config.ALLOWED_KEYS."""

    def test_badges_enabled_key_allowed(self):
        from video_thumbnail_creator.config import ALLOWED_KEYS
        self.assertIn("badges.enabled", ALLOWED_KEYS)

    def test_badges_logo_keys_removed(self):
        from video_thumbnail_creator.config import ALLOWED_KEYS
        self.assertNotIn("badges.hdr_logo", ALLOWED_KEYS)
        self.assertNotIn("badges.uhd_logo", ALLOWED_KEYS)
        self.assertNotIn("badges.fhd_logo", ALLOWED_KEYS)


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