"""Load a Textual App from a file path or module path."""

from __future__ import annotations

import importlib
import importlib.util
import inspect
import sys
from pathlib import Path

from textual.app import App


def load_app(app_path: str) -> App:
    """Load a Textual App from file path or module path.

    Formats:
        "my_app.py"              — load first App subclass from file
        "my_app.py:MyApp"        — load named class from file
        "mypackage.module:MyApp" — load named class from installed module

    Raises:
        FileNotFoundError: if a .py path does not exist
        ValueError: if no App subclass is found in the module
        AttributeError: if the named class does not exist in the module
    """
    class_name: str | None = None

    if ":" in app_path:
        app_path, class_name = app_path.rsplit(":", 1)

    if app_path.endswith(".py"):
        module = _load_from_file(app_path)
    else:
        module = importlib.import_module(app_path)

    if class_name:
        cls = getattr(module, class_name)  # raises AttributeError
    else:
        cls = _find_app_class(module)

    return cls()


def _load_from_file(file_path: str):
    """Import a .py file as a module."""
    path = Path(file_path).resolve()
    if not path.is_file():
        raise FileNotFoundError(f"App file not found: {file_path}")

    # Ensure the parent directory is on sys.path for relative imports
    parent = str(path.parent)
    if parent not in sys.path:
        sys.path.insert(0, parent)

    module_name = path.stem
    spec = importlib.util.spec_from_file_location(module_name, path)
    module = importlib.util.module_from_spec(spec)
    sys.modules[module_name] = module
    spec.loader.exec_module(module)
    return module


def _find_app_class(module) -> type[App]:
    """Find the first App subclass in a module."""
    for name, obj in inspect.getmembers(module, inspect.isclass):
        if issubclass(obj, App) and obj is not App:
            return obj
    raise ValueError(f"No App subclass found in {module.__name__}")
