"""Passkey-backed manager authentication for the hosted coordinator UI."""

from __future__ import annotations

import hashlib
import json
import secrets
import uuid
from typing import Any

import structlog
from fastapi import HTTPException, Request, Response

from hive_compute.config import get_settings
from hive_compute.coordinator.database import get_db_ctx
from hive_compute.coordinator.request_cache import get_request_cache

logger = structlog.get_logger()

try:
    from webauthn import (
        generate_authentication_options,
        generate_registration_options,
        options_to_json,
        verify_authentication_response,
        verify_registration_response,
    )
    from webauthn.helpers import base64url_to_bytes, bytes_to_base64url
    from webauthn.helpers.structs import (
        AuthenticatorSelectionCriteria,
        PublicKeyCredentialDescriptor,
        ResidentKeyRequirement,
        UserVerificationRequirement,
    )

    WEBAUTHN_AVAILABLE = True
    WEBAUTHN_IMPORT_ERROR = None
except ImportError as exc:  # pragma: no cover - exercised only in missing-dependency environments
    WEBAUTHN_AVAILABLE = False
    WEBAUTHN_IMPORT_ERROR = exc

SESSION_COOKIE_NAME = "hive_admin_session"


def ensure_webauthn_available() -> None:
    if WEBAUTHN_AVAILABLE:
        return

    raise HTTPException(
        status_code=503,
        detail=(
            "Passkeys are unavailable because the 'webauthn' package is not installed. "
            "Install the coordinator dependencies again after adding the new package."
        ),
    )


def count_admin_users() -> int:
    with get_db_ctx() as db:
        row = db.execute("SELECT COUNT(*) as cnt FROM admin_users").fetchone()
    return row["cnt"] if row else 0


def get_manager_config() -> dict[str, Any]:
    settings = get_settings()
    admin_count = count_admin_users()
    return {
        "rpId": settings.get_manager_rp_id(),
        "rpName": settings.manager_rp_name,
        "origins": settings.get_manager_origins(),
        "bootstrapEnabled": bool(settings.admin_bootstrap_secret) and admin_count == 0,
        "hasAdmins": admin_count > 0,
        "passkeysAvailable": WEBAUTHN_AVAILABLE,
    }


def begin_bootstrap(username: str, display_name: str | None, bootstrap_secret: str) -> dict[str, Any]:
    ensure_webauthn_available()
    settings = get_settings()

    if not settings.admin_bootstrap_secret:
        raise HTTPException(status_code=503, detail="Admin bootstrap is not configured")

    if count_admin_users() > 0:
        raise HTTPException(
            status_code=409,
            detail="Bootstrap is disabled after the first manager account is enrolled",
        )

    if not secrets.compare_digest(bootstrap_secret, settings.admin_bootstrap_secret):
        raise HTTPException(status_code=403, detail="Invalid bootstrap secret")

    allowed_users = settings.get_bootstrap_users()
    if allowed_users and username not in allowed_users:
        raise HTTPException(status_code=403, detail="This username cannot bootstrap manager access")

    normalized_display_name = (display_name or username).strip() or username

    with get_db_ctx() as db:
        _cleanup_stale_manager_records(db)
        admin = _get_or_create_admin_user(db, username, normalized_display_name)
        credential_rows = db.execute(
            """
            SELECT credential_id, transports
            FROM admin_webauthn_credentials
            WHERE admin_user_id = ?
            ORDER BY created_at ASC
            """,
            (admin["admin_user_id"],),
        ).fetchall()

        options = generate_registration_options(
            rp_id=settings.get_manager_rp_id(),
            rp_name=settings.manager_rp_name,
            user_name=admin["username"],
            user_id=admin["admin_user_id"].encode(),
            user_display_name=admin["display_name"],
            authenticator_selection=AuthenticatorSelectionCriteria(
                resident_key=ResidentKeyRequirement.PREFERRED,
                user_verification=UserVerificationRequirement.REQUIRED,
            ),
            exclude_credentials=[
                PublicKeyCredentialDescriptor(id=base64url_to_bytes(row["credential_id"]))
                for row in credential_rows
            ]
            or None,
        )

        challenge_id = uuid.uuid4().hex
        db.execute(
            """
            INSERT INTO admin_challenges (challenge_id, admin_user_id, challenge_type, challenge, expires_at)
            VALUES (?, ?, 'registration', ?, datetime('now', '+5 minutes'))
            """,
            (challenge_id, admin["admin_user_id"], bytes_to_base64url(options.challenge)),
        )
        _record_admin_audit(db, admin["admin_user_id"], "bootstrap_start", f"user={admin['username']}")

    return {
        "challengeId": challenge_id,
        "options": json.loads(options_to_json(options)),
    }


