#/app/aroflo_connector_app/agent/det_policy.py
from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Dict, Optional


@dataclass(frozen=True)
class DeterministicPolicy:
    """
    Deterministic execution policy for AroFlo connector operations.

    Key rules:
    - Writes are forced to dry_run=True by default (unless explicitly overridden).
    - Reads are allowed as-is.
    - Optional paging limits can be applied at CLI level.
    """
    force_dry_run_for_writes: bool = True
    default_page_size: Optional[int] = 10
    max_page_size: Optional[int] = 50


def apply_policy(
    *,
    op: Any,
    params: Dict[str, Any],
    policy: DeterministicPolicy,
) -> Dict[str, Any]:
    """
    Returns a new params dict with policy enforcement applied.
    We avoid mutating the original input.
    """
    out = dict(params or {})

    side_effect = getattr(op, "side_effect", None)  # "read" | "write" (your ZoneOperation)
    if policy.force_dry_run_for_writes and side_effect == "write":
        # If caller didn't set dry_run, we force it on.
        out.setdefault("dry_run", True)

    # Page size defaults + bounds (if provided by CLI)
    # Note: your join utils expects "pageSize" or "pagesize"; zone code uses coerce_page_size().
    page_size = out.get("pageSize", None)
    if page_size is None:
        page_size = out.get("pagesize", None)

    if page_size is None and policy.default_page_size is not None:
        # Only apply defaults on list-like ops; safe to apply broadly, zone will ignore if unused.
        out.setdefault("pageSize", policy.default_page_size)

    # Enforce max page size if defined and value exists
    v = out.get("pageSize", out.get("pagesize", None))
    if v is not None and policy.max_page_size is not None:
        try:
            iv = int(v)
            if iv > policy.max_page_size:
                out["pageSize"] = policy.max_page_size
        except Exception:
            # If invalid, leave it; zone validation will raise a clear error.
            pass

    return out
