from fastapi import APIRouter, FastAPI, Request
from fastapi.security import OAuth2PasswordBearer
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import contains_eager
from sqlmodel import select

from rvpc.auth.admin import (
    LoggedAdmin,
    MatchingLocInfo,
)
from rvpc.auth.tokens.admin_tokens import (
    AuthentifiedAdmin,
    generate_admin_token,
)
from rvpc.auth.tokens.utils import clean_up, clean_up_capture
from rvpc.db import SessionDep
from rvpc.models.models import (
    AppAdmin,
    Country,
    Location,
    TokenInfo,
)
from rvpc.routers.admin.messages import disabled_message, enabled_message
from rvpc.routers.utils import hx_redirect, smart

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


def make_admin(prefix: str, templates: Jinja2Templates):
    admin = APIRouter(prefix=prefix)

    @admin.get("/login")
    @smart("admin/login.html")
    async def render_login(admin: AuthentifiedAdmin):
        if admin is not None:
            return hx_redirect(path="/admin/dashboard")

    @admin.get("/dashboard")
    @smart("admin/dashboard.html")
    async def render_dashboard(admin: AuthentifiedAdmin, session: SessionDep):
        if admin is not None:
            stmt = (
                select(Country)
                .join(Country.locations)
                .filter(Location.assigned_admin_name == admin.name)
                .options(contains_eager(Country.locations))
            )
            countries = session.exec(stmt).unique()

            return {"countries": countries}

    @admin.post("/login")
    async def process_login(session: SessionDep, logged_admin: LoggedAdmin):
        try:
            if isinstance(logged_admin, AppAdmin):
                token, generic_token = generate_admin_token(
                    admin=logged_admin, token_type="admin"
                )
                token_info = TokenInfo(
                    nonce=generic_token.nonce,
                    expires_at=generic_token.expires_at,
                    token_type=generic_token.token_type,
                )
                session.add(token_info)
                session.commit()
                response = hx_redirect(path="/admin/dashboard")

                response.set_cookie("admin_session", value=token)

                return response
        finally:
            clean_up()

    @admin.post("/disable")
    async def process_disable_capture(
        session: SessionDep,
        admin: AuthentifiedAdmin,
        matching_loc: MatchingLocInfo,
        request: Request,
    ):
        try:
            if isinstance(admin, AppAdmin):
                matching_loc.enabled = False
                session.add(matching_loc)
                session.commit()
                session.refresh(matching_loc)

                response = templates.TemplateResponse(
                    request=request,
                    name="admin/check.html",
                    context={"location": matching_loc},
                )
                await disabled_message(
                    request=request, loc_name=matching_loc.name
                )

                return response
        finally:
            clean_up_capture()

    @admin.post("/enable")
    async def process_enable_capture(
        session: SessionDep,
        admin: AuthentifiedAdmin,
        matching_loc: MatchingLocInfo,
        request: Request,
    ):
        try:
            if isinstance(admin, AppAdmin):
                matching_loc.enabled = True
                session.add(matching_loc)
                session.commit()
                session.refresh(matching_loc)
                response = templates.TemplateResponse(
                    request=request,
                    name="admin/check.html",
                    context={"location": matching_loc},
                )
                await enabled_message(
                    request=request, loc_name=matching_loc.name
                )

                return response
        finally:
            clean_up_capture()

    return admin
