"""UI components for workflow step rendering (plugin selection, file selection, confirmation)"""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/components/steps.ipynb.

# %% auto 0
__all__ = ['render_plugin_config_form', 'render_plugin_details_route', 'render_plugin_selection', 'render_file_selection',
           'render_confirmation']

# %% ../../nbs/components/steps.ipynb 3
from typing import Dict, Any, List, Optional, TYPE_CHECKING
from urllib.parse import quote
from fasthtml.common import *
from fasthtml.svg import Svg, Path as SvgPath, Circle
from cjm_fasthtml_interactions.core.context import InteractionContext
from cjm_fasthtml_daisyui.components.actions.button import btn, btn_colors, btn_sizes, btn_styles
from cjm_fasthtml_daisyui.components.data_display.card import card, card_body, card_title
from cjm_fasthtml_daisyui.components.data_display.badge import badge, badge_colors, badge_sizes, badge_styles
from cjm_fasthtml_daisyui.components.data_display.collapse import collapse, collapse_title, collapse_content, collapse_modifiers
from cjm_fasthtml_daisyui.components.data_display.stat import stat, stat_title, stat_value, stat_desc, stats
from cjm_fasthtml_daisyui.components.data_display.table import table, table_modifiers
from cjm_fasthtml_daisyui.components.data_input.radio import radio
from cjm_fasthtml_daisyui.components.data_input.select import select
from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui, text_dui, stroke_dui, border_dui
from cjm_fasthtml_daisyui.utilities.border_radius import border_radius
from cjm_fasthtml_tailwind.utilities.borders import border
from cjm_fasthtml_tailwind.utilities.spacing import p, m
from cjm_fasthtml_tailwind.utilities.sizing import w, max_h, h
from cjm_fasthtml_tailwind.utilities.typography import font_size, font_weight, text_align
from cjm_fasthtml_tailwind.utilities.layout import overflow
from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import flex_display, justify, items
from cjm_fasthtml_tailwind.core.base import combine_classes

from cjm_fasthtml_settings.components.forms import create_settings_form_container
from cjm_fasthtml_settings.core.utils import get_default_values_from_schema

from ..core.config import SingleFileWorkflowConfig
from ..core.html_ids import SingleFileHtmlIds
from ..core.protocols import PluginInfo, PluginRegistryProtocol

# %% ../../nbs/components/steps.ipynb 5
def _get_file_attr(
    file_path: str, # Path to the file to look up
    media_files: list, # List of MediaFile objects to search
    attr: str, # Attribute name to retrieve from the file
) -> str: # Attribute value or empty string if not found
    """Get an attribute from a file by path."""
    if not file_path:
        return ""
    file = next((f for f in media_files if f.path == file_path), None)
    return getattr(file, attr, "") if file else ""

# %% ../../nbs/components/steps.ipynb 7
def _render_plugin_details_content(
    plugin_id: str, # ID of the plugin to display details for
    plugins: List[PluginInfo], # List of available plugins
    plugin_registry: PluginRegistryProtocol, # Plugin registry adapter for getting plugin config
) -> Optional[FT]: # Plugin info card or None if plugin not found
    """Render details for selected plugin (info card only, no config collapse)."""
    plugin = next((p for p in plugins if p.id == plugin_id), None)
    if not plugin:
        return None

    config = plugin_registry.get_plugin_config(plugin_id)

    return Div(
        H3(plugin.title, cls=combine_classes(font_weight.semibold, m.b(2))),
        Div(
            Span(
                "Streaming" if plugin.supports_streaming else "Standard",
                cls=combine_classes(
                    badge,
                    badge_colors.info if plugin.supports_streaming else badge_styles.ghost,
                    badge_sizes.sm
                )
            ),
            cls=str(m.b(2))
        ),
        P(
            f"Configured: {'Yes' if plugin.is_configured else 'No'}",
            cls=combine_classes(font_size.sm, text_dui.base_content.opacity(70))
        ),
        cls=combine_classes(card, bg_dui.base_200, p(4))
    )

