from __future__ import annotations
from typing import Union, Optional, Dict, Any
from .io import load_model_json
from .web import open_webview, DEFAULT_URL
from .parser import build_from_json
import logging

log = logging.getLogger("opennetwork")

class ModelLoadError(Exception):
    pass

def init(verbose: bool = True) -> bool:
    if verbose:
        banner = (
            "OpenNetwork • Dev Suite\n"
            " - setmodel() launches the Playground\n"
            " - getmodel(path_or_dict) builds a Keras model if TensorFlow is installed\n"
        )
        print(banner)
    return True

def setmodel(url: Optional[str] = None, **window_kwargs) -> bool:
    """
    Open a local webview (if pywebview is installed) or the default browser to the Playground.
    """
    return open_webview(url or DEFAULT_URL, **window_kwargs)

def getmodel(src: Union[str, dict], *, strict: bool = False, auto_flatten: bool = True, return_extras: bool = False):
    """
    Load the JSON and build a Keras model (if TensorFlow is available).
    Returns the tf.keras.Model. If TensorFlow is missing, raises ModelLoadError unless return_extras=True,
    in which case returns (None, {'graph_layers': [...], 'inserted': [...]}) for dry-run validation.
    """
    data = load_model_json(src)
    result = build_from_json(data, strict=strict, auto_flatten=auto_flatten)

    if result.model is None:
        msg = (
            "TensorFlow is not installed. Install it with:\n"
            "  pip install 'opennetwork[keras]'\n"
            "or add tensorflow manually: pip install tensorflow\n"
            "You can still validate the graph via return_extras=True."
        )
        if return_extras:
            return None, {"graph_layers": result.graph_layers, "inserted": result.inserted}
        raise ModelLoadError(msg)

    return result.model
