"""Modèle Frappe/ERPNext v15 : DocType natif `Custom Block` (carrier du Chat OTOIA).

Pourquoi un `Custom Block` (et pas un widget externe)
-----------------------------------------------------
La roadmap Sprint 6 demande « Chat OTOIA embedded dans CHAQUE portail ».
Contrainte #1 « ERPNext natif = priorité absolue avant tout outil externe » : dans
ERPNext v15, un bloc de contenu réutilisable inséré dans un `Workspace` EST le
DocType `Custom Block` (`frappe/desk/doctype/custom_block`). Le desk référence un
Custom Block depuis le `content` (editor.js) d'un Workspace via un bloc de type
`custom_block`. On produit donc un `Custom Block` par portail — aucun framework de
chat externe côté worker.

Champs `Custom Block` utilisés (v15) :
  - `block_name` (Data, unique, requis) : identifiant lisible du bloc.
  - `html`       (HTML) : le markup rendu. Ici, UNIQUEMENT un `<div>` de montage
    vide et déterministe (id dérivé de la clé du portail). Le web-component OTOIA
    réel et son JS sont chargés par le thème desk (VPS · agent Frontend · #8) ;
    le worker ne fabrique aucun script ni endpoint.

Anti-invention (#6) : ce module ne connaît AUCUN portail ni rôle en dur, n'émet
aucun chiffre et aucune URL. Le `<div>` de montage porte la clé du portail et la
persona (sourcée CLAUDE.md) — rien d'autre. La config runtime (rôles autorisés,
portée de connaissance, endpoint) vit dans `chat_mount.json`, pas dans le HTML.

Ce module ne touche JAMAIS le VPS : il retourne des dicts sérialisables.
"""

from __future__ import annotations

from typing import Any

CUSTOM_BLOCK_DOCTYPE = "Custom Block"

# Type de bloc editor.js référençant un Custom Block dans le `content` d'un
# Workspace (v15). Fourni au hand-off VPS ; la clé exacte de payload editor.js
# peut varier selon le patch de version → marquée `a_confirmer` dans le manifeste.
WORKSPACE_CONTENT_BLOCK_TYPE = "custom_block"


def mount_html(html_id: str, portail_key: str, persona: str, css_class: str) -> str:
    """`<div>` de montage vide, déterministe (aucun chiffre, aucune URL)."""
    return (
        f'<div class="{css_class}" id="{html_id}" '
        f'data-portail="{portail_key}" data-assistant="{persona}"></div>'
    )


def custom_block_fixture(block_name: str, html: str) -> dict[str, Any]:
    """Fixture `Custom Block` importable (bench). Champs standard posés par Frappe
    à l'import (name/owner/idx) volontairement non fabriqués."""
    return {
        "doctype": CUSTOM_BLOCK_DOCTYPE,
        "block_name": block_name,
        "html": html,
    }
