"""Security module for verified file write operations.

This module ensures that file writes only occur when explicitly allowed by configuration,
maintaining the encryption-at-rest security model.
"""

import json
from pathlib import Path
from typing import Any

from loguru import logger


class FileWriteSecurityError(Exception):
    """Raised when a file write operation is not allowed by security settings."""

    pass


def write_file_verified(
    filepath: str | Path,
    content: str,
    setting_name: str,
    required_value: Any = True,
    context: str = "",
    mode: str = "w",
    encoding: str = "utf-8",
    settings_snapshot: dict = None,
) -> None:
    """Write content to a file only if security settings allow it.

    Args:
        filepath: Path to the file to write
        content: Content to write to the file
        setting_name: Configuration setting name to check (e.g., "api.allow_file_output")
        required_value: Required value for the setting (default: True)
        context: Description of what's being written (for error messages)
        mode: File open mode (default: "w")
        encoding: File encoding (default: "utf-8")
        settings_snapshot: Optional settings snapshot for programmatic mode

    Raises:
        FileWriteSecurityError: If the security setting doesn't match required value

    Example:
        >>> write_file_verified(
        ...     "report.md",
        ...     markdown_content,
        ...     "api.allow_file_output",
        ...     context="API research report"
        ... )
    """
    from ..config.search_config import get_setting_from_snapshot

    try:
        actual_value = get_setting_from_snapshot(
            setting_name, settings_snapshot=settings_snapshot
        )
    except Exception:
        # Setting doesn't exist - default deny
        actual_value = None

    if actual_value != required_value:
        error_msg = (
            f"File write not allowed: {context or 'file operation'}. "
            f"Set '{setting_name}={required_value}' in config to enable this feature."
        )
        logger.warning(error_msg)
        raise FileWriteSecurityError(error_msg)

    with open(filepath, mode, encoding=encoding) as f:
        f.write(content)

    logger.debug(
        f"Verified file write: {filepath} (setting: {setting_name}={required_value})"
    )


def write_json_verified(
    filepath: str | Path,
    data: dict | list,
    setting_name: str,
    required_value: Any = True,
    context: str = "",
    settings_snapshot: dict = None,
    **json_kwargs,
) -> None:
    """Write JSON data to a file only if security settings allow it.

    Args:
        filepath: Path to the file to write
        data: Dictionary or list to serialize as JSON
        setting_name: Configuration setting name to check
        required_value: Required value for the setting (default: True)
        context: Description of what's being written (for error messages)
        settings_snapshot: Optional settings snapshot for programmatic mode
        **json_kwargs: Additional keyword arguments to pass to json.dumps()
                      (e.g., indent=2, ensure_ascii=False, sort_keys=True, default=custom_serializer)

    Raises:
        FileWriteSecurityError: If the security setting doesn't match required value

    Example:
        >>> write_json_verified(
        ...     "results.json",
        ...     {"accuracy": 0.95},
        ...     "benchmark.allow_file_output",
        ...     context="benchmark results",
        ...     indent=2,
        ...     sort_keys=True
        ... )
    """
    # Default to indent=2 if not specified for readability
    if "indent" not in json_kwargs:
        json_kwargs["indent"] = 2

    content = json.dumps(data, **json_kwargs)
    write_file_verified(
        filepath,
        content,
        setting_name,
        required_value,
        context,
        mode="w",
        encoding="utf-8",
        settings_snapshot=settings_snapshot,
    )
