"""APDU sequence for provisioning an Access Document via PersonalizationApplet.

The applet's PersonalizationApplet (DT-proprietary AID) accepts the AD via
two INSes:
    INS 0x23 WRITE_ACCESS_DOC    — P1|P2 = destination offset, data = chunk
    INS 0x24 FINALIZE_ACCESS_DOC — P1|P2 = total length, Lc = 0

The AD must fit within CredentialStore.ACCESS_DOC_MAX_LEN (1024 bytes).
"""

CLA_PROPRIETARY = 0x80
INS_WRITE_ACCESS_DOC = 0x23
INS_FINALIZE_ACCESS_DOC = 0x24

# Max command data field in a short-form APDU (ISO 7816-4).
APDU_CHUNK_MAX = 255

# Must match CredentialStore.ACCESS_DOC_MAX_LEN on the applet side.
ACCESS_DOC_MAX_LEN = 1024


def access_document_apdus(ad_bytes: bytes, chunk_size: int = APDU_CHUNK_MAX) -> list[bytes]:
    """Returns the ordered list of APDU commands that load ``ad_bytes`` onto
    a provisioning-channel-selected applet.

    The caller should have already SELECTed the PersonalizationApplet AID
    and not yet called COMMIT.
    """
    if len(ad_bytes) > ACCESS_DOC_MAX_LEN:
        raise ValueError(
            f"Access Document is {len(ad_bytes)} bytes; exceeds {ACCESS_DOC_MAX_LEN}-byte applet budget"
        )
    if not (1 <= chunk_size <= APDU_CHUNK_MAX):
        raise ValueError(f"chunk_size must be in [1, {APDU_CHUNK_MAX}]")

    apdus: list[bytes] = []
    for offset in range(0, len(ad_bytes), chunk_size):
        chunk = ad_bytes[offset : offset + chunk_size]
        apdus.append(_apdu(INS_WRITE_ACCESS_DOC, offset >> 8, offset & 0xFF, chunk))

    total = len(ad_bytes)
    apdus.append(_apdu(INS_FINALIZE_ACCESS_DOC, total >> 8, total & 0xFF, b""))
    return apdus


def _apdu(ins: int, p1: int, p2: int, data: bytes) -> bytes:
    # Short-form APDU: CLA INS P1 P2 Lc data
    header = bytes([CLA_PROPRIETARY, ins, p1, p2])
    if data:
        return header + bytes([len(data)]) + data
    return header
