"""Main workflow class orchestrating all subsystems for single-file transcription"""

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

# %% auto 0
__all__ = ['SingleFileTranscriptionWorkflow']

# %% ../../nbs/workflow/workflow.ipynb 3
from typing import Dict, Any, List, Optional
from fasthtml.common import *
from fasthtml.common import APIRouter
from fastcore.basics import patch

from cjm_fasthtml_interactions.patterns.step_flow import Step, StepFlow
from cjm_fasthtml_interactions.core.context import InteractionContext
from cjm_fasthtml_interactions.core.state_store import InMemoryWorkflowStateStore
from cjm_fasthtml_interactions.patterns.async_loading import AsyncLoadingContainer
from cjm_fasthtml_sse.core import SSEBroadcastManager

from cjm_plugin_system.core.manager import PluginManager
from cjm_plugin_system.core.metadata import PluginMeta

from cjm_fasthtml_file_browser.core.file_browser import FileBrowser
from cjm_fasthtml_file_browser.core.models import FileEntry
from cjm_fasthtml_file_browser.core.types import FileType

from ..core.config import SingleFileWorkflowConfig
from ..core.html_ids import SingleFileHtmlIds
from ..core.adapters import PluginRegistryAdapter
from ..core.job_tracker import TranscriptionJobTracker, TranscriptionJob
from ..storage.file_storage import ResultStorage
from cjm_fasthtml_workflow_transcription_single_file.components.steps import (
    render_plugin_selection,
    render_file_selection,
    render_confirmation,
)

# %% ../../nbs/workflow/workflow.ipynb 5
class SingleFileTranscriptionWorkflow:
    """Self-contained single-file transcription workflow.

    Receives a PluginManager from the host application and creates internal
    TranscriptionJobTracker, SSEBroadcastManager, FileBrowser, ResultStorage,
    StepFlow (plugin → file → confirm wizard), and APIRouter.
    """

    # Class-level metadata for future plugin system discovery
    workflow_name: str = "single_file_transcription"
    workflow_version: str = "1.0.0"
    workflow_category: str = "transcription"
    workflow_title: str = "Single File Transcription"
    workflow_description: str = "Transcribe individual audio/video files using configurable transcription plugins"

    def __init__(
        self,
        plugin_manager: PluginManager,  # PluginManager from host application
        config: Optional[SingleFileWorkflowConfig] = None,  # Explicit config (bypasses auto-loading)
        **config_overrides  # Override specific config values
    ):
        """Initialize the workflow with injected PluginManager."""
        # Build configuration: explicit config takes precedence, otherwise auto-load with overrides
        if config is not None:
            self.config = config
        else:
            self.config = SingleFileWorkflowConfig.from_saved_config(**config_overrides)
        
        self._app = None  # Set in setup()
        
        # Store the injected PluginManager
        self._plugin_manager = plugin_manager

        # Create internal SSE manager for this workflow
        self._sse_manager = SSEBroadcastManager()

        # Create internal job tracker with completion callback
        self._job_tracker = TranscriptionJobTracker(
            on_job_completed=self._on_job_completed
        )

        # Create internal FileBrowser for media file discovery
        self._file_browser = FileBrowser(self.config.media)

        # Create internal ResultStorage
        self._result_storage = ResultStorage(self.config.storage)

        # Create workflow's plugin registry adapter (adapts PluginManager to PluginRegistryProtocol)
        self._plugin_adapter = PluginRegistryAdapter(
            self._plugin_manager,
            self.config,
            category=self.config.plugin_category
        )

        # Create workflow state store (server-side storage for StepFlow wizard state)
        self._state_store = InMemoryWorkflowStateStore()

        # Create StepFlow
        self._step_flow = self._create_step_flow()

        # Create routers (main router first, then stepflow)
        self._router = self._create_router()
        self._stepflow_router = self._step_flow.create_router(
            prefix=self.config.get_full_stepflow_prefix()
        )

        # Create media pagination and router (for grid/list browser view)
        self._file_browser.create_pagination(
            pagination_id=f"{self.config.workflow_id}_media",
            content_id=SingleFileHtmlIds.MEDIA_BROWSER_CONTENT,
            preview_route_func=self._create_preview_route_func(),
            modal_id=SingleFileHtmlIds.MEDIA_PREVIEW_MODAL
        )
        self._media_router = self._file_browser.get_pagination_router(
            prefix=self.config.get_full_media_prefix()
        )

        # Create file selection pagination and router (for file selection step table)
        # Filter to only show audio/video files for transcription
        self._file_browser.create_file_selection_pagination(
            pagination_id=f"{self.config.workflow_id}_file_select",
            content_id=SingleFileHtmlIds.FILE_SELECTION_TABLE,
            preview_url_func=self._create_preview_url_func(),
            preview_target_id=SingleFileHtmlIds.MEDIA_PREVIEW_WRAPPER,
            file_type_filter=[FileType.AUDIO, FileType.VIDEO]
        )
        self._file_selection_router = self._file_browser.get_file_selection_router(
            prefix=f"{self.config.route_prefix}/file_select"
        )

    @classmethod
    def create_and_setup(
        cls,
        app,  # FastHTML application instance
        plugin_manager: PluginManager,  # PluginManager from host application
        config: Optional[SingleFileWorkflowConfig] = None,  # Explicit config (bypasses auto-loading)
        **config_overrides  # Override specific config values
    ) -> "SingleFileTranscriptionWorkflow":  # Configured and setup workflow instance
        """Create, configure, and setup a workflow in one call."""
        workflow = cls(plugin_manager=plugin_manager, config=config, **config_overrides)
        workflow.setup(app)
        return workflow

    @property
    def job_tracker(self) -> TranscriptionJobTracker:
        """Access to internal job tracker."""
        return self._job_tracker
    
    @property
    def plugin_manager(self) -> PluginManager:
        """Access to plugin manager."""
        return self._plugin_manager
    
    @property
    def plugin_registry(self) -> PluginRegistryAdapter:
        """Access to plugin registry adapter."""
        return self._plugin_adapter
    
    @property
    def file_browser(self) -> FileBrowser:
        """Access to internal file browser."""
        return self._file_browser
    
    @property
    def result_storage(self) -> ResultStorage:
        """Access to internal result storage."""
        return self._result_storage
    
    @property
    def router(self) -> APIRouter:
        """Main workflow router."""
        return self._router
    
    @property
    def stepflow_router(self) -> APIRouter:
        """StepFlow-generated router."""
        return self._stepflow_router

