import os
from fastapi import APIRouter, Depends, FastAPI
from fastapi.responses import HTMLResponse
import sys

from nexy.hooks import useView
from .utils import deleteFistDotte, dynamicRoute, importModule, convertPathToModulePath

# Analyze the file structure and extract route information
def FIND_ROUTES(base_path):
    routes: list = []
    
    # Verify if the 'app' folder exists
    if os.path.exists(base_path) and os.path.isdir(base_path):
        # Add app directory to Python path
        app_dir = os.path.abspath(base_path)
        if app_dir not in sys.path:
            sys.path.append(app_dir)
            
        # Explore the 'app' folder and its subfolders
        for root, dirs, files in os.walk(base_path):
            # Remove _folders
            dirs[:] = [d for d in dirs if not d.startswith("_")]

            route = {
                "pathname": f"{'/' if os.path.basename(root) == base_path else '/' + deleteFistDotte(os.path.relpath(root, base_path).replace('\\','/'))}",
                "dirName": root
            }
            controller = os.path.join(root, 'controller.py')
            middleware = os.path.join(root, 'middleware.py')
            service = os.path.join(root, 'service.py')

            # Check for files and add to dictionary
            if os.path.exists(controller):
                route["controller"] = convertPathToModulePath(f"{root}/controller")    
            if os.path.exists(middleware):
                route["middleware"] = convertPathToModulePath(f"{root}/middleware") 
            if os.path.exists(service):
                route["service"] = convertPathToModulePath(f"{root}/service") 
            routes.append(route)

    return routes


def Router(app: FastAPI):
    """
    Dynamically loads routes from the 'app' directory.
    """
    
    routes = FIND_ROUTES(base_path="app")
    HTTP_METHODES: tuple = ["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "PATCH", "TRACE"]
    
    for route in routes:

        pathname = dynamicRoute(route_in=route["pathname"])
        
        if "controller" in route:
            try:
                # Import the controller module
                try:
                    controller = importModule(path=route["controller"])
                except ModuleNotFoundError as e:
                    print(f"Error loading No Found {route['controller']}: {e}")
                    continue
                except Exception as e:
                    print(f"Error loading module {route['controller']}: {str(e)}")
                    continue
                
                for function_name in dir(controller):
                    function = getattr(controller, function_name)
                    
                    # Check if function is callable and has annotations
                    if callable(function) and hasattr(function, "__annotations__"):
                        params = getattr(function, "params", {})

                        # Add route for each HTTP method
                        if function_name in HTTP_METHODES:
                            try:

                                if params.get("response_class") == HTMLResponse:
                                    def view( data =  Depends(function)):
                                        return useView( data=data,path=f"{pathname}")
                                    app.add_api_route(
                                        path=pathname,
                                        endpoint= view,
                                        methods=[function_name], 
                                        **{key: value for key, value in params.items() if key != "tags"},
                                        tags=[pathname]
                                    )
                                else:
                                    app.add_api_route(
                                        path=pathname,
                                        endpoint=function,
                                        methods=[function_name],
                                        **{key: value for key, value in params.items() if key != "tags"},
                                        tags=[pathname]
                                    )
                                
                            except Exception as e:
                                # Handle route addition errors
                                print(f"Error adding route {pathname} for method {function_name}: {e}")
                                app.add_api_route(
                                    path=pathname,
                                    endpoint=lambda: {"error": f"Error in method {function_name} for route {pathname}. {str(e)}"},
                                    methods=[function_name],
                                    status_code=500
                                )

                        # Add WebSocket route if Socket method exists
                        elif function_name == "SOCKET":
                            try:
                                app.add_api_websocket_route(f"{pathname}/ws", function)
                            except Exception as e:
                                print(f"Error adding WebSocket for route {pathname}: {e}")
                                app.add_api_websocket_route(
                                    f"{pathname}/ws",
                                    lambda: {"error": f"Error in WebSocket connection for route {pathname}. {str(e)}"}
                                )

            except Exception as e:
                # Handle module import errors
                print(f"Error loading module {route['controller']}: {e}")
                app.add_api_route(
                    path=pathname,
                    endpoint=lambda: {"error": f"Error loading module {route['controller']}. {str(e)}"},
                    methods=["GET"],
                    status_code=500
                )
    return app