# %% ../../nbs/components/steps.ipynb 9
def _render_plugin_details_with_config(
    plugin_id: str, # ID of the plugin to display details for
    plugins: List[PluginInfo], # List of available plugins
    plugin_registry: PluginRegistryProtocol, # Plugin registry adapter for getting plugin config
    raw_plugin_registry, # UnifiedPluginRegistry for config_schema access
    save_url: str, # URL for saving plugin configuration
    reset_url: str, # URL for resetting plugin configuration
) -> Optional[FT]: # Plugin details with config collapse, or None if not found
    """Render plugin details with configuration collapse for initial render."""
    plugin = next((p for p in plugins if p.id == plugin_id), None)
    if not plugin:
        return None

    # If we don't have the raw registry or URLs, fall back to basic content
    if not raw_plugin_registry or not save_url or not reset_url:
        return _render_plugin_details_content(plugin_id, plugins, plugin_registry)

    config = plugin_registry.get_plugin_config(plugin_id)

    return Div(
        # Plugin info card
        Div(
            H3(plugin.title, cls=combine_classes(font_weight.semibold, m.b(2))),
            Div(
                Span(
                    "Streaming" if plugin.supports_streaming else "Standard",
                    cls=combine_classes(
                        badge,
                        badge_colors.info if plugin.supports_streaming else badge_styles.ghost,
                        badge_sizes.sm
                    )
                ),
                cls=str(m.b(2))
            ),
            P(
                f"Configured: {'Yes' if plugin.is_configured else 'No (using defaults)'}",
                cls=combine_classes(font_size.sm, text_dui.base_content.opacity(70))
            ),
            cls=combine_classes(card, bg_dui.base_200, p(4))
        ),

        # Plugin configuration collapse
        _render_plugin_config_collapse(
            plugin_id=plugin_id,
            plugin_registry=raw_plugin_registry,
            save_url=save_url,
            reset_url=reset_url,
        )
    )

# %% ../../nbs/components/steps.ipynb 11
def render_plugin_config_form(
    plugin_id: str, # ID of the plugin to render config for
    plugin_registry, # UnifiedPluginRegistry with config_schema access
    save_url: str, # URL for saving the configuration
    reset_url: str, # URL for resetting to defaults
    alert_message: Optional[Any] = None, # Optional alert to display above the form
) -> FT: # Div containing the settings form with alert container
    """Render the plugin configuration form for the collapse content."""
    # Get plugin metadata to access schema
    plugin_meta = plugin_registry.get_plugin(plugin_id)
    if not plugin_meta or not plugin_meta.config_schema:
        return Div(
            P("No configuration schema available for this plugin.",
              cls=combine_classes(text_dui.base_content.opacity(60), font_size.sm)),
            id=SingleFileHtmlIds.PLUGIN_CONFIG_CONTAINER
        )

    schema = plugin_meta.config_schema

    # Load saved config or use defaults
    saved_config = plugin_registry.load_plugin_config(plugin_id)
    default_config = get_default_values_from_schema(schema)
    current_values = {**default_config, **saved_config}

    # Create settings form container
    settings_content = create_settings_form_container(
        schema=schema,
        values=current_values,
        post_url=f"{save_url}?plugin_id={plugin_id}",
        reset_url=f"{reset_url}?plugin_id={plugin_id}",
        alert_message=alert_message,
        use_alert_container=not alert_message,
        target_id=SingleFileHtmlIds.PLUGIN_CONFIG_CONTAINER
    )

    # Give the container an ID so we can target it for swaps
    settings_content.attrs['id'] = SingleFileHtmlIds.PLUGIN_CONFIG_CONTAINER

    # Override HTMX attributes on the form to target the container
    if hasattr(settings_content, 'children') and len(settings_content.children) > 0:
        form = settings_content.children[-1]
        if hasattr(form, 'attrs'):
            form.attrs['hx-target'] = SingleFileHtmlIds.as_selector(
                SingleFileHtmlIds.PLUGIN_CONFIG_CONTAINER)
            form.attrs['hx-swap'] = 'outerHTML'

            # Update Reset button similarly
            if hasattr(form, 'children') and len(form.children) > 1:
                action_buttons = form.children[1]
                if hasattr(action_buttons, 'children') and len(action_buttons.children) > 1:
                    reset_button = action_buttons.children[1]
                    if hasattr(reset_button, 'attrs'):
                        reset_button.attrs['hx-target'] = SingleFileHtmlIds.as_selector(
                            SingleFileHtmlIds.PLUGIN_CONFIG_CONTAINER)
                        reset_button.attrs['hx-swap'] = 'outerHTML'

    return settings_content