def finish_bootstrap(
    challenge_id: str,
    credential: dict[str, Any],
    user_agent: str | None,
) -> tuple[dict[str, Any], str]:
    ensure_webauthn_available()
    settings = get_settings()

    with get_db_ctx() as db:
        _cleanup_stale_manager_records(db)

        # Re-check inside the transaction to close the TOCTOU window between
        # begin_bootstrap and finish_bootstrap: another admin may have fully
        # enrolled (user + credential) in between.
        enrolled = db.execute(
            "SELECT COUNT(*) as cnt FROM admin_webauthn_credentials"
        ).fetchone()
        if enrolled and enrolled["cnt"] > 0:
            raise HTTPException(
                status_code=409,
                detail="Bootstrap is disabled after the first manager account is enrolled",
            )

        challenge = _get_challenge(db, challenge_id, "registration")
        admin = _get_admin_user_by_id(db, challenge["admin_user_id"])
        if not admin:
            raise HTTPException(status_code=404, detail="Admin user not found")

        try:
            verified = verify_registration_response(
                credential=credential,
                expected_challenge=base64url_to_bytes(challenge["challenge"]),
                expected_rp_id=settings.get_manager_rp_id(),
                expected_origin=settings.get_manager_origins(),
                require_user_verification=True,
            )
        except Exception as exc:  # pragma: no cover - library raises several concrete exception types
            raise HTTPException(status_code=400, detail=f"Passkey registration failed: {exc}") from exc

        transports = credential.get("response", {}).get("transports")
        db.execute(
            """
            INSERT OR REPLACE INTO admin_webauthn_credentials
                (credential_id, admin_user_id, public_key, sign_count, transports, aaguid,
                 credential_device_type, credential_backed_up, last_used_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
            """,
            (
                bytes_to_base64url(verified.credential_id),
                admin["admin_user_id"],
                verified.credential_public_key,
                verified.sign_count,
                json.dumps(transports) if transports else None,
                verified.aaguid,
                verified.credential_device_type.value,
                1 if verified.credential_backed_up else 0,
            ),
        )
        db.execute("DELETE FROM admin_challenges WHERE challenge_id = ?", (challenge_id,))
        _record_admin_audit(db, admin["admin_user_id"], "bootstrap_finish", f"user={admin['username']}")
        session_token = _create_session(db, admin["admin_user_id"], user_agent)

    return _serialize_admin_user(admin), session_token


def regenerate_recovery_codes(admin_user_id: str, count: int = 8) -> dict[str, Any]:
    """Replace any unused recovery codes for the admin and return new plaintext codes once."""
    with get_db_ctx() as db:
        _cleanup_stale_manager_records(db)
        admin = _get_admin_user_by_id(db, admin_user_id)
        if not admin:
            raise HTTPException(status_code=404, detail="Admin user not found")

        db.execute(
            """
            UPDATE admin_recovery_codes
            SET revoked_at = datetime('now')
            WHERE admin_user_id = ? AND used_at IS NULL AND revoked_at IS NULL
            """,
            (admin_user_id,),
        )

        codes: list[str] = []
        for _ in range(count):
            recovery_code = _generate_recovery_code()
            db.execute(
                """
                INSERT INTO admin_recovery_codes (recovery_code_id, admin_user_id, code_hash)
                VALUES (?, ?, ?)
                """,
                (
                    f"recovery_{uuid.uuid4().hex[:12]}",
                    admin_user_id,
                    _hash_token(recovery_code),
                ),
            )
            codes.append(recovery_code)

        _record_admin_audit(db, admin_user_id, "recovery_codes_regenerated", f"count={count}")

    return {
        "codes": codes,
        "count": count,
        "message": "Store these recovery codes somewhere safe. They are shown only once.",
    }


