"""
Selection dialogs for YTSage application.
Contains dialogs for selecting subtitles, playlist videos, and SponsorBlock categories.
"""

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
    QCheckBox,
    QDialog,
    QDialogButtonBox,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QPushButton,
    QScrollArea,
    QVBoxLayout,
    QWidget,
)

from src.utils.ytsage_localization import _


class SubtitleSelectionDialog(QDialog):
    def __init__(self, available_manual, available_auto, previously_selected, parent=None) -> None:
        super().__init__(parent)
        self.setWindowTitle(_("dialogs.select_subtitles"))
        self.setMinimumWidth(400)
        self.setMinimumHeight(300)

        self.available_manual = available_manual
        self.available_auto = available_auto
        self.previously_selected = set(previously_selected)  # Use a set for quick lookups
        self.selected_subtitles = list(previously_selected)  # Initialize with previous selection

        layout = QVBoxLayout(self)
        layout.setSpacing(10)

        # Filter input
        self.filter_input = QLineEdit()
        self.filter_input.setPlaceholderText(_("dialogs.filter_languages_placeholder"))
        self.filter_input.textChanged.connect(self.filter_list)
        self.filter_input.setStyleSheet(
            """
            QLineEdit {
                background-color: #363636;
                border: 2px solid #3d3d3d;
                border-radius: 4px;
                padding: 5px;
                min-height: 30px;
                color: white;
            }
            QLineEdit:focus {
                border-color: #ff0000;
            }
        """
        )
        layout.addWidget(self.filter_input)

        # Scroll Area for the list
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setStyleSheet("QScrollArea { border: none; }")  # Remove border around scroll area
        layout.addWidget(scroll_area)

        # Container widget for list items (needed for scroll area)
        self.list_container = QWidget()
        self.list_layout = QVBoxLayout(self.list_container)
        self.list_layout.setContentsMargins(0, 0, 0, 0)
        self.list_layout.setSpacing(2)  # Compact spacing
        self.list_layout.setAlignment(Qt.AlignmentFlag.AlignTop)  # Align items to top
        scroll_area.setWidget(self.list_container)

        # Populate the list initially
        self.populate_list()

        # OK and Cancel buttons
        button_box = QDialogButtonBox()
        ok_button = button_box.addButton(_("buttons.ok"), QDialogButtonBox.ButtonRole.AcceptRole)
        cancel_button = button_box.addButton(_("buttons.cancel"), QDialogButtonBox.ButtonRole.RejectRole)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)

        # Style the buttons
        for button in button_box.buttons():
            button.setStyleSheet(
                """
                 QPushButton {
                     background-color: #363636;
                     border: 2px solid #3d3d3d;
                     border-radius: 4px;
                     padding: 5px 15px; /* Adjust padding */
                     min-height: 30px; /* Ensure consistent height */
                     color: white;
                 }
                 QPushButton:hover {
                     background-color: #444444;
                 }
                 QPushButton:pressed {
                     background-color: #555555;
                 }
             """
            )
            # Style the OK button specifically if needed
            if button_box.buttonRole(button) == QDialogButtonBox.ButtonRole.AcceptRole:
                button.setStyleSheet(
                    button.styleSheet()
                    + "QPushButton { background-color: #ff0000; border-color: #cc0000; } QPushButton:hover { background-color: #cc0000; }"
                )

        layout.addWidget(button_box)

    def populate_list(self, filter_text="") -> None:
        # Clear existing checkboxes from layout
        while self.list_layout.count():
            item = self.list_layout.takeAt(0)
            widget = item.widget()
            if widget is not None:
                widget.deleteLater()

        filter_text = filter_text.lower()
        combined_subs = {}

        # Add manual subs
        for lang_code, sub_info in self.available_manual.items():
            if not filter_text or filter_text in lang_code.lower():
                combined_subs[lang_code] = f"{lang_code} - Manual"

        # Add auto subs (only if no manual exists and matches filter)
        for lang_code, sub_info in self.available_auto.items():
            if lang_code not in combined_subs:  # Don't overwrite manual
                if not filter_text or filter_text in lang_code.lower():
                    combined_subs[lang_code] = f"{lang_code} - Auto-generated"

        if not combined_subs:
            matching_text = _("dialogs.matching") if filter_text else ""
            no_subs_label = QLabel(_("dialogs.no_subtitles_available") + (f" {matching_text} '{filter_text}'" if filter_text else ""))
            no_subs_label.setStyleSheet("color: #aaaaaa; padding: 10px;")
            self.list_layout.addWidget(no_subs_label)
            return

        # Sort by language code
        sorted_lang_codes = sorted(combined_subs.keys())

        for lang_code in sorted_lang_codes:
            item_text = combined_subs[lang_code]
            checkbox = QCheckBox(item_text)
            checkbox.setProperty("subtitle_id", item_text)  # Store the identifier
            checkbox.setChecked(item_text in self.previously_selected)  # Check if previously selected
            checkbox.stateChanged.connect(self.update_selection)
            checkbox.setStyleSheet(
                """
                 QCheckBox {
                     color: #ffffff;
                     padding: 5px;
                 }
                 QCheckBox::indicator {
                     width: 18px;
                     height: 18px;
                     border-radius: 4px; /* Square checkboxes */
                 }
                 QCheckBox::indicator:unchecked {
                     border: 2px solid #666666;
                     background: #2b2b2b;
                 }
                 QCheckBox::indicator:checked {
                     border: 2px solid #ff0000;
                     background: #ff0000;
                 }
             """
            )
            self.list_layout.addWidget(checkbox)

        self.list_layout.addStretch()  # Pushes items up if list is short

    def filter_list(self) -> None:
        self.populate_list(self.filter_input.text())

    def update_selection(self, state) -> None:
        sender = self.sender()
        subtitle_id = sender.property("subtitle_id")
        if state == Qt.CheckState.Checked.value:
            if subtitle_id not in self.previously_selected:
                self.previously_selected.add(subtitle_id)
        else:
            if subtitle_id in self.previously_selected:
                self.previously_selected.remove(subtitle_id)

    def get_selected_subtitles(self) -> list:
        # Return the final set as a list
        return list(self.previously_selected)

    def accept(self) -> None:
        # Update the final list before closing
        self.selected_subtitles = self.get_selected_subtitles()
        super().accept()