# %% ../../nbs/components/steps.ipynb 13
def _render_plugin_config_collapse(
    plugin_id: str, # ID of the plugin to render config for
    plugin_registry, # UnifiedPluginRegistry with config_schema access
    save_url: str, # URL for saving the configuration
    reset_url: str, # URL for resetting to defaults
) -> FT: # Collapse component with plugin configuration form
    """Render a collapse component containing the plugin configuration form."""
    # Get plugin metadata to check if schema exists
    plugin_meta = plugin_registry.get_plugin(plugin_id)
    if not plugin_meta or not plugin_meta.config_schema:
        return Div()  # No config schema, no collapse needed

    return Div(
        Input(type="checkbox", id=SingleFileHtmlIds.PLUGIN_CONFIG_COLLAPSE),
        Div(
            "Plugin Configuration",
            cls=combine_classes(collapse_title, font_weight.medium, font_size.base)
        ),
        Div(
            render_plugin_config_form(
                plugin_id=plugin_id,
                plugin_registry=plugin_registry,
                save_url=save_url,
                reset_url=reset_url,
            ),
            cls=str(collapse_content)
        ),
        cls=combine_classes(
            collapse,
            collapse_modifiers.arrow,
            bg_dui.base_100,
            border_dui.base_300,
            border(),
            m.t(4)
        )
    )

# %% ../../nbs/components/steps.ipynb 15
def render_plugin_details_route(
    plugin_id: str, # ID of the plugin to display details for
    plugin_registry: PluginRegistryProtocol, # Plugin registry adapter for getting plugins and config
    raw_plugin_registry, # UnifiedPluginRegistry for config_schema access
    save_url: str, # URL for saving plugin configuration
    reset_url: str, # URL for resetting plugin configuration to defaults
) -> FT: # Plugin details with info card and config collapse
    """Render plugin details for HTMX route when plugin dropdown changes."""
    plugins = plugin_registry.get_all_plugins()
    plugin = next((p for p in plugins if p.id == plugin_id), None)
    if not plugin:
        return Div()

    config = plugin_registry.get_plugin_config(plugin_id)

    return Div(
        # Plugin info card
        Div(
            H3(plugin.title, cls=combine_classes(font_weight.semibold, m.b(2))),
            Div(
                Span(
                    "Streaming" if plugin.supports_streaming else "Standard",
                    cls=combine_classes(
                        badge,
                        badge_colors.info if plugin.supports_streaming else badge_styles.ghost,
                        badge_sizes.sm
                    )
                ),
                cls=str(m.b(2))
            ),
            P(
                f"Configured: {'Yes' if plugin.is_configured else 'No (using defaults)'}",
                cls=combine_classes(font_size.sm, text_dui.base_content.opacity(70))
            ),
            cls=combine_classes(card, bg_dui.base_200, p(4))
        ),

        # Plugin configuration collapse
        _render_plugin_config_collapse(
            plugin_id=plugin_id,
            plugin_registry=raw_plugin_registry,
            save_url=save_url,
            reset_url=reset_url,
        )
    )

