"""Gemeinsame Passwort-Link-Erzeugung (Sessions) + Mailtext — wie /auth/forgot-password."""
from __future__ import annotations

import os
import secrets
from datetime import datetime, timedelta
from typing import Any

RESET_TOKEN_PREFIX = "reset_"


def public_reset_link(token: str) -> str:
    base = (os.getenv("APP_URL") or "https://shinkan.jinkendo.de").rstrip("/")
    return f"{base}/reset-password?token={token}"


def revoke_pending_password_resets_for_profile(cur: Any, profile_id: int) -> None:
    """Entfernt alte Reset-Sessions eines Profils, damit nur der neueste Link aktiv ist."""
    cur.execute(
        """
        DELETE FROM sessions
        WHERE profile_id = %s AND token LIKE %s
        """,
        (profile_id, f"{RESET_TOKEN_PREFIX}%"),
    )


def insert_password_reset_session(cur: Any, profile_id: int, *, hours_valid: int = 1) -> str:
    """
    Legt reset_<token>-Session an. Gibt den Klartext-Token zurück (wie bei forgot-password).
    """
    raw = secrets.token_urlsafe(32)
    expires = datetime.now() + timedelta(hours=hours_valid)
    cur.execute(
        """
        INSERT INTO sessions (token, profile_id, expires_at, created_at)
        VALUES (%s, %s, %s, CURRENT_TIMESTAMP)
        """,
        (f"{RESET_TOKEN_PREFIX}{raw}", profile_id, expires.isoformat()),
    )
    return raw


def password_reset_email_body(*, recipient_name: str | None, token: str, intro: str) -> str:
    name = (recipient_name or "").strip() or "Kollege/Kollegin"
    link = public_reset_link(token)
    return f"""Hallo {name},

{intro}

Neues Passwort setzen:
{link}

Der Link ist 1 Stunde gültig. Erst wenn du ihn nutzt und ein neues Passwort wählst, wird dein bestehendes
Passwort ersetzt — bis dahin kannst du dich wie gewohnt anmelden.

Falls du diese Anfrage nicht erwartest, ignoriere diese E-Mail; dein Zugang bleibt unverändert.

Dein Shinkan Jinkendo Team
"""


def issue_password_reset_via_email(cur: Any, send_email_fn, *, profile_id: int, email: str, name: str | None, intro: str) -> bool:
    """Session anlegen und Mail schicken (send_email_fn wie routers.auth.send_email)."""
    revoke_pending_password_resets_for_profile(cur, profile_id)
    raw_token = insert_password_reset_session(cur, profile_id)
    body = password_reset_email_body(recipient_name=name, token=raw_token, intro=intro)
    return send_email_fn(email, "Passwort-Link – Shinkan Jinkendo", body)
