"""Qt widget for intercepting drag events and initiating native drag operations."""

import logging
from pathlib import Path
from typing import List, Optional

from PySide6.QtCore import QMimeData, Qt, QUrl, Signal
from PySide6.QtGui import QDrag
from PySide6.QtWidgets import QWidget

from webdrop_bridge.config import Config
from webdrop_bridge.core.url_converter import URLConverter
from webdrop_bridge.core.validator import PathValidator, ValidationError

logger = logging.getLogger(__name__)


class DragInterceptor(QWidget):
    """Widget that handles drag initiation for file paths or Azure URLs.

    Intercepts drag events from web content, converts Azure Blob Storage URLs
    to local paths, validates them, and initiates native Qt drag operations.

    Signals:
        drag_started: Emitted when a drag operation begins successfully
        drag_failed: Emitted when drag initiation fails
    """

    # Signals with string parameters
    drag_started = Signal(str, str)  # (url_or_path, local_path)
    drag_failed = Signal(str, str)   # (url_or_path, error_message)

    def __init__(self, config: Config, parent: Optional[QWidget] = None):
        """Initialize the drag interceptor.

        Args:
            config: Application configuration
            parent: Parent widget
        """
        super().__init__(parent)
        self.config = config
        self._validator = PathValidator(
            config.allowed_roots,
            check_file_exists=config.check_file_exists
        )
        self._url_converter = URLConverter(config)

    def handle_drag(self, text: str) -> bool:
        """Handle drag event from web view.

        Determines if the text is an Azure URL or file path, converts if needed,
        validates, and initiates native drag operation.

        Args:
            text: Azure Blob Storage URL or file path from web drag

        Returns:
            True if native drag was initiated, False otherwise
        """
        if not text or not text.strip():
            error_msg = "Empty drag text"
            logger.warning(error_msg)
            self.drag_failed.emit("", error_msg)
            return False

        text = text.strip()
        logger.debug(f"Handling drag for text: {text}")

        # Check if it's an Azure URL and convert to local path
        if self._url_converter.is_azure_url(text):
            local_path = self._url_converter.convert_url_to_path(text)
            if local_path is None:
                error_msg = "No mapping found for URL"
                logger.warning(f"{error_msg}: {text}")
                self.drag_failed.emit(text, error_msg)
                return False
            source_text = text
        else:
            # Treat as direct file path
            local_path = Path(text)
            source_text = text

        # Validate the path
        try:
            self._validator.validate(local_path)
        except ValidationError as e:
            error_msg = str(e)
            logger.warning(f"Validation failed for {local_path}: {error_msg}")
            self.drag_failed.emit(source_text, error_msg)
            return False

        logger.info(f"Initiating drag for: {local_path}")

        # Create native file drag
        success = self._create_native_drag(local_path)

        if success:
            self.drag_started.emit(source_text, str(local_path))
        else:
            error_msg = "Failed to create native drag operation"
            logger.error(error_msg)
            self.drag_failed.emit(source_text, error_msg)

        return success

    def _create_native_drag(self, file_path: Path) -> bool:
        """Create a native file system drag operation.

        Args:
            file_path: Local file path to drag

        Returns:
            True if drag was created successfully
        """
        try:
            # Create MIME data with file URL
            mime_data = QMimeData()
            file_url = QUrl.fromLocalFile(str(file_path))
            mime_data.setUrls([file_url])

            # Create and execute drag
            drag = QDrag(self)
            drag.setMimeData(mime_data)

            # Optional: Set a drag icon/pixmap if available
            # drag.setPixmap(...)

            # Start drag operation (blocks until drop or cancel)
            # Qt.CopyAction allows copying files
            result = drag.exec(Qt.DropAction.CopyAction)

            return result == Qt.DropAction.CopyAction

        except Exception as e:
            logger.exception(f"Error creating native drag: {e}")
            return False