def begin_login(username: str) -> dict[str, Any]:
    ensure_webauthn_available()
    settings = get_settings()

    with get_db_ctx() as db:
        _cleanup_stale_manager_records(db)
        admin = db.execute(
            """
            SELECT admin_user_id, username, display_name, role, status
            FROM admin_users
            WHERE username = ? AND status = 'active'
            """,
            (username,),
        ).fetchone()
        if not admin:
            raise HTTPException(status_code=404, detail="Manager user not found")

        credential_rows = db.execute(
            """
            SELECT credential_id, transports
            FROM admin_webauthn_credentials
            WHERE admin_user_id = ?
            ORDER BY created_at ASC
            """,
            (admin["admin_user_id"],),
        ).fetchall()
        if not credential_rows:
            raise HTTPException(status_code=400, detail="This user has no passkeys enrolled yet")

        options = generate_authentication_options(
            rp_id=settings.get_manager_rp_id(),
            allow_credentials=[
                PublicKeyCredentialDescriptor(id=base64url_to_bytes(row["credential_id"]))
                for row in credential_rows
            ],
            user_verification=UserVerificationRequirement.REQUIRED,
        )

        challenge_id = uuid.uuid4().hex
        db.execute(
            """
            INSERT INTO admin_challenges (challenge_id, admin_user_id, challenge_type, challenge, expires_at)
            VALUES (?, ?, 'authentication', ?, datetime('now', '+5 minutes'))
            """,
            (challenge_id, admin["admin_user_id"], bytes_to_base64url(options.challenge)),
        )
        _record_admin_audit(db, admin["admin_user_id"], "login_start", f"user={admin['username']}")

    return {
        "challengeId": challenge_id,
        "options": json.loads(options_to_json(options)),
    }


def begin_recovery_registration(username: str, recovery_code: str) -> dict[str, Any]:
    """Authenticate with a recovery code and begin passkey re-enrollment."""
    ensure_webauthn_available()
    settings = get_settings()

    with get_db_ctx() as db:
        _cleanup_stale_manager_records(db)
        admin = db.execute(
            """
            SELECT admin_user_id, username, display_name, role, status
            FROM admin_users
            WHERE username = ? AND status = 'active'
            """,
            (username,),
        ).fetchone()
        if not admin:
            raise HTTPException(status_code=404, detail="Manager user not found")

        # Validate code exists but don't consume yet — consumption happens
        # atomically in finish_recovery_registration so a failed passkey
        # enrollment doesn't burn the code.
        code_hash = _hash_token(recovery_code.strip().upper())
        recovery = db.execute(
            """
            SELECT recovery_code_id
            FROM admin_recovery_codes
            WHERE admin_user_id = ?
              AND code_hash = ?
              AND used_at IS NULL
              AND revoked_at IS NULL
            """,
            (admin["admin_user_id"], code_hash),
        ).fetchone()
        if not recovery:
            raise HTTPException(status_code=403, detail="Invalid recovery code")

        credential_rows = db.execute(
            """
            SELECT credential_id
            FROM admin_webauthn_credentials
            WHERE admin_user_id = ?
            ORDER BY created_at ASC
            """,
            (admin["admin_user_id"],),
        ).fetchall()

        options = generate_registration_options(
            rp_id=settings.get_manager_rp_id(),
            rp_name=settings.manager_rp_name,
            user_name=admin["username"],
            user_id=admin["admin_user_id"].encode(),
            user_display_name=admin["display_name"],
            authenticator_selection=AuthenticatorSelectionCriteria(
                resident_key=ResidentKeyRequirement.PREFERRED,
                user_verification=UserVerificationRequirement.REQUIRED,
            ),
            exclude_credentials=[
                PublicKeyCredentialDescriptor(id=base64url_to_bytes(row["credential_id"]))
                for row in credential_rows
            ]
            or None,
        )

        challenge_id = uuid.uuid4().hex
        db.execute(
            """
            INSERT INTO admin_challenges
                (challenge_id, admin_user_id, challenge_type, challenge, recovery_code_id, expires_at)
            VALUES (?, ?, 'recovery_registration', ?, ?, datetime('now', '+5 minutes'))
            """,
            (
                challenge_id,
                admin["admin_user_id"],
                bytes_to_base64url(options.challenge),
                recovery["recovery_code_id"],
            ),
        )
        _record_admin_audit(db, admin["admin_user_id"], "recovery_start", f"user={admin['username']}")

    return {
        "challengeId": challenge_id,
        "options": json.loads(options_to_json(options)),
    }