# %% ../../nbs/components/steps.ipynb 18
def render_plugin_selection(
    ctx: InteractionContext, # Interaction context with state and data
    config: SingleFileWorkflowConfig, # Workflow configuration
    plugin_registry: PluginRegistryProtocol, # Plugin registry adapter for getting plugin config
    settings_modal_url: str, # URL for the settings modal route
    plugin_details_url: str, # URL for the plugin details route
    raw_plugin_registry=None, # UnifiedPluginRegistry for config_schema access (optional)
    save_plugin_config_url: str = "", # URL for saving plugin configuration
    reset_plugin_config_url: str = "", # URL for resetting plugin configuration
) -> FT: # Plugin selection step UI component
    """Render plugin selection step showing all discovered plugins."""
    plugins: List[PluginInfo] = ctx.get_data("plugins", [])
    selected_plugin_id = ctx.get("plugin_id")
    plugin_count = len(plugins)
    configured_count = sum(1 for p in plugins if p.is_configured)

    if not plugins:
        # No plugins discovered - show message with optional redirect
        content = [
            P(
                "No transcription plugins are available. Please install a transcription plugin package.",
                cls=combine_classes(text_dui.base_content.opacity(60), m.b(4))
            )
        ]
        if config.no_plugins_redirect:
            content.append(
                A(
                    "Go to Settings",
                    href=config.no_plugins_redirect,
                    cls=combine_classes(btn, btn_colors.primary)
                )
            )
        return Div(*content)

    return Div(
        # Plugin statistics
        Div(
            Div(
                Div("Available Plugins", cls=str(stat_title)),
                Div(
                    str(plugin_count),
                    cls=combine_classes(stat_value, text_dui.base_content)
                ),
                Div(
                    f"{configured_count} with custom config" if configured_count > 0 else "Using default configs",
                    cls=str(stat_desc)
                ),
                cls=str(stat)
            ),
            cls=combine_classes(stats, m.b(4))
        ),

        # Header with title and settings button
        Div(
            H2("Select Plugin", cls=combine_classes(font_size._2xl, font_weight.bold)),
            Button(
                # Gear icon SVG
                Svg(
                    SvgPath(d="M14 17H5"),
                    SvgPath(d="M19 7h-9"),
                    Circle(cx="17", cy="17", r="3"),
                    Circle(cx="7", cy="7", r="3"),
                    xmlns="http://www.w3.org/2000/svg",
                    width="24",
                    height="24",
                    viewBox="0 0 24 24",
                    fill="none",
                    stroke="currentColor",
                    stroke_width="2",
                    stroke_linecap="round",
                    stroke_linejoin="round",
                    cls=combine_classes(stroke_dui.base_content)
                    ),
                type="button",
                hx_get=settings_modal_url,
                hx_target=SingleFileHtmlIds.as_selector(SingleFileHtmlIds.SETTINGS_CONTAINER),
                hx_swap="innerHTML",
                cls=combine_classes(btn, btn_styles.ghost, btn_sizes.sm),
                title="Workflow Settings"
            ),
            cls=combine_classes(flex_display, justify.between, items.center, m.b(4))
        ),

        # Plugin selector dropdown
        Div(
            Label("Transcription Plugin:", cls=combine_classes(font_weight.semibold, m.b(2))),
            Select(
                Option("Select a plugin...", value="", disabled=True, selected=(not selected_plugin_id)),
                *[
                    Option(
                        plugin.title,
                        value=plugin.id,
                        selected=(plugin.id == selected_plugin_id)
                    )
                    for plugin in plugins
                ],
                name="plugin_id",
                cls=combine_classes(select, w.full),
                required=True,
                # HTMX attributes to auto-update plugin details
                hx_get=plugin_details_url,
                hx_target=SingleFileHtmlIds.as_selector(SingleFileHtmlIds.PLUGIN_DETAILS),
                hx_swap="innerHTML",
                hx_trigger="change",
                hx_include="this"
            ),
            cls=str(m.b(4))
        ),

        # Plugin details container
        Div(
            _render_plugin_details_with_config(
                selected_plugin_id,
                plugins,
                plugin_registry,
                raw_plugin_registry,
                save_plugin_config_url,
                reset_plugin_config_url
            ) if selected_plugin_id else None,
            id=SingleFileHtmlIds.PLUGIN_DETAILS,
            cls=str(m.t(4))
        ),

        # Settings modal container (empty, filled via HTMX)
        Div(id=SingleFileHtmlIds.SETTINGS_CONTAINER)
    )

