"""
Settings overlay sub-application.

Provides interactive controls for adjusting reading settings with live preview.
"""

from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from PIL import Image

from .base import OverlaySubApplication
from ..gesture import GestureResponse, ActionType
from ..state import OverlayState
from ..html_generator import generate_settings_overlay

if TYPE_CHECKING:
    from ..application import EbookReader


class SettingsOverlay(OverlaySubApplication):
    """
    Settings overlay with live preview.

    Features:
    - Font size adjustment (increase/decrease)
    - Line spacing adjustment
    - Inter-block spacing adjustment
    - Word spacing adjustment
    - Live preview of changes on base page
    - Back to library button
    """

    def get_overlay_type(self) -> OverlayState:
        """Return SETTINGS overlay type."""
        return OverlayState.SETTINGS

    def open(self, base_page: Image.Image, **kwargs) -> Image.Image:
        """
        Open the settings overlay.

        Args:
            base_page: Current reading page to show underneath
            font_scale: Current font scale
            line_spacing: Current line spacing in pixels
            inter_block_spacing: Current inter-block spacing in pixels
            word_spacing: Current word spacing in pixels

        Returns:
            Composited image with settings overlay
        """
        font_scale = kwargs.get('font_scale', 1.0)
        line_spacing = kwargs.get('line_spacing', 5)
        inter_block_spacing = kwargs.get('inter_block_spacing', 15)
        word_spacing = kwargs.get('word_spacing', 0)

        # Calculate panel size (60% width, 70% height)
        panel_size = self._calculate_panel_size(0.6, 0.7)

        # Generate settings HTML with current values
        html = generate_settings_overlay(
            font_scale=font_scale,
            line_spacing=line_spacing,
            inter_block_spacing=inter_block_spacing,
            word_spacing=word_spacing,
            page_size=panel_size
        )

        # Render HTML to image
        overlay_panel = self.render_html_to_image(html, panel_size)

        # Cache for later use
        self._cached_base_page = base_page.copy()
        self._cached_overlay_image = overlay_panel

        # Composite and return
        return self.composite_overlay(base_page, overlay_panel)

    def handle_tap(self, x: int, y: int) -> GestureResponse:
        """
        Handle tap within settings overlay.

        Detects:
        - Setting adjustment controls (setting:action)
        - Back to library button (action:back_to_library)
        - Tap outside overlay (closes)

        Args:
            x, y: Screen coordinates of tap

        Returns:
            GestureResponse with appropriate action
        """
        import logging
        logger = logging.getLogger(__name__)
        logger.info(f"[SETTINGS_OVERLAY] Handling tap at ({x}, {y})")
        logger.info(f"[SETTINGS_OVERLAY] Panel offset: {self._overlay_panel_offset}, Panel size: {self._panel_size}")

        # Query the overlay to see what was tapped
        query_result = self.query_overlay_pixel(x, y)

        logger.info(f"[SETTINGS_OVERLAY] Query result: {query_result}")

        # If query failed (tap outside overlay panel), close it
        if query_result is None:
            logger.info(f"[SETTINGS_OVERLAY] Tap outside overlay panel, closing")
            return GestureResponse(ActionType.OVERLAY_CLOSED, {})

        # Check if tapped on a settings control link
        if query_result.get("is_interactive") and query_result.get("link_target"):
            link_target = query_result["link_target"]
            logger.info(f"[SETTINGS_OVERLAY] Found interactive link: {link_target}")

            # Parse "setting:action" format
            if link_target.startswith("setting:"):
                action = link_target.split(":", 1)[1]
                logger.info(f"[SETTINGS_OVERLAY] Applying setting change: {action}")
                return self._apply_setting_change(action)

            # Parse "action:command" format for other actions
            elif link_target.startswith("action:"):
                action = link_target.split(":", 1)[1]

                if action == "back_to_library":
                    logger.info(f"[SETTINGS_OVERLAY] Back to library clicked")
                    return GestureResponse(ActionType.BACK_TO_LIBRARY, {})

        # Tap inside overlay but not on interactive element - keep overlay open
        logger.info(f"[SETTINGS_OVERLAY] Tap on non-interactive area inside overlay, ignoring")
        return GestureResponse(ActionType.NONE, {})

    def refresh(self, updated_base_page: Image.Image,
                font_scale: float,
                line_spacing: int,
                inter_block_spacing: int,
                word_spacing: int = 0) -> Image.Image:
        """
        Refresh the settings overlay with updated values and background page.

        This is used for live preview when settings change - it updates both
        the background page (with new settings applied) and the overlay panel
        (with new values displayed).

        Args:
            updated_base_page: Updated reading page with new settings applied
            font_scale: Updated font scale
            line_spacing: Updated line spacing
            inter_block_spacing: Updated inter-block spacing
            word_spacing: Updated word spacing

        Returns:
            Composited image with updated settings overlay
        """
        # Calculate panel size (60% width, 70% height)
        panel_size = self._calculate_panel_size(0.6, 0.7)

        # Generate updated settings HTML
        html = generate_settings_overlay(
            font_scale=font_scale,
            line_spacing=line_spacing,
            inter_block_spacing=inter_block_spacing,
            word_spacing=word_spacing,
            page_size=panel_size
        )

        # Render HTML to image
        overlay_panel = self.render_html_to_image(html, panel_size)

        # Update caches
        self._cached_base_page = updated_base_page.copy()
        self._cached_overlay_image = overlay_panel

        # Composite and return
        return self.composite_overlay(updated_base_page, overlay_panel)

    def _apply_setting_change(self, action: str) -> GestureResponse:
        """
        Apply a setting change and refresh the overlay.

        Args:
            action: Setting action (e.g., "font_increase", "line_spacing_decrease")

        Returns:
            GestureResponse with SETTING_CHANGED action
        """
        # Apply the setting change via reader
        if action == "font_increase":
            self.reader.increase_font_size()
        elif action == "font_decrease":
            self.reader.decrease_font_size()
        elif action == "line_spacing_increase":
            new_spacing = self.reader.page_style.line_spacing + 2
            self.reader.set_line_spacing(new_spacing)
        elif action == "line_spacing_decrease":
            new_spacing = max(0, self.reader.page_style.line_spacing - 2)
            self.reader.set_line_spacing(new_spacing)
        elif action == "block_spacing_increase":
            new_spacing = self.reader.page_style.inter_block_spacing + 3
            self.reader.set_inter_block_spacing(new_spacing)
        elif action == "block_spacing_decrease":
            new_spacing = max(0, self.reader.page_style.inter_block_spacing - 3)
            self.reader.set_inter_block_spacing(new_spacing)
        elif action == "word_spacing_increase":
            new_spacing = self.reader.page_style.word_spacing + 2
            self.reader.set_word_spacing(new_spacing)
        elif action == "word_spacing_decrease":
            new_spacing = max(0, self.reader.page_style.word_spacing - 2)
            self.reader.set_word_spacing(new_spacing)

        # Re-render the base page with new settings applied
        # Must get directly from manager, not get_current_page() which returns overlay
        page = self.reader.manager.get_current_page()
        updated_page = page.render()

        # Refresh the settings overlay with updated values and page
        self.refresh(
            updated_base_page=updated_page,
            font_scale=self.reader.base_font_scale,
            line_spacing=self.reader.page_style.line_spacing,
            inter_block_spacing=self.reader.page_style.inter_block_spacing,
            word_spacing=self.reader.page_style.word_spacing
        )

        return GestureResponse(ActionType.SETTING_CHANGED, {
            "action": action,
            "font_scale": self.reader.base_font_scale,
            "line_spacing": self.reader.page_style.line_spacing,
            "inter_block_spacing": self.reader.page_style.inter_block_spacing,
            "word_spacing": self.reader.page_style.word_spacing
        })