# %% ../../nbs/workflow/workflow.ipynb 7
@patch
def setup(
    self: SingleFileTranscriptionWorkflow,
    app,  # FastHTML application instance
) -> None:
    """Initialize workflow with FastHTML app. Must be called after app creation."""
    self._app = app
    self._file_browser.mount(app)

# %% ../../nbs/workflow/workflow.ipynb 9
@patch
def cleanup(
    self: SingleFileTranscriptionWorkflow,
) -> None:
    """Clean up workflow resources. Mirrors PluginInterface.cleanup() for future plugin system compatibility."""
    self._file_browser.clear_cache()
    self._app = None

# %% ../../nbs/workflow/workflow.ipynb 11
@patch
def get_routers(
    self: SingleFileTranscriptionWorkflow,
) -> List[APIRouter]:  # List containing main router, stepflow router, media router, and file selection router
    """Return all routers for registration with the app."""
    routers = [self._router, self._stepflow_router]
    if self._media_router:
        routers.append(self._media_router)
    if self._file_selection_router:
        routers.append(self._file_selection_router)
    return routers

# %% ../../nbs/workflow/workflow.ipynb 13
@patch
def render_entry_point(
    self: SingleFileTranscriptionWorkflow,
    request,  # FastHTML request object
    sess,  # FastHTML session object
) -> FT:  # AsyncLoadingContainer component
    """Render the workflow entry point for embedding in tabs, etc.

    Returns an AsyncLoadingContainer that loads the current_status endpoint,
    which determines what to show (running job, workflow in progress,
    completed job, or fresh start).
    """
    # Check if there are any discovered plugins in this category
    plugins = self._plugin_manager.get_discovered_by_category(self.config.plugin_category)

    if not plugins:
        # No plugins discovered at all - show message with optional redirect
        from cjm_fasthtml_daisyui.components.actions.button import btn, btn_colors
        from cjm_fasthtml_daisyui.utilities.semantic_colors import text_dui
        from cjm_fasthtml_tailwind.utilities.spacing import m
        from cjm_fasthtml_tailwind.core.base import combine_classes

        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 self.config.no_plugins_redirect:
            content.append(
                A(
                    "Go to Settings",
                    href=self.config.no_plugins_redirect,
                    cls=combine_classes(btn, btn_colors.primary)
                )
            )
        return Div(*content, id=self.config.container_id)

    # Plugins available - load current status asynchronously
    current_status_url = f"{self.config.route_prefix}/current_status"
    return AsyncLoadingContainer(
        container_id=self.config.container_id,
        load_url=current_status_url
    )

