"""Filesystem boundary for SQLite state containing private operator data."""

from __future__ import annotations

import os
import sqlite3
import stat
from pathlib import Path
from typing import Any


PRIVATE_DIRECTORY_MODE = stat.S_IRWXU
PRIVATE_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR


def _reject_symlink(path: Path, *, label: str) -> None:
    try:
        metadata = path.lstat()
    except FileNotFoundError:
        return
    if stat.S_ISLNK(metadata.st_mode):
        raise ValueError(f"private SQLite {label} must not be a symlink: {path}")


def prepare_private_sqlite_path(path: str | Path, *, create: bool = True) -> Path:
    """Create or repair a private SQLite path without following a database symlink."""
    database = Path(path)
    parent = database.parent
    _reject_symlink(parent, label="directory")
    if create:
        parent.mkdir(parents=True, mode=PRIVATE_DIRECTORY_MODE, exist_ok=True)
    elif not parent.exists():
        raise FileNotFoundError(database)
    _reject_symlink(parent, label="directory")
    if not parent.is_dir():
        raise ValueError(f"private SQLite parent is not a directory: {parent}")
    os.chmod(parent, PRIVATE_DIRECTORY_MODE, follow_symlinks=False)

    _reject_symlink(database, label="database")
    flags = os.O_RDWR | (os.O_CREAT if create else 0)
    flags |= getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
    descriptor = os.open(database, flags, PRIVATE_FILE_MODE)
    try:
        metadata = os.fstat(descriptor)
        if not stat.S_ISREG(metadata.st_mode):
            raise ValueError(f"private SQLite database is not a regular file: {database}")
        os.fchmod(descriptor, PRIVATE_FILE_MODE)
    finally:
        os.close(descriptor)

    for suffix in ("-wal", "-shm", "-journal"):
        sidecar = Path(str(database) + suffix)
        _reject_symlink(sidecar, label="sidecar")
        try:
            os.chmod(sidecar, PRIVATE_FILE_MODE, follow_symlinks=False)
        except FileNotFoundError:
            pass
    return database


def connect_private_sqlite(
    path: str | Path, *, existing_only: bool = False, **kwargs: Any
) -> sqlite3.Connection:
    """Open SQLite only after enforcing its private directory and file modes."""
    database = prepare_private_sqlite_path(path, create=not existing_only)
    target: str | Path = database
    if existing_only:
        target = f"{database.resolve().as_uri()}?mode=rw"
        kwargs["uri"] = True
    connection = sqlite3.connect(target, **kwargs)
    # SQLite derives new journal/WAL/SHM permissions from the database. Repair
    # sidecars left by older releases as soon as a connection has opened them.
    prepare_private_sqlite_path(database, create=not existing_only)
    return connection
