"""Route handlers and router initialization for the media gallery."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/routes/handlers.ipynb.

# %% auto #0
__all__ = ['GalleryState', 'init_router']

# %% ../../nbs/routes/handlers.ipynb #c3d4e5f6
from dataclasses import dataclass, field
from typing import Any, Callable, List, Optional

from fasthtml.common import APIRouter

from cjm_file_discovery.core.models import FileInfo, FileType
from cjm_fasthtml_media_gallery.core.config import (
    GalleryConfig, GalleryCallbacks, ViewMode, SelectionMode
)
from ..components.gallery import render_media_gallery
from ..components.preview import render_preview_content
from ..components.players import is_text_previewable, read_text_content
from ..serving.mounter import DirectoryMounter

# %% ../../nbs/routes/handlers.ipynb #e5f6a7b8
@dataclass
class GalleryState:
    """State for the media gallery."""
    view_mode: ViewMode = ViewMode.GRID            # Current view mode
    current_page: int = 1                          # Current page
    active_types: List[FileType] = field(default_factory=list)  # Active type filters
    selected_paths: List[str] = field(default_factory=list)  # Selected file paths
    preview_path: Optional[str] = None             # Currently previewed file
    
    def to_dict(self) -> dict:  # Serializable dictionary
        """Convert to serializable dictionary."""
        return {
            "view_mode": self.view_mode.value,
            "current_page": self.current_page,
            "active_types": [t.value for t in self.active_types],
            "selected_paths": self.selected_paths,
            "preview_path": self.preview_path,
        }
    
    @classmethod
    def from_dict(
        cls,
        data: dict  # Dictionary data
    ) -> "GalleryState":  # GalleryState instance
        """Create from dictionary."""
        return cls(
            view_mode=ViewMode(data.get("view_mode", "grid")),
            current_page=data.get("current_page", 1),
            active_types=[FileType(t) for t in data.get("active_types", [])],
            selected_paths=data.get("selected_paths", []),
            preview_path=data.get("preview_path"),
        )

# %% ../../nbs/routes/handlers.ipynb #h8c9d0e1
def _handle_toggle_view(
    state_getter: Callable[[], GalleryState],  # Function to get current state
    state_setter: Callable[[GalleryState], None],  # Function to save state
    view_mode: str,                           # New view mode
    render_fn: Callable[[GalleryState], Any], # Function to render gallery
) -> Any:  # Rendered gallery component
    """Handle view mode toggle."""
    state = state_getter()
    state.view_mode = ViewMode(view_mode)
    state_setter(state)
    return render_fn(state)

# %% ../../nbs/routes/handlers.ipynb #i9d0e1f2
def _handle_filter_type(
    config: GalleryConfig,                    # Gallery configuration
    state_getter: Callable[[], GalleryState], # Function to get current state
    state_setter: Callable[[GalleryState], None],  # Function to save state
    file_type: str,                           # File type to toggle
    toggle: str,                              # "true" to toggle, else set exclusively
    render_fn: Callable[[GalleryState], Any], # Function to render gallery
) -> Any:  # Rendered gallery component
    """Handle type filter change."""
    state = state_getter()
    target_type = FileType(file_type)
    
    if toggle.lower() == "true":
        # Toggle the type
        if target_type in state.active_types:
            # Don't allow deselecting if it's the only one
            if len(state.active_types) > 1:
                state.active_types.remove(target_type)
        else:
            state.active_types.append(target_type)
    else:
        # Set exclusively
        state.active_types = [target_type]
    
    # Reset to first page when filter changes
    state.current_page = 1
    state_setter(state)
    return render_fn(state)

# %% ../../nbs/routes/handlers.ipynb #j0e1f2g3
def _handle_select(
    config: GalleryConfig,                    # Gallery configuration
    state_getter: Callable[[], GalleryState], # Function to get current state
    state_setter: Callable[[GalleryState], None],  # Function to save state
    callbacks: Optional[GalleryCallbacks],    # Optional callbacks
    path: str,                                # File path to select/deselect
    render_fn: Callable[[GalleryState], Any], # Function to render gallery
) -> Any:  # Rendered gallery component
    """Handle file selection."""
    # Validate selection if callback provided
    if callbacks and callbacks.validate_selection:
        valid, error = callbacks.validate_selection(path)
        if not valid:
            state = state_getter()
            return render_fn(state)
    
    state = state_getter()
    
    # Handle selection based on mode
    if config.selection_mode == SelectionMode.SINGLE:
        if path in state.selected_paths:
            state.selected_paths = []
        else:
            state.selected_paths = [path]
    elif config.selection_mode == SelectionMode.MULTIPLE:
        if path in state.selected_paths:
            state.selected_paths.remove(path)
        else:
            state.selected_paths.append(path)
            # Check max selections
            if config.max_selections and len(state.selected_paths) > config.max_selections:
                state.selected_paths = state.selected_paths[-config.max_selections:]
    
    state_setter(state)
    
    # Call callbacks
    if callbacks and callbacks.on_select:
        callbacks.on_select(path)
    if callbacks and callbacks.on_selection_change:
        callbacks.on_selection_change(state.selected_paths)
    
    return render_fn(state)

# %% ../../nbs/routes/handlers.ipynb #k1f2g3h4
def _handle_page(
    state_getter: Callable[[], GalleryState], # Function to get current state
    state_setter: Callable[[GalleryState], None],  # Function to save state
    page: int,                                # New page number
    render_fn: Callable[[GalleryState], Any], # Function to render gallery
) -> Any:  # Rendered gallery component
    """Handle page change."""
    state = state_getter()
    state.current_page = max(1, page)
    state_setter(state)
    return render_fn(state)

# %% ../../nbs/routes/handlers.ipynb #l2g3h4i5
def _handle_preview(
    files_getter: Callable[[], List[FileInfo]],  # Function to get files
    state_getter: Callable[[], GalleryState],  # Function to get current state
    config: GalleryConfig,  # Gallery configuration
    mounter: DirectoryMounter,  # File URL mounter
    callbacks: Optional[GalleryCallbacks],  # Optional callbacks
    path: str,  # File path to preview
    prev_url: str,  # URL for previous handler
    next_url: str,  # URL for next handler
) -> Any:  # Preview content
    """Handle preview request."""
    state = state_getter()
    all_files = files_getter()
    
    # Filter files by active types (same as gallery view)
    active_types = state.active_types or config.filter.enabled_types
    files = [f for f in all_files if f.file_type in active_types]
    
    # Find the file
    file_info = None
    file_index = -1
    for i, f in enumerate(files):
        if f.path == path:
            file_info = f
            file_index = i
            break
    
    if file_info is None:
        return None
    
    # Get file URL
    file_url = mounter.get_url(path) or path
    
    # Determine prev/next based on filtered list
    has_prev = file_index > 0
    has_next = file_index < len(files) - 1
    
    # Read text content if applicable
    text_content = None
    text_error = None
    if is_text_previewable(file_info):
        text_content, text_error = read_text_content(path)
    
    # Call callback
    if callbacks and callbacks.on_preview:
        callbacks.on_preview(path)
    
    return render_preview_content(
        file_info=file_info,
        file_url=file_url,
        config=config,
        prev_url=prev_url,
        next_url=next_url,
        has_prev=has_prev,
        has_next=has_next,
        modal_id=config.preview_modal_id,
        text_content=text_content,
        text_error=text_error,
    )

# %% ../../nbs/routes/handlers.ipynb #m3h4i5j6
def _handle_preview_nav(
    files_getter: Callable[[], List[FileInfo]], # Function to get files
    state_getter: Callable[[], GalleryState],   # Function to get current state
    config: GalleryConfig,                    # Gallery configuration
    mounter: DirectoryMounter,                # File URL mounter
    callbacks: Optional[GalleryCallbacks],    # Optional callbacks
    current_path: str,                        # Current file path
    direction: int,                           # -1 for prev, +1 for next
    prev_url: str,                            # URL for previous handler
    next_url: str,                            # URL for next handler
) -> Any:  # Preview content
    """Handle preview navigation."""
    state = state_getter()
    all_files = files_getter()
    
    # Filter files by active types (same as gallery view)
    active_types = state.active_types or config.filter.enabled_types
    files = [f for f in all_files if f.file_type in active_types]
    
    # Find current index in filtered list
    current_index = -1
    for i, f in enumerate(files):
        if f.path == current_path:
            current_index = i
            break
    
    if current_index == -1:
        return None
    
    # Calculate new index
    new_index = current_index + direction
    if new_index < 0 or new_index >= len(files):
        return None
    
    new_file = files[new_index]
    return _handle_preview(
        files_getter, state_getter, config, mounter, callbacks,
        new_file.path, prev_url, next_url
    )

# %% ../../nbs/routes/handlers.ipynb #o5j6k7l8
def init_router(
    config: GalleryConfig,                              # Gallery configuration
    files_getter: Callable[[], List[FileInfo]],         # Function to get files
    mounter: DirectoryMounter,                          # File URL mounter
    state_getter: Callable[[], GalleryState],           # Function to get current state
    state_setter: Callable[[GalleryState], None],       # Function to save state
    route_prefix: str = "/gallery",                     # Route prefix for all gallery routes
    callbacks: Optional[GalleryCallbacks] = None,       # Optional callbacks
) -> APIRouter:  # Configured APIRouter with all gallery routes
    """Initialize and return an APIRouter with all gallery routes."""
    router = APIRouter(prefix=route_prefix)
    
    def _render_gallery(state: GalleryState) -> Any:
        """Helper to render gallery with current state."""
        files = files_getter()
        return render_media_gallery(
            files=files,
            config=config,
            view_mode=state.view_mode,
            active_types=state.active_types or config.filter.enabled_types,
            get_file_url=mounter.create_url_getter(),
            selected_paths=state.selected_paths,
            toggle_view_url=toggle_view.to(),
            filter_url=filter_type.to(),
            preview_url=preview.to(),
            select_url=select.to() if config.selection_mode != SelectionMode.NONE else None,
            page_url=page.to(),
            current_page=state.current_page,
        )
    
    # -------------------------------------------------------------------------
    # View and Filter Routes
    # -------------------------------------------------------------------------
    
    @router
    def toggle_view(view_mode: str) -> Any:
        """Toggle between grid and list view."""
        return _handle_toggle_view(
            state_getter=state_getter,
            state_setter=state_setter,
            view_mode=view_mode,
            render_fn=_render_gallery,
        )
    
    @router
    def filter_type(file_type: str, toggle: str = "true") -> Any:
        """Filter by file type."""
        return _handle_filter_type(
            config=config,
            state_getter=state_getter,
            state_setter=state_setter,
            file_type=file_type,
            toggle=toggle,
            render_fn=_render_gallery,
        )
    
    # -------------------------------------------------------------------------
    # Selection Routes
    # -------------------------------------------------------------------------
    
    @router
    def select(path: str) -> Any:
        """Select or deselect a file."""
        return _handle_select(
            config=config,
            state_getter=state_getter,
            state_setter=state_setter,
            callbacks=callbacks,
            path=path,
            render_fn=_render_gallery,
        )
    
    # -------------------------------------------------------------------------
    # Pagination Routes
    # -------------------------------------------------------------------------
    
    @router
    def page(page: int) -> Any:
        """Change page."""
        return _handle_page(
            state_getter=state_getter,
            state_setter=state_setter,
            page=page,
            render_fn=_render_gallery,
        )
    
    # -------------------------------------------------------------------------
    # Preview Routes
    # -------------------------------------------------------------------------
    
    @router
    def preview(path: str) -> Any:
        """Open preview for a file."""
        return _handle_preview(
            files_getter=files_getter,
            state_getter=state_getter,
            config=config,
            mounter=mounter,
            callbacks=callbacks,
            path=path,
            prev_url=preview_prev.to(),
            next_url=preview_next.to(),
        )
    
    @router
    def preview_prev(path: str) -> Any:
        """Navigate to previous file in preview."""
        return _handle_preview_nav(
            files_getter=files_getter,
            state_getter=state_getter,
            config=config,
            mounter=mounter,
            callbacks=callbacks,
            current_path=path,
            direction=-1,
            prev_url=preview_prev.to(),
            next_url=preview_next.to(),
        )
    
    @router
    def preview_next(path: str) -> Any:
        """Navigate to next file in preview."""
        return _handle_preview_nav(
            files_getter=files_getter,
            state_getter=state_getter,
            config=config,
            mounter=mounter,
            callbacks=callbacks,
            current_path=path,
            direction=1,
            prev_url=preview_prev.to(),
            next_url=preview_next.to(),
        )
    
    return router