# %% ../../nbs/workflow/workflow.ipynb 14
@patch
def _on_job_completed(
    self: SingleFileTranscriptionWorkflow,
    job_id: str,  # The completed job's ID
    tracker: TranscriptionJobTracker,  # The job tracker instance
) -> None:
    """Workflow-specific completion handling. Auto-saves results if enabled."""
    if not self._result_storage.should_auto_save():
        return

    job = tracker.get_job(job_id)
    result = tracker.get_job_result(job_id)

    if not job or not result:
        return

    # Check if already saved (via job metadata)
    if job.metadata and job.metadata.get('saved_to_disk'):
        return

    try:
        data = result.get('data', {})
        plugin_meta = self._plugin_manager.get_plugin_meta(job.plugin_name)

        self._result_storage.save(
            job_id=job_id,
            file_path=job.file_path,
            file_name=job.file_name,
            plugin_id=job.plugin_name,
            plugin_name=plugin_meta.name if plugin_meta else job.plugin_name,
            text=data.get('text', ''),
            metadata=data.get('metadata', {})
        )

        # Mark as saved in job metadata
        if not job.metadata:
            job.metadata = {}
        job.metadata['saved_to_disk'] = True

        print(f"[Workflow] Auto-saved result for job {job_id}")

    except Exception as e:
        print(f"[Workflow] Error saving result for {job_id}: {e}")
        import traceback
        traceback.print_exc()

# %% ../../nbs/workflow/workflow.ipynb 15
@patch
def _create_preview_route_func(
    self: SingleFileTranscriptionWorkflow,
):  # Function that generates preview route URLs
    """Create a function that generates preview route URLs (with optional file_type)."""
    route_prefix = self.config.route_prefix

    def preview_route_func(idx: int, file_type: Optional[str] = None) -> str:
        url = f"{route_prefix}/media_preview?idx={idx}"
        if file_type:
            url += f"&file_type={file_type}"
        return url

    return preview_route_func

# %% ../../nbs/workflow/workflow.ipynb 16
@patch
def _create_preview_url_func(
    self: SingleFileTranscriptionWorkflow,
):  # Function that generates preview URLs for file selection
    """Create a function that generates preview URLs for file selection (index only)."""
    route_prefix = self.config.route_prefix

    def preview_url_func(idx: int) -> str:
        return f"{route_prefix}/media_preview?idx={idx}"

    return preview_url_func

