import logging
from typing import Annotated

from fastapi import APIRouter, Cookie
from fastapi.templating import Jinja2Templates
from sqlmodel import select

from rvpc.auth.admin import (
    LoggedAdmin,
    MatchingLocLogin,
)
from rvpc.auth.device import MatchingDevice, NewOrExistingDevice
from rvpc.auth.tokens.capture_tokens import (
    ValidCaptureTokenInfo,
    generate_capture_token,
)
from rvpc.auth.tokens.utils import clean_up
from rvpc.db import SessionDep
from rvpc.models.models import AppAdmin, CaptureTokenInfo, Location
from rvpc.routers.utils import hx_redirect, smart


def make_device(prefix: str, templates: Jinja2Templates):
    device = APIRouter(prefix=prefix)

    @device.get("/menu")
    @smart("device/menu.html")
    async def render_device_menu(session: SessionDep):
        locations = session.exec(select(Location)).all()
        return {"locations": locations}

    @device.get("/add")
    @smart("device/add.html")
    async def render_device_auth(location: str):
        return {"location": location}

    @device.get("/remove")
    @smart("device/remove.html")
    async def render_device_disable(location: Annotated[str, Cookie()]):
        return {"location": location}

    @device.post("/add")
    async def enable_device(
        session: SessionDep,
        matching_loc: MatchingLocLogin,
        logged_admin: LoggedAdmin,
        device: NewOrExistingDevice,
    ):
        try:
            if isinstance(logged_admin, AppAdmin):
                token, generic_token = generate_capture_token(
                    admin=logged_admin,
                    expires_in=3600,
                )

                token_info = CaptureTokenInfo(
                    nonce=generic_token.nonce,
                    expires_at=generic_token.expires_at,
                    token_type="capture",
                    admin=logged_admin,
                    location=matching_loc,
                )

                session.add(matching_loc)
                session.add(token_info)
                session.commit()

                response = hx_redirect("/cards/new")
                response.headers.append("hx-trigger", "deviceStatusChange")
                response.set_cookie("capture_session", value=token)
                response.set_cookie("device", value=str(device.id))
                response.set_cookie("location", value=matching_loc.name)

                return response
        finally:
            clean_up()

    @device.post("/remove")
    async def remove(
        session: SessionDep,
        matching_device: MatchingDevice,
        token_info: ValidCaptureTokenInfo,
        logged_admin: LoggedAdmin,
    ):
        try:
            if isinstance(logged_admin, AppAdmin):
                logging.warning(token_info)
                session.delete(token_info)
                session.delete(matching_device)
                session.commit()

                response = hx_redirect("/map")
                response.headers.append("hx-trigger", "deviceStatusChange")
                response.delete_cookie("capture_session")
                response.delete_cookie("device")
                response.delete_cookie("location")

                return response
        finally:
            clean_up()

    return device
