import sys
import logging
from functools import wraps
import petl
from enum import StrEnum
from typing import Optional
from collections.abc import Callable
from pydantic import BaseModel, Field
from scim_filter_petl import compile_scim_filter
from logging.config import dictConfig
dictConfig(
    {
        "version": 1,
        "formatters": {
            "default": {
                "format": "[%(asctime)s] %(levelname)s in %(module)s: %(message)s",
            }
        },
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "stream": "ext://sys.stdout",
                "formatter": "default",
            }
        },
        "root": {"level": "DEBUG", "handlers": ["console"]},
    }
)
# logging.StreamHandler(sys.stdout)
logger = logging.getLogger(__name__)


class EnumLCMAction(StrEnum):
    WRITEBACK = 'writeback'


class SCIMAction(BaseModel):
    action: Callable
    name: Optional[str] = None

class App(BaseModel):
    actions: Optional[dict[EnumLCMAction, list[SCIMAction]]] = Field(default_factory=lambda: {})


class LCM_APPS_MODEL(BaseModel):
    apps: Optional[dict[str, App]] = Field(default_factory=lambda: {})

    def get_app_actions(self, appname, action):

        return self.apps[appname].actions[action]


# SCIM_APPS = {}
LCM_APPS = LCM_APPS_MODEL()


def lcm_action(_func=None, app_label=None, action=None, **kwargs):

    def inner(func):
        
        nonlocal app_label

        @wraps(func)
        def wrapper(*args, **kwargs):
            """A wrapper function"""

            # Extend some capabilities of func
            

            return {'result': func(*args, **kwargs)}

        # do something before the decorator is returned
        # HOOK_EVENTS[event]['hooks'].append(wrapper)
        

        LCM_APPS.apps.setdefault(app_label, App())
        LCM_APPS.apps[app_label].actions.setdefault(action, [])
        LCM_APPS.apps[app_label].actions[action].append(SCIMAction(action=wrapper))

        return wrapper

    if _func is None:
        return inner
    else:
        return inner(_func)