# %% ../../nbs/workflow/workflow.ipynb 17
@patch
def _create_step_flow(
    self: SingleFileTranscriptionWorkflow,
) -> StepFlow:  # Configured StepFlow instance
    """Create and configure the StepFlow instance."""
    # Create wrapper functions that capture self
    workflow = self

    def load_plugins(request) -> Dict[str, Any]:
        """Load available transcription plugins."""
        plugins = workflow._plugin_adapter.get_all_plugins()
        return {"plugins": plugins}

    def load_media_files(request) -> Dict[str, Any]:
        """Load available media files from internal FileBrowser."""
        # Get only audio/video files for transcription
        files = workflow._file_browser.get_files_by_type([FileType.AUDIO, FileType.VIDEO])
        # Convert FileEntry to the format expected by the step
        file_infos = []
        for f in files:
            # Create a simple object with the expected attributes
            class FileInfo:
                def __init__(self, file_entry: FileEntry):
                    self.path = file_entry.path
                    self.name = file_entry.name
                    self.file_type = file_entry.file_type.value  # Convert enum to string
                    self.size_str = file_entry.size_str
                    self.modified_str = file_entry.modified_str
            file_infos.append(FileInfo(f))
        return {"media_files": file_infos}

    def load_confirmation_data(request) -> Dict[str, Any]:
        """Load data for confirmation step."""
        return {}

    def render_plugin_step(ctx: InteractionContext):
        """Render plugin selection step."""
        return render_plugin_selection(
            ctx,
            config=workflow.config,
            plugin_registry=workflow._plugin_adapter,
            settings_modal_url=workflow._router.settings_modal.to(),
            plugin_details_url=workflow._router.plugin_details.to(),
            plugin_manager=workflow._plugin_manager,
            save_plugin_config_url=workflow._router.save_plugin_config.to(),
            reset_plugin_config_url=workflow._router.reset_plugin_config.to(),
        )

    def render_file_step(ctx: InteractionContext):
        """Render file selection step."""
        return render_file_selection(
            ctx,
            config=workflow.config,
            file_selection_router=workflow._file_browser.file_selection_router,
        )

    def render_confirm_step(ctx: InteractionContext):
        """Render confirmation step."""
        return render_confirmation(ctx, plugin_registry=workflow._plugin_adapter)

    def validate_plugin_selection(state: Dict[str, Any]) -> bool:
        """Validate that a plugin has been selected."""
        plugin_id = state.get("plugin_id", "")
        return bool(plugin_id and plugin_id.strip())

    def validate_file_selection(state: Dict[str, Any]) -> bool:
        """Validate that a file has been selected."""
        return bool(state.get("file_path")) and bool(state.get("file_name"))

    def validate_confirm(state: Dict[str, Any]) -> bool:
        """Validate confirmation."""
        return True

    async def on_complete(state: Dict[str, Any], request):
        """Handle workflow completion."""
        from cjm_fasthtml_workflow_transcription_single_file.workflow.job_handler import start_transcription_job
        # Save configuration via the plugin manager
        workflow._plugin_manager.update_plugin_config(state["plugin_id"], 
                                                      self._plugin_adapter.get_plugin_config(state["plugin_id"]))
        result = await start_transcription_job(state, request, workflow)
        # Clear workflow state since we've successfully started the transcription
        # This ensures "New Transcription" button starts fresh instead of resuming
        workflow._state_store.clear_state(workflow.config.workflow_id, request.session)
        return result

    return StepFlow(
        flow_id=self.config.workflow_id,
        state_store=self._state_store,
        container_id=self.config.container_id,
        steps=[
            Step(
                id="plugin",
                title="Select Plugin",
                render=render_plugin_step,
                validate=validate_plugin_selection,
                data_loader=load_plugins,
                data_keys=["plugin_id"],
                show_back=False,
                show_cancel=True,
                next_button_text="Continue"
            ),
            Step(
                id="file",
                title="Select File",
                render=render_file_step,
                validate=validate_file_selection,
                data_loader=load_media_files,
                data_keys=["file_path", "file_name", "file_type", "file_size"],
                show_back=True,
                show_cancel=True,
                next_button_text="Continue"
            ),
            Step(
                id="confirm",
                title="Confirm",
                render=render_confirm_step,
                validate=validate_confirm,
                data_loader=load_confirmation_data,
                data_keys=[],
                show_back=True,
                show_cancel=True,
                next_button_text="Start Transcription"
            )
        ],
        on_complete=on_complete,
        show_progress=self.config.show_progress,
        wrap_in_form=True
    )

# %% ../../nbs/workflow/workflow.ipynb 18
@patch
def _create_router(
    self: SingleFileTranscriptionWorkflow,
) -> APIRouter:  # Configured APIRouter with all workflow routes
    """Create the workflow's API router with all routes."""
    from cjm_fasthtml_workflow_transcription_single_file.workflow.routes import init_router
    return init_router(self)
