"""
Page operations mixin for pyPhotoAlbum
"""

from pyPhotoAlbum.decorators import ribbon_action, dialog_action
from pyPhotoAlbum.dialogs import PageSetupDialog
from pyPhotoAlbum.project import Page
from pyPhotoAlbum.page_layout import PageLayout


class PageOperationsMixin:
    """Mixin providing page management operations"""

    # Note: Previous/Next page navigation removed - now using scrollable multi-page view
    # User can scroll through all pages vertically

    @ribbon_action(label="Add Page", tooltip="Add a new page to the project", tab="Layout", group="Page")
    def add_page(self):
        """Add a new page to the project after the current page"""
        # Get the most visible page in viewport to determine insertion point
        current_page_index = self._get_most_visible_page_index()

        # Ensure index is valid, default to end if not
        if current_page_index < 0 or current_page_index >= len(self.project.pages):
            insert_index = len(self.project.pages)
        else:
            # Insert after the current page
            insert_index = current_page_index + 1

        # Create layout with project default size
        width_mm, height_mm = self.project.page_size_mm
        new_layout = PageLayout(width=width_mm, height=height_mm)

        # Calculate proper page number for the new page
        # The page_number represents the logical page number in the book
        if insert_index == 0:
            # Inserting at the beginning
            new_page_number = 1
        elif insert_index >= len(self.project.pages):
            # Inserting at the end - calculate based on last page
            if self.project.pages:
                last_page = self.project.pages[-1]
                # Add the count of pages the last page represents
                new_page_number = last_page.page_number + last_page.get_page_count()
            else:
                new_page_number = 1
        else:
            # Inserting in the middle - take the page number of the page that will come after
            new_page_number = self.project.pages[insert_index].page_number

        new_page = Page(layout=new_layout, page_number=new_page_number)
        # New pages are not manually sized - they use project defaults
        new_page.manually_sized = False

        # Insert the page at the calculated position
        self.project.add_page(new_page, index=insert_index)

        # Renumber all pages to ensure consistent numbering
        # Page numbers represent logical page numbers in the book
        current_page_num = 1
        for page in self.project.pages:
            page.page_number = current_page_num
            current_page_num += page.get_page_count()

        self.update_view()

        # Get display name for status message
        new_page_name = self.project.get_page_display_name(new_page)
        print(f"Added {new_page_name} at position {insert_index + 1} with size {width_mm}×{height_mm} mm")

    @ribbon_action(label="Page Setup", tooltip="Configure page size and settings", tab="Layout", group="Page")
    @dialog_action(dialog_class=PageSetupDialog, requires_pages=True)
    def page_setup(self, values):
        """
        Apply page setup configuration.

        This method contains only business logic. UI presentation
        is handled by PageSetupDialog and the dialog_action decorator.

        Args:
            values: Dictionary of values from the dialog
        """
        selected_page = values["selected_page"]
        selected_index = values["selected_index"]

        # Update project cover settings
        self.project.paper_thickness_mm = values["paper_thickness_mm"]
        self.project.cover_bleed_mm = values["cover_bleed_mm"]

        # Handle cover designation (only for first page)
        if selected_index == 0:
            was_cover = selected_page.is_cover
            is_cover = values["is_cover"]

            if was_cover != is_cover:
                selected_page.is_cover = is_cover
                self.project.has_cover = is_cover

                if is_cover:
                    # Calculate and set cover dimensions
                    self.project.update_cover_dimensions()
                    print(f"Page 1 designated as cover")
                else:
                    # Restore normal page size
                    selected_page.layout.size = self.project.page_size_mm
                    print(f"Cover removed from page 1")

        # Get new values
        width_mm = values["width_mm"]
        height_mm = values["height_mm"]

        # Don't allow manual size changes for covers
        if not selected_page.is_cover:
            # Check if size actually changed
            # For double spreads, compare with base width
            if selected_page.is_double_spread:
                old_base_width = (
                    selected_page.layout.base_width
                    if hasattr(selected_page.layout, "base_width")
                    else selected_page.layout.size[0] / 2
                )
                old_height = selected_page.layout.size[1]
                size_changed = old_base_width != width_mm or old_height != height_mm

                if size_changed:
                    # Update double spread
                    selected_page.layout.base_width = width_mm
                    selected_page.layout.size = (width_mm * 2, height_mm)
                    selected_page.manually_sized = True
                    print(
                        f"{self.project.get_page_display_name(selected_page)} "
                        f"(double spread) updated to {width_mm}×{height_mm} mm per page"
                    )
            else:
                old_size = selected_page.layout.size
                size_changed = old_size != (width_mm, height_mm)

                if size_changed:
                    # Update single page
                    selected_page.layout.size = (width_mm, height_mm)
                    selected_page.layout.base_width = width_mm
                    selected_page.manually_sized = True
                    print(
                        f"{self.project.get_page_display_name(selected_page)} " f"updated to {width_mm}×{height_mm} mm"
                    )

        # Update DPI settings
        self.project.working_dpi = values["working_dpi"]
        self.project.export_dpi = values["export_dpi"]

        # Apply to other pages based on scope
        # 0 = page only, 1 = non-manual pages, 2 = all pages
        apply_scope = values.get("apply_scope", 0)
        if apply_scope in (1, 2):
            self.project.page_size_mm = (width_mm, height_mm)
            print(f"Project default page size set to {width_mm}×{height_mm} mm")

            for page in self.project.pages:
                if page is selected_page or page.is_cover:
                    continue
                if apply_scope == 1 and page.manually_sized:
                    continue
                if page.is_double_spread:
                    page.layout.base_width = width_mm
                    page.layout.size = (width_mm * 2, height_mm)
                else:
                    page.layout.size = (width_mm, height_mm)
                    page.layout.base_width = width_mm

        self.update_view()

        # Build status message
        page_name = self.project.get_page_display_name(selected_page)
        if selected_page.is_cover:
            status_msg = f"{page_name} updated"
        else:
            status_msg = f"{page_name} size: {width_mm}×{height_mm} mm"
            if values.get("apply_scope", 0) in (1, 2):
                status_msg += " (set as default)"
        self.show_status(status_msg, 2000)

    @ribbon_action(
        label="Toggle Spread", tooltip="Toggle double page spread for current page", tab="Layout", group="Page"
    )
    def toggle_double_spread(self):
        """Toggle double spread for the current page"""
        if not self.project.pages:
            return

        # Try to get the most visible page in viewport, fallback to current_page_index
        page_index = self._get_most_visible_page_index()

        # Ensure index is valid
        if page_index < 0 or page_index >= len(self.project.pages):
            page_index = 0

        current_page = self.project.pages[page_index]

        # Toggle the state
        is_double = not current_page.is_double_spread
        current_page.is_double_spread = is_double

        # Mark as manually sized when toggling spread
        current_page.manually_sized = True

        # Update the page layout width
        current_width = current_page.layout.size[0]
        current_height = current_page.layout.size[1]

        # Get base width (might already be doubled)
        if hasattr(current_page.layout, "base_width"):
            base_width = current_page.layout.base_width
        else:
            # Assume current width is single if not marked as facing
            base_width = current_width / 2 if current_page.layout.is_facing_page else current_width

        # Set new width based on double spread state
        new_width = base_width * 2 if is_double else base_width
        current_page.layout.base_width = base_width
        current_page.layout.is_facing_page = is_double
        current_page.layout.size = (new_width, current_height)

        # Update display
        self.update_view()

        status = "enabled" if is_double else "disabled"
        page_name = self.project.get_page_display_name(current_page)
        self.show_status(f"{page_name}: Double spread {status}, width = {new_width:.0f}mm", 2000)
        print(f"{page_name}: Double spread {status}, width = {new_width}mm")

    @ribbon_action(label="Remove Page", tooltip="Remove the currently selected page", tab="Layout", group="Page")
    def remove_page(self):
        """Remove the currently selected page"""
        if len(self.project.pages) <= 1:
            self.show_warning("Cannot Remove", "Must have at least one page")
            print("Cannot remove page - must have at least one page")
            return

        # Get the most visible page in viewport
        page_index = self._get_most_visible_page_index()

        # Ensure index is valid
        if page_index < 0 or page_index >= len(self.project.pages):
            page_index = len(self.project.pages) - 1

        page_to_remove = self.project.pages[page_index]
        page_name = self.project.get_page_display_name(page_to_remove)

        # Remove the selected page
        self.project.remove_page(page_to_remove)

        # Renumber remaining pages to ensure consistent numbering
        # Page numbers represent logical page numbers in the book
        current_page_num = 1
        for page in self.project.pages:
            page.page_number = current_page_num
            current_page_num += page.get_page_count()

        # Update display
        self.update_view()

        print(f"Removed {page_name}, now have {len(self.project.pages)} pages")
