# retoor <retoor@molodetz.nl>

import hashlib
import logging
from typing import Annotated
from datetime import datetime, timezone
from fastapi import Depends, APIRouter, Request
from fastapi.responses import HTMLResponse
from devplacepy.database import get_table
from devplacepy.templating import templates
from devplacepy.utils import hash_password_async
from devplacepy.seo import base_seo_context
from devplacepy.models import ResetPasswordForm
from devplacepy.responses import respond, action_result, wants_json, json_error
from devplacepy.schemas import AuthPageOut
from devplacepy.services.audit import record as audit
from devplacepy.dependencies import json_or_form

logger = logging.getLogger(__name__)
router = APIRouter()

@router.get("/reset-password/{token}", response_class=HTMLResponse)
async def reset_password_page(request: Request, token: str):
    seo_ctx = base_seo_context(
        request,
        title="Set New Password",
        robots="noindex,nofollow",
    )
    return respond(
        request,
        "reset_password.html",
        {
            **seo_ctx,
            "request": request,
            "page": "reset-password",
            "token": token,
        },
        model=AuthPageOut,
    )

@router.post("/reset-password/{token}")
async def reset_password(
    request: Request, token: str, data: Annotated[ResetPasswordForm, Depends(json_or_form(ResetPasswordForm))]
):
    password = data.password
    errors = []

    resets = get_table("password_resets")
    users = get_table("users")
    token_hash = hashlib.sha256(token.encode()).hexdigest()
    matched = resets.find_one(token=token_hash, used=False)

    expired = False
    if matched:
        expires = datetime.fromisoformat(matched["expires_at"])
        if expires.tzinfo is None:
            expires = expires.replace(tzinfo=timezone.utc)
        expired = expires < datetime.now(timezone.utc)

    if not matched or expired:
        errors.append("Invalid or expired reset token")
        if wants_json(request):
            return json_error(400, errors[0], errors=errors)
        seo_ctx = base_seo_context(
            request, title="Set New Password", robots="noindex,nofollow"
        )
        return templates.TemplateResponse(
            request,
            "reset_password.html",
            {
                **seo_ctx,
                "request": request,
                "token": token,
                "errors": errors,
            },
        )

    users.update(
        {"uid": matched["user_uid"], "password_hash": await hash_password_async(password)},
        ["uid"],
    )
    resets.update({"id": matched["id"], "used": True}, ["id"])
    logger.info(f"Password reset completed for user {matched['user_uid']}")
    reset_user = users.find_one(uid=matched["user_uid"])
    audit.record(
        request,
        "auth.password.reset_complete",
        user=reset_user,
        actor_kind="user",
        target_type="user",
        target_uid=matched["user_uid"],
        target_label=reset_user.get("username") if reset_user else None,
        summary=f"password reset completed for user {reset_user.get('username') if reset_user else matched['user_uid']}",
        links=[
            audit.target(
                "user",
                matched["user_uid"],
                reset_user.get("username") if reset_user else None,
            )
        ],
    )
    return action_result(request, "/auth/login")
