import logging
from importlib.resources import files
from pathlib import Path
from typing import Optional, Any

import fasthtml.fastapp
from fasthtml.components import Link, Script
from starlette.responses import Response

from myfasthtml.auth.routes import setup_auth_routes
from myfasthtml.auth.utils import create_auth_beforeware
from myfasthtml.core.AuthProxy import AuthProxy
from myfasthtml.core.instances import RootInstance
from myfasthtml.core.utils import utils_app

logger = logging.getLogger("MyFastHtml")


def get_asset_path(filename):
  """Get asset file path"""
  return files("myfasthtml") / "assets" / filename


# Get assets directory path
assets_path = files("myfasthtml") / "assets"
assets_dir = Path(str(assets_path))


def get_asset_content(filename):
  """Get asset file content"""
  return get_asset_path(filename).read_text()


def create_app(daisyui: Optional[bool] = True,
               vis: Optional[bool] = True,
               protect_routes: Optional[bool] = True,
               mount_auth_app: Optional[bool] = False,
               base_url: Optional[str] = None,
               **kwargs) -> Any:
  """
  Creates and configures a FastHtml application with optional support for daisyUI themes and
  authentication routes.
  
  :param daisyui: Flag to enable or disable inclusion of daisyUI-related assets for styling.
                  Defaults to False.
  :param protect_routes: Flag to enable or disable routes protection based on authentication.
                  Defaults to True.
  :param mount_auth_app: Flag to enable or disable mounting of authentication routes.
                         Defaults to False.
  :param base_url: Url to use for the application (used by the auth APIs)
  :param kwargs: Arbitrary keyword arguments forwarded to the application initialization logic.

  :return: A tuple containing the FastHtml application instance and the associated router.
  :rtype: Any
  """
  hdrs = [
      Link(href="/myfasthtml/myfasthtml.css", rel="stylesheet", type="text/css"),
      Script(src="/myfasthtml/myfasthtml.js"),
  ]
  
  if daisyui:
    hdrs += [
        Link(href="/myfasthtml/daisyui-5.css", rel="stylesheet", type="text/css"),
        Link(href="/myfasthtml/daisyui-5-themes.css", rel="stylesheet", type="text/css"),
        Script(src="/myfasthtml/tailwindcss-browser@4.js"),
    ]
  
  if vis:
    hdrs += [
        Script(src="/myfasthtml/vis-network.min.js"),
    ]
  
  beforeware = create_auth_beforeware() if protect_routes else None
  app, rt = fasthtml.fastapp.fast_app(before=beforeware, hdrs=tuple(hdrs), **kwargs)
  
  # remove the global static files routes
  original_routes = app.routes[:]
  app.routes.clear()
  
  # Serve assets
  @app.get("/myfasthtml/{filename:path}.{ext:static}")
  def serve_assets(filename: str, ext: str):
    path = filename + "." + ext
    try:
      content = get_asset_content(path)
      
      if filename.endswith('.css'):
        return Response(content, media_type="text/css")
      elif filename.endswith('.js'):
        return Response(content, media_type="application/javascript")
      else:
        return Response(content)
    except Exception as e:
      return Response(f"Asset not found: {path}", status_code=404)
  
  # and put it back after the myfasthtml static files routes
  for r in original_routes:
    app.routes.append(r)
  
  # route the commands and the bindings
  app.mount("/myfasthtml", utils_app)
  
  if mount_auth_app:
    # Setup authentication routes
    setup_auth_routes(app, rt, base_url=base_url)
    
    # create the AuthProxy instance
    AuthProxy(RootInstance, base_url)  # using the auto register mechanism to expose it
  
  return app, rt
