from datasette.permissions import Action
from datasette import hookimpl
from .internal_migrations import internal_migrations
from sqlite_utils import Database
from functools import wraps
from urllib.parse import urlencode
import asyncio
import os

from . import hookspecs

from datasette.plugins import pm
from datasette_vite import vite_entry

from .bg_task import bg_task, Notifier
from .internal_db import InternalDB, NewAlertRouteParameters, NewSubscription
_ = (InternalDB, NewAlertRouteParameters, NewSubscription)

# Import route module to trigger route registration on the shared router
from . import routes
from .router import router, ALERTS_ACCESS_NAME

_ = (routes,)

__all___ = [
    Notifier,
]

pm.add_hookspecs(hookspecs)

@hookimpl
async def startup(datasette):
    def migrate(connection):
        db = Database(connection)
        internal_migrations.apply(db)

    await datasette.get_internal_database().execute_write_fn(migrate)


@hookimpl
def asgi_wrapper(datasette):
    def wrap_with_alerts(app):
        @wraps(app)
        async def record_last_request(scope, receive, send):
            if not hasattr(datasette, "_alertx"):
                asyncio.create_task(bg_task(datasette))
            datasette._alertx = 1
            await app(scope, receive, send)

        return record_last_request

    return wrap_with_alerts


@hookimpl
def register_routes():
    return router.routes()


@hookimpl
def extra_template_vars(datasette):
    entry = vite_entry(
        datasette=datasette,
        plugin_package="datasette_alerts",
        vite_dev_path=os.environ.get("DATASETTE_ALERTS_VITE_PATH"),
    )
    return {"datasette_alerts_vite_entry": entry}



@hookimpl
def table_actions(datasette, actor, database, table, request):
    async def check():
        allowed = await datasette.allowed(
            action=ALERTS_ACCESS_NAME, actor=actor
        )
        if allowed:
            # Extract filter params (non-_ params, or params with __ in them)
            filter_args = []
            if request and request.args:
                for key in request.args:
                    if key.startswith("_") and "__" not in key:
                        continue
                    for v in request.args.getlist(key):
                        filter_args.append((key, v))

            params = urlencode([("table_name", table)] + filter_args)
            if filter_args:
                params += "&alert_type=trigger"

            return [
                {
                    "href": datasette.urls.path(
                        f"/-/{database}/datasette-alerts/new?{params}"
                    ),
                    "label": "Configure new alert",
                    "description": "Receive notifications when new records are added or changed to this table",
                }
            ]

    return check

@hookimpl
def database_actions(datasette, actor, database, request):
    async def check():
        allowed = await datasette.allowed(
            action=ALERTS_ACCESS_NAME, actor=actor
        )
        if allowed:
            return [
                {
                    "href": datasette.urls.path(
                        f"/-/{database}/datasette-alerts"
                    ),
                    "label": "Alerts",
                    "description": "View and manage alerts for this database",
                }
            ]

    return check


@hookimpl
def register_actions(datasette):
    return [
        Action(
            name=ALERTS_ACCESS_NAME,
            description="Can access datasette alerts ",
        )
    ]