"""
Reusable routing helper for the "Get Supporting Docs" flow.

This module centralizes the logic to branch by application id and invoke the
appropriate supporting documents flow. Callers provide context-specific
handlers via callables to avoid circular imports and preserve nuanced fallback
behavior in different parts of the app.
"""

from typing import Callable, Optional
import logging
import time


def route_supporting_docs(
    app,
    *,
    sage_handler: Optional[Callable[[], None]] = None,
    fallback_generic: Optional[Callable[[], None]] = None,
    sleep_before: float = 0.0,
    allow_xero_fallback: bool = True,
) -> None:
    """Route supporting docs logic by application id.

    Parameters
    - app: The UI app instance containing application id and UI helpers.
    - sage_handler: Optional callable to run for Sage (app_id==12). If not
      provided, defaults to calling the Sage supporting docs module's flow.
    - fallback_generic: Optional callable invoked for generic/other apps, or
      as a fallback when app-specific flows fail where allowed by the caller.
    - sleep_before: Optional seconds to sleep before running the flow to allow
      the UI to settle (used by playback's dedicated action).
    - allow_xero_fallback: Whether to invoke fallback on Xero failures. In the
      dedicated playback action we do not fallback; in analyzer context we do.
    """

    # Optional pre-delay to let the UI settle before proceeding
    try:
        if sleep_before and sleep_before > 0:
            time.sleep(float(sleep_before))
    except Exception:
        pass

    # Determine application id for routing
    try:
        app_id = getattr(app, 'current_application_id', None) or getattr(app, 'application_id', None)
        app_id = int(app_id) if app_id is not None else None
    except Exception:
        app_id = None

    # Xero: use the Attach files/Files subplaylist flow
    if app_id == 6:
        try:
            from .xero_supporting_docs import play_supporting_docs_attach_files as _xero_play
            _xero_play(app)
            return
        except Exception:
            logging.exception('[SupportDocsRouter] Xero supporting docs flow failed')
            if allow_xero_fallback and callable(fallback_generic):
                try:
                    fallback_generic()
                except Exception:
                    logging.exception('[SupportDocsRouter] Xero fallback handler failed')
            return

    # Sage: use caller-provided handler when present (e.g., attachments finder in analyzer)
    if app_id == 12:
        if callable(sage_handler):
            try:
                sage_handler()
                return
            except Exception:
                logging.exception('[SupportDocsRouter] Sage custom handler failed')
                # Analyzer often prefers no generic fallback here to avoid loops
                if callable(fallback_generic):
                    try:
                        fallback_generic()
                    except Exception:
                        logging.exception('[SupportDocsRouter] Sage fallback handler failed')
                return
        else:
            try:
                from .sage_supporting_docs import play_supporting_docs as _sage_play
                _sage_play(app)
                return
            except Exception:
                logging.exception('[SupportDocsRouter] Sage supporting docs flow failed')
                # Allow fallback to generic when provided
                if callable(fallback_generic):
                    try:
                        fallback_generic()
                    except Exception:
                        logging.exception('[SupportDocsRouter] Sage fallback handler failed')
                return

    # QuickBooks: dedicated playback flow for app ids 9 or 10
    if app_id in (9, 10):
        try:
            from .QuickBooks_supporting_docs import play_supporting_docs as _qb_play
            _qb_play(app)
            return
        except Exception:
            logging.exception('[SupportDocsRouter] QuickBooks supporting docs flow failed')
            # Allow fallback to generic when provided
            if callable(fallback_generic):
                try:
                    fallback_generic()
                except Exception:
                    logging.exception('[SupportDocsRouter] QuickBooks fallback handler failed')
            return

    # MYOB: dedicated playback flow for app id 11
    if app_id == 11:
        try:
            from .myob_supporting_docs import play_supporting_docs as _myob_play
            _myob_play(app)
            return
        except Exception:
            logging.exception('[SupportDocsRouter] MYOB supporting docs flow failed')
            # Allow fallback to generic when provided
            if callable(fallback_generic):
                try:
                    fallback_generic()
                except Exception:
                    logging.exception('[SupportDocsRouter] MYOB fallback handler failed')
            return

    # Generic or unrecognized app: invoke provided fallback if any
    if callable(fallback_generic):
        try:
            fallback_generic()
        except Exception:
            logging.exception('[SupportDocsRouter] Generic fallback handler failed')
    # else: no-op when no fallback is provided


