"""Allocation-safe registered-customer authority acquisition."""

from __future__ import annotations

import os
import stat
from typing import Literal

from .customer_coaching import CustomerRuntime
from .resource_registrar_contract import ResourceRegistrarProtocol
from .weekly_operations import (
    CustomerKey,
    WeeklyOperationsAuthorityCompromise,
    WeeklyOperationsConflict,
    customer_identity_digest,
)
from .weekly_operations_authority import WeeklyOperationsAuthorityRoot
from .weekly_operations_canonical_snapshot import (
    CanonicalBindingMaterial,
    CanonicalDescriptorSet,
    CanonicalFilePin,
    CanonicalPinSet,
    create_binding,
)
from .weekly_operations_customer_authority import CanonicalCheckinCustomerAuthority
from .weekly_operations_customer_authority_factory import (
    CanonicalAuthorityConstruction,
    construct_unregistered_authority_from_owned_descriptors,
)
from .weekly_operations_registered_binding import RegisteredCanonicalCheckinCustomerBinding
from .weekly_operations_customer_authority_identity import (
    CANONICAL_CUSTOMER_SCHEMA_DIGEST,
    CanonicalCustomerNames,
)
from .weekly_operations_customer_authority_parser import OpenedCanonicalCustomerFiles

def _open_child_owned(
    parent: int, name: str, kind: Literal["directory", "file"],
    registrar: ResourceRegistrarProtocol,
) -> int:
    flags = os.O_RDONLY | os.O_NONBLOCK | os.O_NOFOLLOW | os.O_CLOEXEC
    if kind == "directory":
        flags |= os.O_DIRECTORY
    descriptor = registrar.open_fd(lambda: os.open(name, flags, dir_fd=parent))
    info = os.fstat(descriptor)
    safe = stat.S_ISDIR(info.st_mode) if kind == "directory" else stat.S_ISREG(info.st_mode)
    if not safe:
        raise WeeklyOperationsAuthorityCompromise(
            "canonical authority child is nonregular"
        )
    return descriptor


def _open_registered_files_owned(
    names: CanonicalCustomerNames, registrar: ResourceRegistrarProtocol
) -> tuple[CanonicalDescriptorSet, CanonicalPinSet]:
    flags = (
        os.O_RDONLY | os.O_DIRECTORY | os.O_NONBLOCK
        | os.O_NOFOLLOW | os.O_CLOEXEC
    )
    root = registrar.open_fd(lambda: os.open(names.root, flags))
    wizard = _open_child_owned(root, names.wizard, "directory", registrar)
    plans = _open_child_owned(root, names.plans, "directory", registrar)
    events = _open_child_owned(wizard, names.events, "file", registrar)
    sequence = _open_child_owned(plans, names.sequence, "file", registrar)
    lock = _open_child_owned(wizard, names.lock, "file", registrar)
    descriptors = CanonicalDescriptorSet(root, wizard, plans, events, sequence, lock)
    pins = CanonicalPinSet(
        CanonicalFilePin.from_descriptor(root, "directory"),
        CanonicalFilePin.from_descriptor(wizard, "directory"),
        CanonicalFilePin.from_descriptor(plans, "directory"),
        CanonicalFilePin.from_descriptor(events, "file"),
        CanonicalFilePin.from_descriptor(sequence, "file"),
        CanonicalFilePin.from_descriptor(lock, "file", invariant=True),
    )
    return descriptors, pins


def acquire_unregistered_authority_owned(
    runtime: CustomerRuntime,
    registry_authority: WeeklyOperationsAuthorityRoot,
    registrar: ResourceRegistrarProtocol,
    expected: RegisteredCanonicalCheckinCustomerBinding | None = None,
) -> CanonicalCheckinCustomerAuthority:
    """Acquire with all six descriptors registered before this factory returns."""
    names = CanonicalCustomerNames(runtime.data_root.absolute())
    descriptors, pins = _open_registered_files_owned(names, registrar)
    customer = customer_identity_digest(CustomerKey(runtime.spec.customer_key))
    registered = runtime.registered_binding
    observed = create_binding(
        CanonicalBindingMaterial(
            customer, registered.binding_digest, CANONICAL_CUSTOMER_SCHEMA_DIGEST, pins
        )
    )
    if expected is not None and observed != expected.canonical_binding:
        raise WeeklyOperationsConflict(
            "canonical customer authority reacquisition drift"
        )
    construction = CanonicalAuthorityConstruction(
        OpenedCanonicalCustomerFiles(descriptors, pins), expected
    )
    return construct_unregistered_authority_from_owned_descriptors(
        runtime, registry_authority, construction
    )