# %% ../../nbs/components/steps.ipynb 20
def render_file_selection(
    ctx: InteractionContext, # Interaction context with state and data
    config: SingleFileWorkflowConfig, # Workflow configuration
    file_selection_router: APIRouter, # Router for file selection pagination (or None)
) -> FT: # File selection step UI component with paginated table
    """Render file selection step with paginated table view and preview capability."""
    # media_files are objects with path, name, media_type, size_str, modified_str attributes
    media_files = ctx.get_data("media_files", [])
    selected_file = ctx.get("file_path")

    if not media_files:
        # No files available - show message with optional redirect
        content = [
            P(
                "No audio or video files available for transcription.",
                cls=combine_classes(text_dui.base_content.opacity(60), text_align.center, p(8))
            )
        ]
        if config.no_files_redirect:
            content.append(
                Div(
                    A(
                        "Configure Media Directories",
                        href=config.no_files_redirect,
                        cls=combine_classes(btn, btn_colors.primary)
                    ),
                    cls=str(text_align.center)
                )
            )
        return Div(*content)

    # Use pagination - content loads via hx_trigger="load"
    # IMPORTANT: Must explicitly set hx_target="this" to prevent inheriting
    # hx_target from parent StepFlow form (which targets the workflow container)
    # Pass selected file as query param so pagination can mark it as checked

    table_container = Div(
        # Placeholder that will be replaced by pagination content
        hx_get=file_selection_router.content.to(page=1, selected=selected_file),
        hx_trigger="load",
        hx_target="this",
        hx_swap="outerHTML",
        id=SingleFileHtmlIds.FILE_SELECTION_TABLE,
        cls=combine_classes(
            overflow.x.auto,
            bg_dui.base_100,
            border_radius.box,
            m.b(4),
            p(8)
        )
    )

    return Div(
        H2("Select File", cls=combine_classes(font_size._2xl, font_weight.bold, m.b(4))),

        # Paginated file selection table (loads async via pagination router)
        table_container,

        # Hidden inputs to store file metadata
        Input(type="hidden", name="file_name", id="file_name",
              value=_get_file_attr(selected_file, media_files, "name")),
        Input(type="hidden", name="file_type", id="file_type",
              value=_get_file_attr(selected_file, media_files, "media_type")),
        Input(type="hidden", name="file_size", id="file_size",
              value=_get_file_attr(selected_file, media_files, "size_str")),

        # Modal wrapper placeholder - will be replaced via HTMX when preview is clicked
        # This ensures the modal is removed when navigating away from this step
        Div(id=SingleFileHtmlIds.MEDIA_PREVIEW_WRAPPER)
    )

# %% ../../nbs/components/steps.ipynb 22
def render_confirmation(
    ctx: InteractionContext, # Interaction context with state and data
    plugin_registry: PluginRegistryProtocol, # Plugin registry adapter for getting plugin info
) -> FT: # Confirmation step UI component showing selected plugin and file
    """Render confirmation step showing selected plugin and file."""
    # Get state from workflow session
    plugin_id = ctx.get("plugin_id")
    file_path = ctx.get("file_path")
    file_name = ctx.get("file_name", "Unknown")
    file_type = ctx.get("file_type", "Unknown")
    file_size = ctx.get("file_size", "Unknown")

    # Get plugin info
    plugin_info = plugin_registry.get_plugin(plugin_id)
    plugin_title = plugin_info.title if plugin_info else plugin_id
    supports_streaming = plugin_info.supports_streaming if plugin_info else False

    return Div(
        H2("Ready to Transcribe", cls=str(card_title)),

        Div(
            # File info
            Div(
                H3("Selected File", cls=combine_classes(font_weight.semibold, m.b(2))),
                Div(
                    P(f"Name: {file_name}", cls=str(font_size.sm)),
                    P(f"Type: {file_type.title()}", cls=str(font_size.sm)),
                    P(f"Size: {file_size}", cls=str(font_size.sm)),
                    cls=combine_classes(text_dui.base_content.opacity(80))
                ),
                cls=str(m.b(4))
            ),

            # Plugin info
            Div(
                H3("Using Plugin", cls=combine_classes(font_weight.semibold, m.b(2))),
                Div(
                    P(plugin_title, cls=str(font_size.sm)),
                    Span(
                        "Streaming" if supports_streaming else "Standard",
                        cls=combine_classes(
                            badge,
                            badge_colors.info if supports_streaming else badge_styles.ghost,
                            badge_sizes.sm,
                            m.t(1)
                        )
                    ),
                    cls=combine_classes(text_dui.base_content.opacity(80))
                ),
                cls=str(m.b(4))
            ),

            P(
                "Click 'Start Transcription' to begin processing.",
                cls=combine_classes(text_dui.base_content.opacity(60), font_size.sm, text_align.center, m.t(4))
            ),

            cls=combine_classes(card_body)
        ),
        cls=combine_classes(card, bg_dui.base_200)
    )