class PlaylistSelectionDialog(QDialog):
    def __init__(self, playlist_entries, previously_selected_string, parent=None) -> None:
        super().__init__(parent)
        self.setWindowTitle(_("playlist.select_videos_title"))
        self.setMinimumWidth(500)
        self.setMinimumHeight(400)  # Allow more vertical space

        self.playlist_entries = playlist_entries
        self.checkboxes = []

        # Main layout
        main_layout = QVBoxLayout(self)

        # Top buttons (Select/Deselect All)
        button_layout = QHBoxLayout()
        select_all_btn = QPushButton(_("buttons.select_all"))
        deselect_all_btn = QPushButton(_("buttons.deselect_all"))
        select_all_btn.clicked.connect(self._select_all)
        deselect_all_btn.clicked.connect(self._deselect_all)
        # Style the buttons to match the subtitle dialog
        select_all_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #363636;
                border: 2px solid #3d3d3d;
                border-radius: 4px;
                padding: 5px 15px;
                min-height: 30px;
                color: white;
            }
            QPushButton:hover {
                background-color: #444444;
            }
            QPushButton:pressed {
                background-color: #555555;
            }
        """
        )
        deselect_all_btn.setStyleSheet(select_all_btn.styleSheet())
        button_layout.addWidget(select_all_btn)
        button_layout.addWidget(deselect_all_btn)
        button_layout.addStretch()
        main_layout.addLayout(button_layout)

        # Scrollable area for checkboxes
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setStyleSheet("QScrollArea { border: none; }")  # Remove border around scroll area
        scroll_widget = QWidget()
        self.list_layout = QVBoxLayout(scroll_widget)  # Layout for checkboxes
        self.list_layout.setContentsMargins(0, 0, 0, 0)
        self.list_layout.setSpacing(2)  # Compact spacing
        self.list_layout.setAlignment(Qt.AlignmentFlag.AlignTop)  # Align items to top
        scroll_area.setWidget(scroll_widget)
        main_layout.addWidget(scroll_area)

        # Populate checkboxes
        self._populate_list(previously_selected_string)

        # Dialog buttons (OK/Cancel)
        button_box = QDialogButtonBox()
        ok_button = button_box.addButton(_("buttons.ok"), QDialogButtonBox.ButtonRole.AcceptRole)
        cancel_button = button_box.addButton(_("buttons.cancel"), QDialogButtonBox.ButtonRole.RejectRole)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)

        # Style the buttons to match subtitle dialog
        for button in button_box.buttons():
            button.setStyleSheet(
                """
                QPushButton {
                    background-color: #363636;
                    border: 2px solid #3d3d3d;
                    border-radius: 4px;
                    padding: 5px 15px;
                    min-height: 30px;
                    color: white;
                }
                QPushButton:hover {
                    background-color: #444444;
                }
                QPushButton:pressed {
                    background-color: #555555;
                }
            """
            )
            # Style the OK button specifically if needed
            if button_box.buttonRole(button) == QDialogButtonBox.ButtonRole.AcceptRole:
                button.setStyleSheet(
                    button.styleSheet()
                    + "QPushButton { background-color: #ff0000; border-color: #cc0000; } QPushButton:hover { background-color: #cc0000; }"
                )

        main_layout.addWidget(button_box)

        # Apply styling to match subtitle dialog
        self.setStyleSheet(
            """
            QDialog { background-color: #15181b; }
            QCheckBox {
                color: #ffffff;
                padding: 5px;
            }
            QCheckBox::indicator {
                width: 18px;
                height: 18px;
                border-radius: 4px;
            }
            QCheckBox::indicator:unchecked {
                border: 2px solid #666666;
                background: #2b2b2b;
            }
            QCheckBox::indicator:checked {
                border: 2px solid #ff0000;
                background: #ff0000;
            }
            QWidget { background-color: #15181b; }
        """
        )

    def _parse_selection_string(self, selection_string) -> set:
        """Parses a yt-dlp playlist selection string (e.g., '1-3,5,7-9') into a set of 1-based indices."""
        selected_indices = set()
        if not selection_string:
            # If no previous selection, assume all are selected initially
            return set(range(1, len(self.playlist_entries) + 1))

        parts = selection_string.split(",")
        for part in parts:
            part = part.strip()
            if "-" in part:
                try:
                    start, end = map(int, part.split("-"))
                    if start <= end:
                        selected_indices.update(range(start, end + 1))
                except ValueError:
                    pass  # Ignore invalid ranges
            else:
                try:
                    selected_indices.add(int(part))
                except ValueError:
                    pass  # Ignore invalid numbers
        return selected_indices

    def _populate_list(self, previously_selected_string) -> None:
        """Populates the scroll area with checkboxes for each video."""
        selected_indices = self._parse_selection_string(previously_selected_string)

        # Clear existing checkboxes if any (e.g., if repopulating)
        while self.list_layout.count():
            child = self.list_layout.takeAt(0)
            if child.widget():
                child.widget().deleteLater()
        self.checkboxes.clear()

        for index, entry in enumerate(self.playlist_entries):
            if not entry:
                continue  # Skip None entries if yt-dlp returns them

            video_index = index + 1  # yt-dlp uses 1-based indexing
            title = entry.get("title", f"Video {video_index}")
            # Shorten title if too long
            display_title = (title[:70] + "...") if len(title) > 73 else title

            checkbox = QCheckBox(f"{video_index}. {display_title}")
            checkbox.setChecked(video_index in selected_indices)
            checkbox.setProperty("video_index", video_index)  # Store index
            checkbox.setStyleSheet(
                """
                QCheckBox {
                    color: #ffffff;
                    padding: 5px;
                }
                QCheckBox::indicator {
                    width: 18px;
                    height: 18px;
                    border-radius: 4px;
                }
                QCheckBox::indicator:unchecked {
                    border: 2px solid #666666;
                    background: #2b2b2b;
                }
                QCheckBox::indicator:checked {
                    border: 2px solid #ff0000;
                    background: #ff0000;
                }
            """
            )
            self.list_layout.addWidget(checkbox)
            self.checkboxes.append(checkbox)
        self.list_layout.addStretch()  # Push checkboxes to the top

    def _select_all(self) -> None:
        for checkbox in self.checkboxes:
            checkbox.setChecked(True)

    def _deselect_all(self) -> None:
        for checkbox in self.checkboxes:
            checkbox.setChecked(False)

    def _condense_indices(self, indices: list[int]) -> str:
        """Condenses a list of 1-based indices into a yt-dlp selection string."""
        if not indices:
            return ""

        # Remove duplicates and sort in one step
        indices = sorted(set(indices))

        ranges = []
        start = end = indices[0]

        for num in indices[1:]:
            if num == end + 1:
                end = num
            else:
                ranges.append(f"{start}-{end}" if start != end else str(start))
                start = end = num

        # Append the last range
        ranges.append(f"{start}-{end}" if start != end else str(start))

        return ",".join(ranges)

    def get_selected_items_string(self) -> str | None:
        """Returns the selection string based on checked boxes."""
        selected_indices = [cb.property("video_index") for cb in self.checkboxes if cb.isChecked()]

        # Check if all items are selected
        if len(selected_indices) == len(self.playlist_entries):
            return None  # yt-dlp default is all items, so return None or empty string

        return self._condense_indices(selected_indices)


class SponsorBlockCategoryDialog(QDialog):
    """Dialog for selecting SponsorBlock categories to remove from videos."""

    # Default SponsorBlock categories with descriptions
    SPONSORBLOCK_CATEGORIES = {
        "sponsor": {
            "name_key": "sponsorblock.sponsor",
            "description_key": "sponsorblock.sponsor_desc",
            "default": True,
        },
        "selfpromo": {
            "name_key": "sponsorblock.selfpromo",
            "description_key": "sponsorblock.selfpromo_desc",
            "default": True,
        },
        "interaction": {
            "name_key": "sponsorblock.interaction",
            "description_key": "sponsorblock.interaction_desc",
            "default": True,
        },
        "intro": {
            "name_key": "sponsorblock.intro",
            "description_key": "sponsorblock.intro_desc",
            "default": False,
        },
        "outro": {
            "name_key": "sponsorblock.outro",
            "description_key": "sponsorblock.outro_desc",
            "default": False,
        },
        "preview": {
            "name_key": "sponsorblock.preview",
            "description_key": "sponsorblock.preview_desc",
            "default": False,
        },
        "music_offtopic": {
            "name_key": "sponsorblock.music_offtopic",
            "description_key": "sponsorblock.music_offtopic_desc",
            "default": False,
        },
        "filler": {
            "name_key": "sponsorblock.filler",
            "description_key": "sponsorblock.filler_desc",
            "default": False,
        },
    }

    def __init__(self, previously_selected=None, parent=None) -> None:
        super().__init__(parent)
        self.setWindowTitle(_("dialogs.sponsorblock_categories"))
        self.setMinimumWidth(500)
        self.setMinimumHeight(400)

        # Set the window icon to match the main app
        if parent:
            self.setWindowIcon(parent.windowIcon())

        self.previously_selected = set(previously_selected) if previously_selected else set()
        self.checkboxes = {}

        self.init_ui()
        self.apply_styling()

    def init_ui(self) -> None:
        layout = QVBoxLayout(self)

        # Title and description
        title_label = QLabel(_("dialogs.sponsorblock_categories"))
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #ffffff; margin: 10px;")
        layout.addWidget(title_label)

        desc_label = QLabel(_("dialogs.sponsorblock_description"))
        desc_label.setWordWrap(True)
        desc_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        desc_label.setStyleSheet("color: #cccccc; margin: 10px; font-size: 11px;")
        layout.addWidget(desc_label)

        # Scroll area for categories
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setStyleSheet("QScrollArea { border: none; }")

        scroll_widget = QWidget()
        scroll_layout = QVBoxLayout(scroll_widget)
        scroll_layout.setContentsMargins(10, 0, 10, 0)
        scroll_layout.setSpacing(8)

        # Add category checkboxes
        for category_id, category_info in self.SPONSORBLOCK_CATEGORIES.items():
            # Create a container widget for each category
            category_widget = QWidget()
            category_layout = QVBoxLayout(category_widget)
            category_layout.setContentsMargins(0, 0, 0, 0)
            category_layout.setSpacing(2)

            # Create checkbox with localized name
            checkbox = QCheckBox(_(category_info["name_key"]))
            checkbox.setProperty("category_id", category_id)

            # Determine if this category should be checked
            if self.previously_selected:
                # Use previously selected categories
                is_checked = category_id in self.previously_selected
            else:
                # Use default values for first time
                is_checked = category_info["default"]

            checkbox.setChecked(is_checked)

            checkbox.setStyleSheet(
                """
                QCheckBox {
                    color: #ffffff;
                    padding: 4px;
                    spacing: 10px;
                    font-weight: bold;
                }
                QCheckBox::indicator {
                    width: 18px;
                    height: 18px;
                    border-radius: 4px;
                }
                QCheckBox::indicator:unchecked {
                    border: 2px solid #666666;
                    background: #2b2b2b;
                }
                QCheckBox::indicator:checked {
                    border: 2px solid #ff0000;
                    background: #ff0000;
                }
            """
            )

            # Create description label with localized text
            desc_label = QLabel(_(category_info["description_key"]))
            desc_label.setStyleSheet("color: #aaaaaa; font-size: 11px; margin-left: 28px; margin-bottom: 8px;")
            desc_label.setWordWrap(True)

            category_layout.addWidget(checkbox)
            category_layout.addWidget(desc_label)

            self.checkboxes[category_id] = checkbox
            scroll_layout.addWidget(category_widget)

        scroll_layout.addStretch()
        scroll_area.setWidget(scroll_widget)
        layout.addWidget(scroll_area)

        # Quick selection buttons
        button_layout = QHBoxLayout()

        select_defaults_btn = QPushButton(_("buttons.select_defaults"))
        select_defaults_btn.clicked.connect(self.select_defaults)
        select_defaults_btn.setStyleSheet(self._get_button_style())

        select_all_btn = QPushButton(_("buttons.select_all"))
        select_all_btn.clicked.connect(self.select_all)
        select_all_btn.setStyleSheet(self._get_button_style())

        deselect_all_btn = QPushButton(_("buttons.deselect_all"))
        deselect_all_btn.clicked.connect(self.deselect_all)
        deselect_all_btn.setStyleSheet(self._get_button_style())

        button_layout.addWidget(select_defaults_btn)
        button_layout.addWidget(select_all_btn)
        button_layout.addWidget(deselect_all_btn)
        button_layout.addStretch()

        layout.addLayout(button_layout)

        # Dialog buttons
        button_box = QDialogButtonBox()
        ok_button = button_box.addButton(_("buttons.ok"), QDialogButtonBox.ButtonRole.AcceptRole)
        cancel_button = button_box.addButton(_("buttons.cancel"), QDialogButtonBox.ButtonRole.RejectRole)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)

        # Style the dialog buttons
        for button in button_box.buttons():
            button.setStyleSheet(self._get_button_style())
            if button_box.buttonRole(button) == QDialogButtonBox.ButtonRole.AcceptRole:
                button.setStyleSheet(
                    button.styleSheet()
                    + "QPushButton { background-color: #ff0000; border-color: #cc0000; } "
                    + "QPushButton:hover { background-color: #cc0000; }"
                )

        layout.addWidget(button_box)

    def _get_button_style(self) -> str:
        """Returns the standard button style for this dialog."""
        return """
            QPushButton {
                background-color: #363636;
                border: 2px solid #3d3d3d;
                border-radius: 4px;
                padding: 5px 15px;
                min-height: 30px;
                color: white;
            }
            QPushButton:hover {
                background-color: #444444;
            }
            QPushButton:pressed {
                background-color: #555555;
            }
        """

    def apply_styling(self) -> None:
        """Apply the dialog styling to match the rest of the application."""
        self.setStyleSheet(
            """
            QDialog {
                background-color: #15181b;
                color: #ffffff;
            }
            QLabel {
                color: #ffffff;
            }
            QWidget {
                background-color: #15181b;
            }
        """
        )

    def select_defaults(self) -> None:
        """Select only the default categories."""
        for category_id, checkbox in self.checkboxes.items():
            default_value = self.SPONSORBLOCK_CATEGORIES[category_id]["default"]
            checkbox.setChecked(default_value)

    def select_all(self) -> None:
        """Select all categories."""
        for checkbox in self.checkboxes.values():
            checkbox.setChecked(True)

    def deselect_all(self) -> None:
        """Deselect all categories."""
        for checkbox in self.checkboxes.values():
            checkbox.setChecked(False)

    def get_selected_categories(self) -> list:
        """Returns a list of selected category IDs."""
        selected = []
        for category_id, checkbox in self.checkboxes.items():
            if checkbox.isChecked():
                selected.append(category_id)
        return selected

    def get_selected_categories_string(self) -> str:
        """Returns a comma-separated string of selected categories for yt-dlp."""
        selected = self.get_selected_categories()
        return ",".join(selected) if selected else ""