def finish_login(challenge_id: str, credential: dict[str, Any], user_agent: str | None) -> tuple[dict[str, Any], str]:
    ensure_webauthn_available()
    settings = get_settings()

    credential_id = credential.get("id")
    if not credential_id:
        raise HTTPException(status_code=400, detail="Credential ID is required")

    with get_db_ctx() as db:
        _cleanup_stale_manager_records(db)
        challenge = _get_challenge(db, challenge_id, "authentication")
        admin = _get_admin_user_by_id(db, challenge["admin_user_id"])
        if not admin:
            raise HTTPException(status_code=404, detail="Admin user not found")

        stored_credential = db.execute(
            """
            SELECT credential_id, public_key, sign_count
            FROM admin_webauthn_credentials
            WHERE credential_id = ? AND admin_user_id = ?
            """,
            (credential_id, admin["admin_user_id"]),
        ).fetchone()
        if not stored_credential:
            raise HTTPException(status_code=404, detail="Passkey not registered for this user")

        try:
            verified = verify_authentication_response(
                credential=credential,
                expected_challenge=base64url_to_bytes(challenge["challenge"]),
                expected_rp_id=settings.get_manager_rp_id(),
                expected_origin=settings.get_manager_origins(),
                credential_public_key=stored_credential["public_key"],
                credential_current_sign_count=stored_credential["sign_count"],
                require_user_verification=True,
            )
        except Exception as exc:  # pragma: no cover - library raises several concrete exception types
            raise HTTPException(status_code=400, detail=f"Passkey verification failed: {exc}") from exc

        db.execute(
            """
            UPDATE admin_webauthn_credentials
            SET sign_count = ?, last_used_at = datetime('now')
            WHERE credential_id = ?
            """,
            (verified.new_sign_count, credential_id),
        )
        db.execute("DELETE FROM admin_challenges WHERE challenge_id = ?", (challenge_id,))
        _record_admin_audit(db, admin["admin_user_id"], "login_finish", f"user={admin['username']}")
        session_token = _create_session(db, admin["admin_user_id"], user_agent)

    return _serialize_admin_user(admin), session_token


def finish_recovery_registration(
    challenge_id: str,
    credential: dict[str, Any],
    user_agent: str | None,
) -> tuple[dict[str, Any], str]:
    """Finish passkey re-enrollment that was initiated with a recovery code."""
    ensure_webauthn_available()
    settings = get_settings()

    with get_db_ctx() as db:
        _cleanup_stale_manager_records(db)
        challenge = _get_challenge(db, challenge_id, "recovery_registration")
        admin = _get_admin_user_by_id(db, challenge["admin_user_id"])
        if not admin:
            raise HTTPException(status_code=404, detail="Admin user not found")

        try:
            verified = verify_registration_response(
                credential=credential,
                expected_challenge=base64url_to_bytes(challenge["challenge"]),
                expected_rp_id=settings.get_manager_rp_id(),
                expected_origin=settings.get_manager_origins(),
                require_user_verification=True,
            )
        except Exception as exc:  # pragma: no cover - library raises several concrete exception types
            raise HTTPException(status_code=400, detail=f"Passkey registration failed: {exc}") from exc

        transports = credential.get("response", {}).get("transports")
        db.execute(
            """
            INSERT OR REPLACE INTO admin_webauthn_credentials
                (credential_id, admin_user_id, public_key, sign_count, transports, aaguid,
                 credential_device_type, credential_backed_up, last_used_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
            """,
            (
                bytes_to_base64url(verified.credential_id),
                admin["admin_user_id"],
                verified.credential_public_key,
                verified.sign_count,
                json.dumps(transports) if transports else None,
                verified.aaguid,
                verified.credential_device_type.value,
                1 if verified.credential_backed_up else 0,
            ),
        )
        # Atomically consume the recovery code now that enrollment succeeded.
        # UPDATE WHERE ensures only one finish can consume the same code.
        if challenge["recovery_code_id"]:
            result = db.execute(
                """
                UPDATE admin_recovery_codes
                SET used_at = datetime('now')
                WHERE recovery_code_id = ? AND used_at IS NULL AND revoked_at IS NULL
                """,
                (challenge["recovery_code_id"],),
            )
            if result.rowcount == 0:
                raise HTTPException(status_code=403, detail="Recovery code already used")
        db.execute("DELETE FROM admin_challenges WHERE challenge_id = ?", (challenge_id,))
        _record_admin_audit(db, admin["admin_user_id"], "recovery_finish", f"user={admin['username']}")
        session_token = _create_session(db, admin["admin_user_id"], user_agent)

    return _serialize_admin_user(admin), session_token


