"""
EmbeddingBuddy application factory and server functions.

This module contains the main application creation logic with imports
moved inside functions to avoid loading heavy dependencies at module level.
"""


def create_app():
    """Create and configure the Dash application instance."""
    import os
    import dash
    import dash_bootstrap_components as dbc
    from .ui.layout import AppLayout
    from .ui.callbacks.data_processing import DataProcessingCallbacks
    from .ui.callbacks.visualization import VisualizationCallbacks
    from .ui.callbacks.interactions import InteractionCallbacks

    # Get the assets directory relative to this module
    module_dir = os.path.dirname(__file__)
    assets_path = os.path.join(module_dir, "assets")

    app = dash.Dash(
        __name__,
        title="EmbeddingBuddy",
        external_stylesheets=[
            dbc.themes.BOOTSTRAP,
        ],
        assets_folder=assets_path,
        meta_tags=[
            {
                "name": "description",
                "content": "Interactive embedding visualization tool for exploring high-dimensional vectors through dimensionality reduction techniques like PCA, t-SNE, and UMAP.",
            },
            {"name": "author", "content": "EmbeddingBuddy"},
            {
                "name": "keywords",
                "content": "embeddings, visualization, dimensionality reduction, PCA, t-SNE, UMAP, machine learning, data science",
            },
            {"name": "viewport", "content": "width=device-width, initial-scale=1.0"},
            {
                "property": "og:title",
                "content": "EmbeddingBuddy - Interactive Embedding Visualization",
            },
            {
                "property": "og:description",
                "content": "Explore and visualize embedding vectors through interactive 2D/3D plots with multiple dimensionality reduction techniques.",
            },
            {"property": "og:type", "content": "website"},
        ],
    )

    # Allow callbacks to components that are dynamically created in tabs
    app.config.suppress_callback_exceptions = True

    layout_manager = AppLayout()
    app.layout = layout_manager.create_layout()

    DataProcessingCallbacks()
    VisualizationCallbacks()
    InteractionCallbacks()

    # Register client-side callback for embedding generation
    _register_client_side_callbacks(app)

    return app


def _register_client_side_callbacks(app):
    """Register client-side callbacks for browser-based processing."""
    from dash import Input, Output, State

    # Client-side callback for embedding generation
    app.clientside_callback(
        """
        function(nClicks, textContent, modelName, tokenizationMethod, batchSize, category, subcategory) {
            if (!nClicks || !textContent || !textContent.trim()) {
                return window.dash_clientside.no_update;
            }

            console.log('🔍 Checking for Transformers.js...');
            console.log('window.dash_clientside:', typeof window.dash_clientside);
            console.log('window.dash_clientside.transformers:', typeof window.dash_clientside?.transformers);
            console.log('generateEmbeddings function:', typeof window.dash_clientside?.transformers?.generateEmbeddings);

            if (typeof window.dash_clientside !== 'undefined' &&
                typeof window.dash_clientside.transformers !== 'undefined' &&
                typeof window.dash_clientside.transformers.generateEmbeddings === 'function') {

                console.log('✅ Calling Transformers.js generateEmbeddings...');
                return window.dash_clientside.transformers.generateEmbeddings(
                    nClicks, textContent, modelName, tokenizationMethod, category, subcategory
                );
            }

            // More detailed error information
            let errorMsg = '❌ Transformers.js not available. ';
            if (typeof window.dash_clientside === 'undefined') {
                errorMsg += 'dash_clientside not found.';
            } else if (typeof window.dash_clientside.transformers === 'undefined') {
                errorMsg += 'transformers module not found.';
            } else if (typeof window.dash_clientside.transformers.generateEmbeddings !== 'function') {
                errorMsg += 'generateEmbeddings function not found.';
            }

            console.error(errorMsg);

            return [
                { error: 'Transformers.js not loaded. Please refresh the page and try again.' },
                false
            ];
        }
        """,
        [
            Output("embeddings-generated-trigger", "data"),
            Output("generate-embeddings-btn", "disabled", allow_duplicate=True),
        ],
        [Input("generate-embeddings-btn", "n_clicks")],
        [
            State("text-input-area", "value"),
            State("model-selection", "value"),
            State("tokenization-method", "value"),
            State("batch-size", "value"),
            State("text-category", "value"),
            State("text-subcategory", "value"),
        ],
        prevent_initial_call=True,
    )


def run_app(app=None, debug=None, host=None, port=None):
    """Run the Dash application with specified settings."""
    from .config.settings import AppSettings

    if app is None:
        app = create_app()

    app.run(
        debug=debug if debug is not None else AppSettings.DEBUG,
        host=host if host is not None else AppSettings.HOST,
        port=port if port is not None else AppSettings.PORT,
    )


def serve(host=None, port=None, dev=False, debug=False):
    """Start the EmbeddingBuddy web server.

    Args:
        host: Host to bind to (default: 127.0.0.1)
        port: Port to bind to (default: 8050)
        dev: Development mode - enable debug logging and auto-reload (default: False)
        debug: Enable debug logging only, no auto-reload (default: False)
    """
    import os
    from .config.settings import AppSettings

    # Determine actual values to use
    actual_host = host if host is not None else AppSettings.HOST
    actual_port = port if port is not None else AppSettings.PORT

    # Determine mode
    # --dev takes precedence and enables both debug and auto-reload
    # --debug enables only debug logging
    # No flags = production mode (no debug, no auto-reload)
    use_reloader = dev
    use_debug = dev or debug

    # Only print startup messages in main process (not in Flask reloader)
    if not os.environ.get("WERKZEUG_RUN_MAIN"):
        from importlib.metadata import version

        try:
            pkg_version = version("embeddingbuddy")
        except Exception:
            pkg_version = "unknown"

        mode = "development" if dev else ("debug" if debug else "production")
        print(f"Starting EmbeddingBuddy v{pkg_version} in {mode} mode...")
        print("Loading dependencies (this may take a few seconds)...")
        print(f"Server will start at http://{actual_host}:{actual_port}")
        if use_reloader:
            print("Auto-reload enabled - server will restart on code changes")

    app = create_app()

    # Suppress Flask development server warning in production mode
    if not use_debug and not use_reloader:
        import warnings
        import logging

        # Suppress the werkzeug warning
        warnings.filterwarnings("ignore", message=".*development server.*")

        # Set werkzeug logger to ERROR level to suppress the warning
        werkzeug_logger = logging.getLogger("werkzeug")
        werkzeug_logger.setLevel(logging.ERROR)

    # Use Flask's built-in server with appropriate settings
    app.run(
        debug=use_debug, host=actual_host, port=actual_port, use_reloader=use_reloader
    )


def main():
    """Legacy entry point - redirects to cli module.

    This is kept for backward compatibility but the main CLI
    is now in embeddingbuddy.cli for faster startup.
    """
    from .cli import main as cli_main

    cli_main()


if __name__ == "__main__":
    main()
