"""Resource preview widget for Resource Hacker.

This module provides the preview component for displaying resource content
including icons, text, and other resource types.
"""

from __future__ import annotations

import logging
import math
import struct

from PySide2.QtCore import Qt, Signal
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QGroupBox, QLabel, QScrollArea, QSizePolicy, QTextEdit, QVBoxLayout, QWidget

from ..models.icon_handler import IconHandler

logger = logging.getLogger(__name__)


class PreviewWidget(QWidget):
    """Widget for previewing resource content."""

    # Signals
    resource_loaded = Signal(dict)  # Emits resource info when loaded

    def __init__(self):
        super().__init__()
        self.current_resource: dict | None = None
        self._setup_ui()

    def _setup_ui(self):
        """Set up the preview widget UI."""
        layout = QVBoxLayout(self)
        layout.setContentsMargins(10, 10, 10, 10)
        layout.setSpacing(10)

        # Create scroll area for content
        self.scroll_area = QScrollArea()
        self.scroll_area.setWidgetResizable(True)
        self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)

        # Create content widget
        self.content_widget = QWidget()
        self.content_layout = QVBoxLayout(self.content_widget)
        self.content_layout.setContentsMargins(10, 10, 10, 10)

        self.scroll_area.setWidget(self.content_widget)
        layout.addWidget(self.scroll_area)

        # Initialize with welcome message
        self._show_welcome_message()

        logger.info("Preview widget initialized")

    def _show_welcome_message(self):
        """Show welcome message when no resource is selected."""
        # Clear existing content
        self._clear_content()

        # Create welcome label
        welcome_label = QLabel("Select a resource from the tree to preview its content")
        welcome_label.setAlignment(Qt.AlignCenter)
        welcome_label.setStyleSheet("""
            QLabel {
                font-size: 14px;
                color: #666666;
                padding: 50px;
            }
        """)

        self.content_layout.addWidget(welcome_label)
        self.content_layout.addStretch()

    def _clear_content(self):
        """Clear all content from the preview area."""
        while self.content_layout.count():
            child = self.content_layout.takeAt(0)
            if child.widget():
                child.widget().deleteLater()

    def display_resource(self, resource_info: dict):
        """Display a resource in the preview area."""
        try:
            self.current_resource = resource_info
            self._clear_content()

            # Add resource info header
            self._add_resource_header(resource_info)

            # Display content based on resource type
            resource_type = resource_info.get("type_id")
            data = resource_info.get("data", b"")

            if resource_type == 3:  # RT_ICON
                self._display_icon_resource(data)
            elif resource_type == 14:  # RT_GROUP_ICON
                self._display_group_icon_resource(data)
            elif resource_type == 6:  # RT_STRING
                self._display_string_resource(data)
            elif resource_type == 16:  # RT_VERSION
                self._display_version_resource(data)
            elif resource_type == 11:  # RT_MESSAGE
                self._display_message_resource(data)
            elif resource_type == 10:  # RT_HTML
                self._display_html_resource(data)
            elif resource_type == 24:  # RT_MANIFEST
                self._display_manifest_resource(data)
            else:
                self._display_binary_resource(data)

            self.resource_loaded.emit(resource_info)
            logger.info(f"Displayed resource: {resource_info.get('type_name', 'Unknown')}")

        except Exception as e:
            logger.error(f"Error displaying resource: {e}")
            self._display_error(f"Error displaying resource: {e!s}")

    def _add_resource_header(self, resource_info: dict):
        """Add resource information header."""
        header_group = QGroupBox("Resource Information")
        header_layout = QVBoxLayout(header_group)

        info_lines = [
            f"<b>Name:</b> {resource_info.get('name', 'Unknown')}",
            f"<b>Type:</b> {resource_info.get('type_name', 'Unknown')} (ID: {resource_info.get('type_id', 'Unknown')})",
            f"<b>Size:</b> {resource_info.get('size_formatted', '0 B')}",
            f"<b>Language:</b> {resource_info.get('language_id', 0)}",
            f"<b>Offset:</b> 0x{resource_info.get('offset', 0):x}",
        ]

        info_text = "<br>".join(info_lines)
        info_label = QLabel(info_text)
        info_label.setTextFormat(Qt.RichText)
        info_label.setWordWrap(True)

        header_layout.addWidget(info_label)
        self.content_layout.addWidget(header_group)

    def _display_icon_resource(self, data: bytes):
        """Display icon resource with enhanced preview."""
        try:
            logger.info(f"Displaying icon resource: {len(data)} bytes")

            # Try to extract icon using IconHandler
            image = IconHandler.extract_icon_from_resource(data)
            if image:
                logger.info(f"Successfully extracted icon: {image.size} {image.mode}")
                # Display the actual icon image
                self._display_image(image, "Icon Preview")

                # Add additional icon information
                self._display_icon_details(image, data)
            else:
                logger.warning("Icon extraction failed, showing binary fallback")
                # Fallback to binary display with ICO analysis
                self._display_binary_resource(data)
                self._display_ico_fallback_info(data)
        except Exception as e:
            logger.error(f"Error displaying icon resource: {e}")
            self._display_binary_resource(data)
            self._display_ico_fallback_info(data)

    def _display_group_icon_resource(self, data: bytes):
        """Display group icon resource."""
        try:
            # Parse group icon structure
            if len(data) >= 6:
                reserved, ico_type, count = struct.unpack("<HHH", data[:6])
                info_text = "Group Icon Information:<br>"
                info_text += f"• Reserved: {reserved}<br>"
                info_text += f"• Type: {ico_type}<br>"
                info_text += f"• Icon Count: {count}<br>"

                if count > 0 and len(data) >= 6 + (count * 14):
                    info_text += "<br>Icon Entries:<br>"
                    offset = 6
                    for i in range(min(count, 10)):  # Show first 10 entries
                        if offset + 14 <= len(data):
                            (
                                width,
                                height,
                                _color_count,
                                _reserved2,
                                planes,
                                bit_count,
                                _bytes_in_res,
                                _image_offset,
                            ) = struct.unpack("<BBBBHHII", data[offset : offset + 14])
                            info_text += f"  {i + 1}. {width}x{height} ({planes} planes, {bit_count} bpp)<br>"
                            offset += 14
                        else:
                            break

                if count > 10:
                    info_text += f"<br>... and {count - 10} more entries"

                self._display_text(info_text, "Group Icon Information")
            else:
                self._display_binary_resource(data)
        except Exception as e:
            logger.error(f"Error parsing group icon: {e}")
            self._display_binary_resource(data)

    def _display_string_resource(self, data: bytes):
        """Display string table resource."""
        try:
            # String tables are stored as UTF-16 strings
            if len(data) >= 2:
                try:
                    # Try to decode as UTF-16
                    text = data.decode("utf-16")
                    self._display_text(text, "String Table")
                except UnicodeDecodeError:
                    # Fallback to UTF-8
                    try:
                        text = data.decode("utf-8")
                        self._display_text(text, "String Table (UTF-8)")
                    except UnicodeDecodeError:
                        self._display_binary_resource(data)
            else:
                self._display_binary_resource(data)
        except Exception as e:
            logger.error(f"Error displaying string resource: {e}")
            self._display_binary_resource(data)

    def _display_version_resource(self, data: bytes):
        """Display version resource."""
        try:
            # Parse VS_VERSION_INFO structure (simplified)
            info_text = "Version Information:<br><br>"

            if len(data) >= 6:
                # VS_FIXEDFILEINFO structure
                (
                    signature,
                    _struct_version,
                    file_version_ms,
                    file_version_ls,
                    product_version_ms,
                    product_version_ls,
                    _file_flags_mask,
                    _file_flags,
                    file_os,
                    file_type,
                    _file_subtype,
                    _file_date_ms,
                    _file_date_ls,
                ) = struct.unpack("<IIIIIIIIIIIII", data[:52])

                info_text += f"• Signature: 0x{signature:x}<br>"
                info_text += (
                    f"• File Version: {file_version_ms >> 16}.{file_version_ms & 0xFFFF}."
                    f"{file_version_ls >> 16}.{file_version_ls & 0xFFFF}<br>"
                )
                info_text += (
                    f"• Product Version: {product_version_ms >> 16}.{product_version_ms & 0xFFFF}."
                    f"{product_version_ls >> 16}.{product_version_ls & 0xFFFF}<br>"
                )
                info_text += f"• File OS: {file_os}<br>"
                info_text += f"• File Type: {file_type}<br>"

            self._display_text(info_text, "Version Information")
        except Exception as e:
            logger.error(f"Error parsing version resource: {e}")
            self._display_binary_resource(data)

    def _display_message_resource(self, data: bytes):
        """Display message table resource."""
        try:
            info_text = "Message Table Information:<br>"
            info_text += f"• Size: {len(data)} bytes<br>"
            info_text += f"• First few bytes: {data[:32].hex()}<br>"

            self._display_text(info_text, "Message Table")
        except Exception as e:
            logger.error(f"Error displaying message resource: {e}")
            self._display_binary_resource(data)

    def _display_html_resource(self, data: bytes):
        """Display HTML resource."""
        try:
            # Try to decode as text
            try:
                text = data.decode("utf-8")
            except UnicodeDecodeError:
                try:
                    text = data.decode("utf-16")
                except UnicodeDecodeError:
                    self._display_binary_resource(data)
                    return

            self._display_text(text, "HTML Content", is_html=True)
        except Exception as e:
            logger.error(f"Error displaying HTML resource: {e}")
            self._display_binary_resource(data)

    def _display_manifest_resource(self, data: bytes):
        """Display manifest resource."""
        try:
            # Try to decode as XML
            try:
                text = data.decode("utf-8")
            except UnicodeDecodeError:
                try:
                    text = data.decode("utf-16")
                except UnicodeDecodeError:
                    self._display_binary_resource(data)
                    return

            self._display_text(text, "Manifest XML")
        except Exception as e:
            logger.error(f"Error displaying manifest resource: {e}")
            self._display_binary_resource(data)

    def _display_binary_resource(self, data: bytes):
        """Display binary resource with intelligent preview."""
        try:
            # Always show hex dump first
            hex_dump = self._create_hex_dump(data)
            self._display_text(hex_dump, "Binary Data (Hex Dump)")

            # Try to provide human-readable preview based on data content
            self._display_intelligent_preview(data)

        except Exception as e:
            logger.error(f"Error displaying binary resource: {e}")
            self._display_error(f"Error displaying binary data: {e!s}")

    def _display_image(self, image, title: str):
        """Display an image with enhanced styling."""
        try:
            # Create image label
            image_label = QLabel()
            image_label.setAlignment(Qt.AlignCenter)
            image_label.setStyleSheet("""
                background-color: white;
                border: 2px solid #3b82f6;
                border-radius: 8px;
                padding: 10px;
            """)

            # Convert PIL image to QPixmap using robust buffer method
            conversion_error = None
            try:
                from io import BytesIO

                from PIL import Image

                # Validate input image
                if not image or image.size[0] <= 0 or image.size[1] <= 0:
                    raise ValueError(f"Invalid image: {image}, size: {getattr(image, 'size', 'unknown')}")

                logger.debug(f"Converting image: mode={image.mode}, size={image.size}")

                buffer = BytesIO()

                # Handle different image modes properly for Qt compatibility
                try:
                    if image.mode == "RGBA":
                        # Convert RGBA to RGB with white background
                        rgb_image = Image.new("RGB", image.size, (255, 255, 255))
                        rgb_image.paste(image, mask=image.split()[-1])  # Use alpha channel as mask
                        rgb_image.save(buffer, format="PNG")
                    elif image.mode in ["P", "PA"]:  # Palette modes
                        image_rgb = image.convert("RGB")
                        image_rgb.save(buffer, format="PNG")
                    else:
                        image.save(buffer, format="PNG")
                except Exception as save_error:
                    logger.error(f"Failed to save image to buffer: {save_error}")
                    # Try with verification disabled
                    try:
                        image.save(buffer, format="PNG", optimize=False, compress_level=1)
                    except Exception as save_error2:
                        raise Exception(f"Image save failed: {save_error2}") from save_error2

                # Check buffer content
                buffer_data = buffer.getvalue()
                if not buffer_data:
                    raise Exception("Buffer is empty after image save")

                logger.debug(f"Buffer size: {len(buffer_data)} bytes")

                # Load into QPixmap with validation
                pixmap = QPixmap()
                if not pixmap.loadFromData(buffer_data):
                    # Try alternative loading methods
                    logger.warning("Primary load failed, trying alternative methods")

                    # Method 1: Try loading as different format
                    temp_pixmap = QPixmap()
                    if temp_pixmap.loadFromData(buffer_data, "PNG"):
                        pixmap = temp_pixmap
                    else:
                        # Method 2: Create from QImage
                        from PySide2.QtGui import QImage

                        qimage = QImage.fromData(buffer_data)
                        if not qimage.isNull():
                            pixmap = QPixmap.fromImage(qimage)
                        else:
                            raise Exception("All loading methods failed")

                logger.debug(
                    f"Successfully converted {image.mode} image {image.size} "
                    f"to pixmap {pixmap.width()}x{pixmap.height()}"
                )

            except Exception as e:
                logger.error(f"Failed to convert PIL image to QPixmap: {e}")
                logger.error(
                    f"Image details - mode: {getattr(image, 'mode', 'unknown')}, "
                    f"size: {getattr(image, 'size', 'unknown')}"
                )
                conversion_error = str(e)
                # Create gray placeholder pixmap
                pixmap = QPixmap(100, 100)
                pixmap.fill(Qt.gray)

            # Scale image to fit with better quality
            max_size = 300  # Reduced for better layout
            if pixmap.width() > max_size or pixmap.height() > max_size:
                pixmap = pixmap.scaled(max_size, max_size, Qt.KeepAspectRatio, Qt.SmoothTransformation)

            image_label.setPixmap(pixmap)

            # Create group box with enhanced styling
            image_group = QGroupBox(title)
            image_group.setStyleSheet("""
                QGroupBox {
                    font-weight: bold;
                    font-size: 14px;
                    border: 2px solid #3b82f6;
                    border-radius: 10px;
                    margin-top: 1ex;
                    padding: 10px;
                }
                QGroupBox::title {
                    subcontrol-origin: margin;
                    left: 10px;
                    padding: 0 5px 0 5px;
                    color: #3b82f6;
                }
            """)

            image_layout = QVBoxLayout(image_group)
            image_layout.addWidget(image_label)
            image_layout.setAlignment(Qt.AlignCenter)

            # Add error message if conversion failed
            if conversion_error:
                error_label = QLabel(f"⚠️ 图像显示错误: {conversion_error}")
                error_label.setStyleSheet("""
                    QLabel {
                        color: #cc0000;
                        background-color: #ffeeee;
                        border: 1px solid #ff6666;
                        padding: 8px;
                        border-radius: 4px;
                        font-size: 12px;
                        margin-top: 5px;
                    }
                """)
                error_label.setWordWrap(True)
                error_label.setAlignment(Qt.AlignCenter)
                image_layout.addWidget(error_label)

            self.content_layout.addWidget(image_group)
            self.content_layout.addStretch()

        except Exception as e:
            logger.error(f"Error displaying image: {e}")
            self._display_error(f"Error displaying image: {e!s}")

    def _display_text(self, text: str, title: str, is_html: bool = False):
        """Display text content."""
        try:
            # Create text display
            text_edit = QTextEdit()
            text_edit.setReadOnly(True)
            text_edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

            if is_html:
                text_edit.setHtml(text)
            else:
                text_edit.setPlainText(text)

            # Limit height for small content
            if text.count("\n") < 20:
                text_edit.setMaximumHeight(300)

            # Create group box
            text_group = QGroupBox(title)
            text_layout = QVBoxLayout(text_group)
            text_layout.addWidget(text_edit)

            self.content_layout.addWidget(text_group)
            self.content_layout.addStretch()

        except Exception as e:
            logger.error(f"Error displaying text: {e}")
            self._display_error(f"Error displaying text: {e!s}")

    def _display_error(self, message: str):
        """Display error message."""
        error_label = QLabel(f"Error: {message}")
        error_label.setStyleSheet("""
            QLabel {
                color: #cc0000;
                background-color: #ffeeee;
                border: 1px solid #cc0000;
                padding: 10px;
                border-radius: 4px;
            }
        """)
        error_label.setWordWrap(True)

        self.content_layout.addWidget(error_label)
        self.content_layout.addStretch()

    def _create_hex_dump(self, data: bytes, bytes_per_line: int = 16) -> str:
        """Create a hex dump of binary data."""
        if not data:
            return "Empty data"

        lines = []
        for i in range(0, len(data), bytes_per_line):
            # Address
            line = f"{i:08x}: "

            # Hex bytes
            hex_part = ""
            ascii_part = ""

            for j in range(bytes_per_line):
                if i + j < len(data):
                    byte = data[i + j]
                    hex_part += f"{byte:02x} "
                    ascii_part += chr(byte) if 32 <= byte <= 126 else "."
                else:
                    hex_part += "   "
                    ascii_part += " "

            line += f"{hex_part:<48} |{ascii_part}|"
            lines.append(line)

        # Add summary
        lines.append("")
        lines.append(f"Total size: {len(data)} bytes")

        return "\n".join(lines)

    def _display_intelligent_preview(self, data: bytes):
        """Provide intelligent human-readable preview based on data content."""
        if not data:
            return

        # Try to detect and display different data types

        # 1. Check for ICO files
        if self._is_likely_ico(data):
            self._display_ico_preview(data)
            return

        # 2. Check for XML/Manifest content
        if self._is_likely_xml(data):
            self._display_xml_preview(data)
            return

        # 3. Check for JSON content
        if self._is_likely_json(data):
            self._display_json_preview(data)
            return

        # 4. Check for text content
        if self._is_likely_text(data):
            self._display_text_preview(data)
            return

        # 5. Check for structured data patterns
        self._display_structured_data_info(data)

    def _is_likely_ico(self, data: bytes) -> bool:
        """Check if data looks like an ICO file."""
        if len(data) < 6:
            return False

        # Check ICO header: reserved(2) + type(2) + count(2)
        try:
            reserved, ico_type, count = struct.unpack("<HHH", data[:6])
            return reserved == 0 and ico_type == 1 and count > 0 and count <= 100
        except struct.error:
            return False

    def _is_likely_xml(self, data: bytes) -> bool:
        """Check if data looks like XML content."""
        if len(data) < 10:
            return False

        # Try to decode as text and look for XML patterns
        try:
            # Try UTF-8 first
            text = data[: min(1000, len(data))].decode("utf-8")
        except UnicodeDecodeError:
            try:
                # Try UTF-16
                text = data[: min(1000, len(data))].decode("utf-16")
            except UnicodeDecodeError:
                return False

        # Look for XML indicators
        text_lower = text.lower().strip()
        return "<?xml" in text_lower or ("<" in text_lower and ">" in text_lower and not text_lower.startswith("<html"))

    def _is_likely_json(self, data: bytes) -> bool:
        """Check if data looks like JSON content."""
        if len(data) < 10:
            return False

        try:
            text = data.decode("utf-8").strip()
            return (text.startswith("{") and text.endswith("}")) or (text.startswith("[") and text.endswith("]"))
        except UnicodeDecodeError:
            return False

    def _is_likely_text(self, data: bytes) -> bool:
        """Check if data is likely text content."""
        if len(data) == 0:
            return False

        # Check if most bytes are printable ASCII or common text characters
        printable_chars = sum(1 for b in data if 32 <= b <= 126 or b in (9, 10, 13))
        return printable_chars / len(data) > 0.7

    def _display_ico_preview(self, data: bytes):
        """Display ICO file information preview."""
        try:
            # Parse basic ICO information
            _reserved, ico_type, count = struct.unpack("<HHH", data[:6])

            info_lines = [
                "<b>ICO File Detected</b>",
                f"• Icon Count: {count}",
                f"• File Type: {'Icon' if ico_type == 1 else 'Cursor' if ico_type == 2 else f'Unknown ({ico_type})'}",
                f"• Total Size: {len(data)} bytes",
                "",
            ]

            # Parse icon directory entries
            if count > 0 and len(data) >= 6 + (count * 16):
                info_lines.append("<b>Icon Details:</b>")
                offset = 6
                for i in range(min(count, 5)):  # Show first 5 icons
                    if offset + 16 <= len(data):
                        entry_data = data[offset : offset + 16]
                        (
                            width,
                            height,
                            _color_count,
                            _reserved2,
                            planes,
                            bit_count,
                            _bytes_in_res,
                            _image_offset,
                        ) = struct.unpack("<BBBBHHII", entry_data)

                        display_width = width if width > 0 else 256
                        display_height = height if height > 0 else 256

                        info_lines.append(
                            f"  {i + 1}. {display_width}x{display_height}px, {bit_count}bpp, {planes} plane(s)"
                        )
                        offset += 16
                    else:
                        break

                if count > 5:
                    info_lines.append(f"  ... and {count - 5} more icons")

            info_text = "<br>".join(info_lines)
            self._display_text(info_text, "ICO File Information", is_html=True)

        except Exception as e:
            logger.error(f"Error parsing ICO preview: {e}")
            self._display_text("Unable to parse ICO file structure", "ICO Preview Error")

    def _display_xml_preview(self, data: bytes):
        """Display XML content preview."""
        try:
            # Decode XML content
            try:
                xml_content = data.decode("utf-8")
            except UnicodeDecodeError:
                xml_content = data.decode("utf-16")

            # Create a formatted preview
            lines = xml_content.strip().split("\n")
            preview_lines = []

            # Show first few lines with line numbers
            for i, line in enumerate(lines[:15]):
                stripped_line = line.strip()
                if stripped_line:
                    preview_lines.append(f"{i + 1:3d}: {stripped_line}")
                    if len(preview_lines) >= 10:  # Limit preview length
                        break

            if len(lines) > 15:
                preview_lines.append(f"... ({len(lines)} total lines)")

            preview_text = "\n".join(preview_lines)
            self._display_text(preview_text, "XML Content Preview")

        except Exception as e:
            logger.error(f"Error parsing XML preview: {e}")
            self._display_text("Unable to parse XML content", "XML Preview Error")

    def _display_json_preview(self, data: bytes):
        """Display JSON content preview."""
        try:
            import json

            json_content = data.decode("utf-8")
            parsed = json.loads(json_content)

            # Create a pretty-printed preview
            preview = json.dumps(parsed, indent=2, ensure_ascii=False)
            lines = preview.split("\n")

            # Show first few lines
            preview_lines = lines[:15]
            if len(lines) > 15:
                preview_lines.append(f"... ({len(lines)} total lines)")

            preview_text = "\n".join(preview_lines)
            self._display_text(preview_text, "JSON Content Preview")

        except Exception as e:
            logger.error(f"Error parsing JSON preview: {e}")
            self._display_text("Unable to parse JSON content", "JSON Preview Error")

    def _display_text_preview(self, data: bytes):
        """Display text content preview."""
        try:
            # Try different encodings
            encodings = ["utf-8", "utf-16", "gbk", "ascii"]
            text_content = None
            used_encoding = None

            for encoding in encodings:
                try:
                    text_content = data.decode(encoding)
                    used_encoding = encoding
                    break
                except UnicodeDecodeError:
                    continue

            if text_content is None:
                self._display_text(
                    "Unable to decode text content with common encodings",
                    "Text Preview Error",
                )
                return

            # Create preview with line numbers
            lines = text_content.split("\n")
            preview_lines = []

            for i, line in enumerate(lines[:15]):
                stripped_line = line.rstrip()
                if stripped_line or i < len(lines) - 1:  # Show empty lines except trailing ones
                    preview_lines.append(f"{i + 1:3d}: {stripped_line}")
                    if len(preview_lines) >= 10:
                        break

            if len(lines) > 15:
                preview_lines.append(f"... ({len(lines)} total lines)")

            preview_text = "\n".join(preview_lines)
            title = f"Text Content Preview ({used_encoding.upper()})"
            self._display_text(preview_text, title)

        except Exception as e:
            logger.error(f"Error parsing text preview: {e}")
            self._display_text("Unable to parse text content", "Text Preview Error")

    def _display_icon_details(self, image, data: bytes):
        """Display detailed information about icon resource."""
        try:
            info_lines = [
                "<b>Icon Details</b>",
                f"• Dimensions: {image.width} x {image.height} pixels",
                f"• Color Mode: {image.mode}",
                f"• File Size: {len(data)} bytes",
                f"• Aspect Ratio: {image.width / image.height:.2f}:1",
                "",
            ]

            # Add color depth information
            if image.mode == "RGBA":
                info_lines.append("• Color Depth: 32-bit (RGBA)")
            elif image.mode == "RGB":
                info_lines.append("• Color Depth: 24-bit (RGB)")
            elif image.mode == "P":
                info_lines.append("• Color Depth: 8-bit (Palette)")
            else:
                info_lines.append(f"• Color Mode: {image.mode}")

            # Check for transparency
            if image.mode == "RGBA":
                # Check if there are actually transparent pixels
                has_transparency = False
                if hasattr(image, "getchannel"):
                    try:
                        alpha_channel = image.getchannel("A")
                        has_transparency = any(pixel < 255 for pixel in alpha_channel.getdata())
                    except Exception:
                        pass

                if has_transparency:
                    info_lines.append("• Transparency: Present")
                else:
                    info_lines.append("• Transparency: None (fully opaque)")

            info_text = "<br>".join(info_lines)
            self._display_text(info_text, "Icon Properties", is_html=True)

        except Exception as e:
            logger.error(f"Error displaying icon details: {e}")

    def _display_ico_fallback_info(self, data: bytes):
        """Display ICO information when direct image extraction fails."""
        try:
            if self._is_likely_ico(data):
                # Parse ICO header even if image extraction failed
                try:
                    _reserved, ico_type, count = struct.unpack("<HHH", data[:6])
                    info_lines = [
                        "<b>ICO File Information</b>",
                        f"• File Type: {self._get_ico_type_description(ico_type)}",
                        f"• Icon Count: {count}",
                        f"• File Size: {len(data)} bytes",
                        "• <font color='red'>Warning: Could not extract image data</font>",
                        "• This may indicate a corrupted or unsupported ICO format",
                    ]

                    info_text = "<br>".join(info_lines)
                    self._display_text(info_text, "ICO Analysis", is_html=True)
                except struct.error:
                    self._display_text("Invalid ICO file structure", "ICO Analysis Error")

        except Exception as e:
            logger.error(f"Error displaying ICO fallback info: {e}")

    def _display_structured_data_info(self, data: bytes):
        """Display information about structured data patterns."""
        try:
            info_lines = [
                "<b>Data Analysis</b>",
                f"• Size: {len(data)} bytes",
                f"• Entropy: {self._calculate_entropy(data):.2f} bits/byte",
                f"• Printable Characters: {self._get_printable_ratio(data):.1%}",
                "",
            ]

            # Check for common file signatures
            signatures = self._detect_file_signatures(data)
            if signatures:
                info_lines.append("<b>Possible File Types:</b>")
                for sig in signatures[:3]:  # Show top 3 matches
                    info_lines.append(f"• {sig}")

            # Show first few bytes as hex
            if len(data) > 0:
                info_lines.append("")
                info_lines.append("<b>Header Bytes:</b>")
                header_hex = " ".join(f"{b:02x}" for b in data[:16])
                info_lines.append(f"  {header_hex}")
                if len(data) > 16:
                    info_lines.append("  ...")

            info_text = "<br>".join(info_lines)
            self._display_text(info_text, "Data Structure Analysis", is_html=True)

        except Exception as e:
            logger.error(f"Error analyzing data structure: {e}")

    def _calculate_entropy(self, data: bytes) -> float:
        """Calculate entropy of data (0-8 bits/byte)."""
        if not data:
            return 0.0

        # Count byte frequencies
        frequency = {}
        for byte in data:
            frequency[byte] = frequency.get(byte, 0) + 1

        # Calculate entropy
        entropy = 0.0
        data_len = len(data)
        for count in frequency.values():
            probability = count / data_len
            entropy -= probability * math.log2(probability)

        return entropy

    def _get_printable_ratio(self, data: bytes) -> float:
        """Get ratio of printable ASCII characters."""
        if not data:
            return 0.0
        printable_count = sum(1 for b in data if 32 <= b <= 126)
        return printable_count / len(data)

    def _detect_file_signatures(self, data: bytes) -> list:
        """Detect possible file types based on signatures."""
        signatures = {
            b"MZ": "DOS/Windows executable",
            b"PE\x00\x00": "Windows PE executable",
            b"\x89PNG\r\n\x1a\n": "PNG image",
            b"\xff\xd8\xff": "JPEG image",
            b"GIF87a": "GIF image (87a)",
            b"GIF89a": "GIF image (89a)",
            b"BM": "BMP image",
            b"\x00\x00\x01\x00": "ICO file",
            b"RIFF": "RIFF container (WAV/AVI)",
            b"PK\x03\x04": "ZIP archive",
            b"\x1f\x8b": "GZIP compressed",
            b"\xfd7zXZ\x00": "7-Zip archive",
            b"\x52\x61\x72\x21\x1a\x07\x00": "RAR archive",
        }

        matches = []
        for signature, description in signatures.items():
            if data.startswith(signature):
                matches.append(description)

        return matches

    def get_current_resource(self) -> dict | None:
        """Get the currently displayed resource."""
        return self.current_resource

    def clear_preview(self):
        """Clear the current preview."""
        self.current_resource = None
        self._show_welcome_message()
