"""Lecture des roles RBAC qui referencent un DocType donne (source unique · #6).

Le contrat `rbac_50_roles.json` est l'UNIQUE source de verite des roles ERPNext
(valide par `rbac.schema.json` dans le job CI `rbac-tests`). Ici on ne fait que
le LIRE : pour le DocType `CONFOTUR Application`, quels roles y ont acces et avec
quelles actions. Ces `permissions_cibles` deviennent, mot pour mot, les DocPerm
du DocType genere -> les permissions du fixture SONT le contrat RBAC, pas une
reinvention.

Reutilisation (workflow #5, zero duplication) : la resolution `id -> nom Frappe`
et le `portail` restent delegues au `RoleResolver` du module CRM voisin — on ne
redefinit ni le format des roles ni leur nommage.
"""

from __future__ import annotations

import json
import os
from typing import Any

_HERE = os.path.dirname(os.path.abspath(__file__))
_DELIVERABLES = os.path.normpath(os.path.join(_HERE, "..", "..", ".."))
RBAC_CONTRACT_PATH = os.path.join(_DELIVERABLES, "rbac", "rbac_50_roles.json")


def load_contract(path: str = RBAC_CONTRACT_PATH) -> dict[str, Any]:
    with open(path, encoding="utf-8") as fh:
        return json.load(fh)


def roles_targeting(doctype: str, contract: dict[str, Any]) -> list[dict[str, Any]]:
    """Roles dont un `permissions_cibles` vise `doctype`.

    Retour trie par `id` de role (determinisme). Chaque element :
      {role_id, actions: [..], custom: bool}
    `actions` reprend, sans ajout ni retrait, la liste declaree dans le contrat.
    Leve si un meme role declare deux fois le meme doctype (contrat ambigu).
    """
    out: list[dict[str, Any]] = []
    for role in contract.get("roles", []):
        matches = [pc for pc in role.get("permissions_cibles", [])
                   if pc.get("doctype") == doctype]
        if not matches:
            continue
        if len(matches) > 1:
            raise ValueError(
                f"Role {role.get('id')!r} declare {doctype!r} plusieurs fois "
                f"dans permissions_cibles (contrat ambigu)."
            )
        pc = matches[0]
        out.append({
            "role_id": role["id"],
            "actions": list(pc.get("actions", [])),
            "custom": bool(pc.get("custom", False)),
        })
    out.sort(key=lambda r: r["role_id"])
    return out