def get_current_admin(request: Request) -> dict[str, Any] | None:
    return _resolve_current_admin(request, touch_last_seen=True)


def resolve_valid_manager_session_hash(request: Request) -> str | None:
    session_token = request.cookies.get(SESSION_COOKIE_NAME)
    if not session_token:
        return None

    session_hash = _hash_token(session_token)
    admin = _resolve_current_admin(request, touch_last_seen=False)
    return session_hash if admin else None


def require_manager_admin(request: Request) -> dict[str, Any]:
    admin = get_current_admin(request)
    if admin:
        return admin

    raise HTTPException(status_code=401, detail="Manager sign-in required")


def revoke_session(request: Request) -> None:
    session_token = request.cookies.get(SESSION_COOKIE_NAME)
    if not session_token:
        return

    with get_db_ctx() as db:
        db.execute(
            """
            UPDATE admin_sessions
            SET revoked_at = datetime('now')
            WHERE session_id_hash = ? AND revoked_at IS NULL
            """,
            (_hash_token(session_token),),
        )


def _resolve_current_admin(request: Request, *, touch_last_seen: bool) -> dict[str, Any] | None:
    session_token = request.cookies.get(SESSION_COOKIE_NAME)
    if not session_token:
        return None

    session_hash = _hash_token(session_token)
    cache = get_request_cache(request)
    cache_key = ("manager_session", session_hash)
    entry = cache.get(cache_key)
    if isinstance(entry, dict):
        admin = entry.get("admin")
        if not admin:
            return None
        if touch_last_seen and not entry.get("last_seen_touched"):
            with get_db_ctx() as db:
                db.execute(
                    "UPDATE admin_sessions SET last_seen_at = datetime('now') WHERE session_id_hash = ?",
                    (session_hash,),
                )
            entry["last_seen_touched"] = True
        return admin

    with get_db_ctx() as db:
        _cleanup_stale_manager_records(db)
        row = db.execute(
            """
            SELECT
                u.admin_user_id,
                u.username,
                u.display_name,
                u.role,
                u.status,
                u.created_at,
                u.last_login_at
            FROM admin_sessions s
            JOIN admin_users u ON u.admin_user_id = s.admin_user_id
            WHERE s.session_id_hash = ?
              AND s.revoked_at IS NULL
              AND s.expires_at > datetime('now')
              AND u.status = 'active'
            """,
            (session_hash,),
        ).fetchone()
        if not row:
            cache[cache_key] = {"admin": None, "last_seen_touched": False}
            return None

        admin = _serialize_admin_user(row)
        last_seen_touched = False
        if touch_last_seen:
            db.execute(
                "UPDATE admin_sessions SET last_seen_at = datetime('now') WHERE session_id_hash = ?",
                (session_hash,),
            )
            last_seen_touched = True

    cache[cache_key] = {"admin": admin, "last_seen_touched": last_seen_touched}
    return admin


def set_session_cookie(response: Response, session_token: str) -> None:
    settings = get_settings()
    response.set_cookie(
        key=SESSION_COOKIE_NAME,
        value=session_token,
        max_age=settings.manager_session_hours * 3600,
        httponly=True,
        secure=settings.is_manager_cookie_secure(),
        samesite="strict",
        path="/",
    )


def clear_session_cookie(response: Response) -> None:
    response.delete_cookie(SESSION_COOKIE_NAME, path="/")


def record_manager_action(admin: dict[str, Any], action: str, detail: str | None = None) -> None:
    """Best-effort audit log — never raises, so mutations don't fail on logging."""
    try:
        with get_db_ctx() as db:
            _record_admin_audit(db, admin["adminUserId"], action, detail)
    except Exception:
        logger.warning("Failed to record manager audit", action=action, exc_info=True)


