"""Durable control-file publication and exclusive reservation."""

from __future__ import annotations

import os
from contextlib import suppress
from pathlib import Path

from .faults import NO_FAULTS, FaultInjector
from .fdio import (
    PRIVATE_MODE,
    SEALED_MODE,
    SecureIoError,
    fsync_retry,
    identity,
    open_control_root,
    write_all,
)

_FILE_FLAGS = os.O_CLOEXEC | os.O_NOFOLLOW | os.O_NONBLOCK


def publish_atomic(
    directory: Path,
    name: str,
    payload: bytes,
    *,
    faults: FaultInjector = NO_FAULTS,
    checkpoint: str = "publish",
) -> None:
    """Publish a 0400 control receipt with exact root and full durability."""
    with open_control_root(directory) as directory_fd:
        temporary = f".{name}.{os.getpid()}.tmp"
        faults.hit(f"{checkpoint}:before-open")
        descriptor = os.open(
            temporary,
            os.O_WRONLY | os.O_CREAT | os.O_EXCL | _FILE_FLAGS,
            PRIVATE_MODE,
            dir_fd=directory_fd,
        )
        try:
            faults.hit(f"{checkpoint}:before-write")
            write_all(descriptor, payload)
            faults.hit(f"{checkpoint}:after-write")
            fsync_retry(descriptor)
            faults.hit(f"{checkpoint}:after-file-fsync")
            os.fchmod(descriptor, SEALED_MODE)
        finally:
            os.close(descriptor)
        try:
            os.replace(temporary, name, src_dir_fd=directory_fd, dst_dir_fd=directory_fd)
            faults.hit(f"{checkpoint}:after-rename")
            fsync_retry(directory_fd)
            faults.hit(f"{checkpoint}:after-dir-fsync")
            check = os.open(name, os.O_RDONLY | _FILE_FLAGS, dir_fd=directory_fd)
            try:
                info = os.fstat(check)
                named = os.stat(name, dir_fd=directory_fd, follow_symlinks=False)
                if identity(info) != identity(named) or identity(info)[4:] != (SEALED_MODE, 1):
                    raise SecureIoError("published identity")
                if os.read(check, len(payload) + 1) != payload:
                    raise SecureIoError("published readback")
                faults.hit(f"{checkpoint}:after-readback")
            finally:
                os.close(check)
        finally:
            with suppress(FileNotFoundError):
                os.unlink(temporary, dir_fd=directory_fd)


def reserve_exclusive(
    directory: Path,
    name: str,
    payload: bytes,
    *,
    faults: FaultInjector = NO_FAULTS,
) -> None:
    """Create one immutable reservation exactly once."""
    with open_control_root(directory) as directory_fd:
        try:
            descriptor = os.open(
                name,
                os.O_WRONLY | os.O_CREAT | os.O_EXCL | _FILE_FLAGS,
                SEALED_MODE,
                dir_fd=directory_fd,
            )
        except FileExistsError as error:
            raise SecureIoError("reservation consumed") from error
        try:
            faults.hit("reservation:before-write")
            write_all(descriptor, payload)
            faults.hit("reservation:after-write")
            fsync_retry(descriptor)
            faults.hit("reservation:after-file-fsync")
        finally:
            os.close(descriptor)
        fsync_retry(directory_fd)
        faults.hit("reservation:after-dir-fsync")
