"""
Tests for text_edit_dialog module
"""

import pytest
from unittest.mock import Mock, patch
from PyQt6.QtGui import QColor


class TestTextEditDialogInit:
    """Tests for TextEditDialog initialization"""

    def test_init_basic(self, qtbot):
        """Test basic dialog initialization"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = "Hello World"
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        assert dialog.text_element == mock_text_element
        assert dialog.windowTitle() == "Edit Text"

    def test_init_loads_text_content(self, qtbot):
        """Test that init loads text content from element"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = "Test content here"
        mock_text_element.font_settings = {"family": "Arial", "size": 14, "color": (0, 0, 0)}
        mock_text_element.alignment = "center"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        assert dialog.text_edit.toPlainText() == "Test content here"

    def test_init_loads_font_family(self, qtbot):
        """Test that init loads font family from element"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Georgia", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        assert dialog.font_combo.currentText() == "Georgia"

    def test_init_loads_font_size(self, qtbot):
        """Test that init loads font size from element"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 24, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        assert dialog.font_size_spin.value() == 24

    def test_init_loads_color_255_range(self, qtbot):
        """Test that init loads color in 0-255 range"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (255, 128, 64)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        assert dialog.current_color.red() == 255
        assert dialog.current_color.green() == 128
        assert dialog.current_color.blue() == 64

    def test_init_loads_color_01_range(self, qtbot):
        """Test that init loads color in 0-1 range"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (1.0, 0.5, 0.0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        assert dialog.current_color.red() == 255
        assert dialog.current_color.green() == 127
        assert dialog.current_color.blue() == 0

    def test_init_loads_alignment(self, qtbot):
        """Test that init loads alignment from element"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "right"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        assert dialog.alignment_combo.currentText() == "right"

    def test_init_handles_unknown_font(self, qtbot):
        """Test that init handles unknown font family gracefully"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "UnknownFont", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        # Should not crash, will keep default selection
        assert dialog.font_combo.currentIndex() >= 0

    def test_init_handles_default_values(self, qtbot):
        """Test that init handles missing font settings"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {}  # Empty settings
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        # Should use defaults
        assert dialog.font_size_spin.value() == 12


class TestTextEditDialogUI:
    """Tests for TextEditDialog UI elements"""

    def test_font_size_range(self, qtbot):
        """Test that font size spinner has correct range"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        assert dialog.font_size_spin.minimum() == 6
        assert dialog.font_size_spin.maximum() == 72

    def test_alignment_options(self, qtbot):
        """Test that alignment combo has correct options"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        options = [dialog.alignment_combo.itemText(i) for i in range(dialog.alignment_combo.count())]
        assert "left" in options
        assert "center" in options
        assert "right" in options
        assert "justify" in options

    def test_font_options(self, qtbot):
        """Test that font combo has expected fonts"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        fonts = [dialog.font_combo.itemText(i) for i in range(dialog.font_combo.count())]
        assert "Arial" in fonts
        assert "Times New Roman" in fonts
        assert "Courier New" in fonts


class TestChooseColor:
    """Tests for _choose_color method"""

    def test_choose_color_updates_current_color(self, qtbot):
        """Test that choosing color updates current_color"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        # Mock QColorDialog to return a specific color
        with patch("pyPhotoAlbum.text_edit_dialog.QColorDialog.getColor") as mock_get_color:
            mock_color = QColor(255, 0, 0)
            mock_get_color.return_value = mock_color

            dialog._choose_color()

            assert dialog.current_color.red() == 255
            assert dialog.current_color.green() == 0
            assert dialog.current_color.blue() == 0

    def test_choose_color_invalid_does_not_update(self, qtbot):
        """Test that invalid color choice does not update current_color"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        original_color = QColor(dialog.current_color)

        # Mock QColorDialog to return invalid color (user cancelled)
        with patch("pyPhotoAlbum.text_edit_dialog.QColorDialog.getColor") as mock_get_color:
            mock_get_color.return_value = QColor()  # Invalid color

            dialog._choose_color()

            # Color should remain unchanged
            assert dialog.current_color == original_color


class TestUpdateColorButton:
    """Tests for _update_color_button method"""

    def test_update_color_button_dark_color(self, qtbot):
        """Test color button with dark color uses white text"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        dialog.current_color = QColor(0, 0, 0)  # Black
        dialog._update_color_button()

        stylesheet = dialog.color_button.styleSheet()
        assert "color: white" in stylesheet

    def test_update_color_button_light_color(self, qtbot):
        """Test color button with light color uses black text"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (255, 255, 255)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        dialog.current_color = QColor(255, 255, 255)  # White
        dialog._update_color_button()

        stylesheet = dialog.color_button.styleSheet()
        assert "color: black" in stylesheet


class TestGetValues:
    """Tests for get_values method"""

    def test_get_values_returns_text(self, qtbot):
        """Test get_values returns text content"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = "Original"
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        dialog.text_edit.setPlainText("New text content")

        values = dialog.get_values()
        assert values["text_content"] == "New text content"

    def test_get_values_returns_font_settings(self, qtbot):
        """Test get_values returns font settings"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        dialog.font_combo.setCurrentText("Georgia")
        dialog.font_size_spin.setValue(18)
        dialog.current_color = QColor(100, 150, 200)

        values = dialog.get_values()
        assert values["font_settings"]["family"] == "Georgia"
        assert values["font_settings"]["size"] == 18
        assert values["font_settings"]["color"] == (100, 150, 200)

    def test_get_values_returns_alignment(self, qtbot):
        """Test get_values returns alignment"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        dialog.alignment_combo.setCurrentText("center")

        values = dialog.get_values()
        assert values["alignment"] == "center"

    def test_get_values_complete_structure(self, qtbot):
        """Test get_values returns complete structure"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog

        mock_text_element = Mock()
        mock_text_element.text_content = "Test"
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        values = dialog.get_values()

        # Check structure
        assert "text_content" in values
        assert "font_settings" in values
        assert "alignment" in values
        assert "family" in values["font_settings"]
        assert "size" in values["font_settings"]
        assert "color" in values["font_settings"]


class TestDialogButtons:
    """Tests for dialog buttons"""

    def test_cancel_button_rejects(self, qtbot):
        """Test that cancel button rejects the dialog"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog
        from PyQt6.QtWidgets import QPushButton

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        # Find cancel button
        buttons = dialog.findChildren(QPushButton)
        cancel_button = next(b for b in buttons if b.text() == "Cancel")

        # Click should reject
        with qtbot.waitSignal(dialog.rejected, timeout=1000):
            cancel_button.click()

    def test_ok_button_accepts(self, qtbot):
        """Test that OK button accepts the dialog"""
        from pyPhotoAlbum.text_edit_dialog import TextEditDialog
        from PyQt6.QtWidgets import QPushButton

        mock_text_element = Mock()
        mock_text_element.text_content = ""
        mock_text_element.font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
        mock_text_element.alignment = "left"

        dialog = TextEditDialog(mock_text_element)
        qtbot.addWidget(dialog)

        # Find OK button
        buttons = dialog.findChildren(QPushButton)
        ok_button = next(b for b in buttons if b.text() == "OK")

        # Click should accept
        with qtbot.waitSignal(dialog.accepted, timeout=1000):
            ok_button.click()
