# retoor <retoor@molodetz.nl>

import logging
from typing import Annotated

from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse

from devplacepy.dependencies import json_or_form
from devplacepy.models import AccountDeleteForm
from devplacepy.responses import action_result, json_error, respond
from devplacepy.routers.profile._shared import resolve_customization_target
from devplacepy.schemas import AccountDeletionOut
from devplacepy.seo import base_seo_context
from devplacepy.services.audit import record as audit
from devplacepy.services.moderation import deletion
from devplacepy.utils import get_current_user, verify_password_async

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

REMOVED = [
    "Your account record, username, email address and password",
    "Your profile: bio, location, links and avatar",
    "Your posts, comments, gists, projects, project files and quizzes",
    "Your uploads and media gallery",
    "Your direct-message history, votes, reactions, bookmarks and polls",
    "Your API key, access tokens and every signed-in session",
    "Your assistant conversations, tasks, lessons and custom tools",
]

RETAINED = [
    "Append-only audit and moderation records, which hold identifiers rather than "
    "your profile, so the platform can show it enforced its own rules",
    "Backup archives, until they rotate out on their normal schedule",
]


def _owner_only(
    request: Request,
    username: str,
    message: str = "Only the account holder can delete this account",
):
    target, denied = resolve_customization_target(request, username)
    if denied is not None:
        return None, denied
    viewer = get_current_user(request)
    if not viewer or viewer["uid"] != target["uid"]:
        audit.record(
            request,
            "security.authz.denied",
            user=viewer,
            result="denied",
            target_type="user",
            target_uid=target["uid"],
            target_label=target["username"],
            metadata={"reason": message},
            summary=f"non-owner denied {request.method} {request.url.path}",
            links=[audit.target("user", target["uid"], target["username"])],
        )
        return None, json_error(403, message)
    return target, None


async def _password_matches(password: str, hashed: str) -> bool:
    if not hashed:
        return False
    try:
        return await verify_password_async(password, hashed)
    except ValueError:
        return False


@router.get("/{username}/delete", response_class=HTMLResponse)
async def delete_account_page(request: Request, username: str):
    target, denied = _owner_only(request, username)
    if denied is not None:
        return denied
    seo_ctx = base_seo_context(
        request,
        title="Delete your account",
        description="Permanently remove your DevPlace account and personal data.",
        robots="noindex,nofollow",
        breadcrumbs=[
            {"name": "Home", "url": "/feed"},
            {"name": target["username"], "url": f"/profile/{target['username']}"},
            {
                "name": "Delete account",
                "url": f"/profile/{target['username']}/delete",
            },
        ],
    )
    return respond(
        request,
        "account_delete.html",
        {
            **seo_ctx,
            "request": request,
            "user": target,
            "username": target["username"],
            "grace_hours": deletion.grace_hours(),
            "removed": REMOVED,
            "retained": RETAINED,
        },
        model=AccountDeletionOut,
    )


@router.post("/{username}/delete")
async def delete_account(
    request: Request,
    username: str,
    data: Annotated[AccountDeleteForm, Depends(json_or_form(AccountDeleteForm))],
):
    target, denied = _owner_only(request, username)
    if denied is not None:
        return denied
    if not await _password_matches(data.password, target.get("password_hash", "")):
        audit.record(
            request,
            "account.delete.request",
            result="denied",
            target_type="user",
            target_uid=target["uid"],
            target_label=target["username"],
            summary=f"account deletion for {target['username']} refused: wrong password",
            links=[audit.target("user", target["uid"], target["username"])],
        )
        return json_error(403, "That password is not correct")
    result = deletion.delete_account(target)
    if result is None:
        return json_error(409, "This account is already being deleted")
    logger.info(f"Account {target['username']} deleted by request")
    audit.record(
        request,
        "account.delete.request",
        target_type="user",
        target_uid=target["uid"],
        target_label=target["username"],
        metadata={
            "stamp": result["stamp"],
            "rows": result["rows"],
            "grace_hours": result["grace_hours"],
        },
        summary=f"account {target['username']} deleted",
        links=[audit.target("user", target["uid"], target["username"])],
    )
    response = action_result(request, "/", data=result)
    response.delete_cookie("session")
    return response