def list_admin_audit(limit: int = 25) -> list[dict[str, Any]]:
    with get_db_ctx() as db:
        rows = db.execute(
            """
            SELECT
                l.audit_id, l.action, l.detail, l.created_at,
                u.admin_user_id, u.username, u.display_name, u.role
            FROM admin_audit_log l
            LEFT JOIN admin_users u ON u.admin_user_id = l.admin_user_id
            ORDER BY l.created_at DESC, l.audit_id DESC
            LIMIT ?
            """,
            (limit,),
        ).fetchall()

    return [
        {
            "auditId": row["audit_id"],
            "action": row["action"],
            "detail": row["detail"],
            "createdAt": row["created_at"],
            "admin": {
                "adminUserId": row["admin_user_id"],
                "username": row["username"],
                "displayName": row["display_name"],
                "role": row["role"],
            } if row["admin_user_id"] else None,
        }
        for row in rows
    ]


def _get_or_create_admin_user(db, username: str, display_name: str):
    admin = db.execute(
        """
        SELECT admin_user_id, username, display_name, role, status, created_at, last_login_at
        FROM admin_users
        WHERE username = ?
        """,
        (username,),
    ).fetchone()
    if admin:
        return admin

    admin_user_id = f"admin_{uuid.uuid4().hex[:12]}"
    db.execute(
        """
        INSERT INTO admin_users (admin_user_id, username, display_name, role, status)
        VALUES (?, ?, ?, 'developer', 'active')
        """,
        (admin_user_id, username, display_name),
    )
    return _get_admin_user_by_id(db, admin_user_id)


def _get_admin_user_by_id(db, admin_user_id: str):
    return db.execute(
        """
        SELECT admin_user_id, username, display_name, role, status, created_at, last_login_at
        FROM admin_users
        WHERE admin_user_id = ?
        """,
        (admin_user_id,),
    ).fetchone()


def _get_challenge(db, challenge_id: str, challenge_type: str):
    challenge = db.execute(
        """
        SELECT challenge_id, admin_user_id, challenge_type, challenge, recovery_code_id, expires_at
        FROM admin_challenges
        WHERE challenge_id = ?
          AND challenge_type = ?
          AND expires_at > datetime('now')
        """,
        (challenge_id, challenge_type),
    ).fetchone()
    if challenge:
        return challenge

    raise HTTPException(status_code=400, detail="Passkey challenge expired or was not found")


def _cleanup_stale_manager_records(db) -> None:
    db.execute("DELETE FROM admin_challenges WHERE expires_at <= datetime('now')")
    db.execute(
        """
        DELETE FROM admin_sessions
        WHERE expires_at <= datetime('now') OR revoked_at IS NOT NULL
        """
    )


def _create_session(db, admin_user_id: str, user_agent: str | None) -> str:
    token = secrets.token_urlsafe(32)
    db.execute(
        """
        INSERT INTO admin_sessions (session_id_hash, admin_user_id, expires_at, last_seen_at, user_agent)
        VALUES (?, ?, datetime('now', ?), datetime('now'), ?)
        """,
        (_hash_token(token), admin_user_id, f"+{get_settings().manager_session_hours} hours", user_agent),
    )
    db.execute(
        "UPDATE admin_users SET last_login_at = datetime('now') WHERE admin_user_id = ?",
        (admin_user_id,),
    )
    return token


def _serialize_admin_user(admin) -> dict[str, Any]:
    return {
        "adminUserId": admin["admin_user_id"],
        "username": admin["username"],
        "displayName": admin["display_name"],
        "role": admin["role"],
        "status": admin["status"],
        "createdAt": admin["created_at"],
        "lastLoginAt": admin["last_login_at"],
    }


def _record_admin_audit(db, admin_user_id: str, action: str, detail: str | None = None) -> None:
    db.execute(
        """
        INSERT INTO admin_audit_log (admin_user_id, action, detail)
        VALUES (?, ?, ?)
        """,
        (admin_user_id, action, detail),
    )


def _hash_token(token: str) -> str:
    return hashlib.sha256(token.encode()).hexdigest()


def _generate_recovery_code() -> str:
    # 128 bits of entropy via two 8-byte hex segments, always uppercase
    left = secrets.token_hex(8).upper()
    right = secrets.token_hex(8).upper()
    return f"HC-{left}-{right}"
