from typing import Annotated

from argon2 import PasswordHasher
from fastapi import Cookie, Depends, Form, HTTPException
from fastapi.security import OAuth2PasswordRequestForm

from rvpc.auth.tokens.admin_tokens import AuthentifiedAdmin
from rvpc.auth.types import PasswordValidated, PasswordValidationError
from rvpc.db import SessionDep
from rvpc.models.models import AppAdmin, Location


async def validate_admin(
    admin: AppAdmin,
    password: Annotated[str, Form()],
):
    ph = PasswordHasher()

    if not ph.verify(hash=admin.password_hash, password=password):
        return PasswordValidationError("")

    return PasswordValidated(username=admin.name)


async def admin_login(
    session: SessionDep,
    form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> AppAdmin | PasswordValidationError:
    admin = session.get(AppAdmin, form_data.username)

    if admin is None:
        return PasswordValidationError("No match for username")

    validation_result = await validate_admin(
        admin=admin, password=form_data.password
    )

    if isinstance(validation_result, PasswordValidated):
        return admin

    return validation_result


LoggedAdmin = Annotated[
    AppAdmin | PasswordValidationError, Depends(admin_login)
]


async def get_loc_info(
    session: SessionDep,
    location: Annotated[str | None, Cookie()] | str,
) -> Location:
    loc_info = session.get(Location, location)
    if loc_info is not None:
        return loc_info

    raise HTTPException(status_code=400)


LocInfo = Annotated[Location, Depends(get_loc_info)]


async def match_location(admin: AuthentifiedAdmin, loc_info: LocInfo):
    if loc_info.assigned_admin == admin:
        return loc_info

    raise HTTPException(status_code=403)


async def match_loc_on_login(admin: LoggedAdmin, loc_info: LocInfo):
    if loc_info.assigned_admin == admin:
        return loc_info
    raise HTTPException(status_code=403)
MatchingLocInfo = Annotated[Location, Depends(match_location)]
MatchingLocLogin = Annotated[Location, Depends(match_loc_on_login)]
