"""v3.6 Runtime Harness — JSONL record schema validator.

chair_authorization_id=CHAIR-AUTH-TASK-2703-V36-HARNESS-MVP-260528

Required fields (5 canonical fields per spec verbatim):
  ts, decision, matched_rule, command_or_tool, task_id, timestamp
  (ts + timestamp both required to fulfill "ts (ISO8601 UTC)" and "timestamp (epoch float)" spec)
"""
from __future__ import annotations

from typing import Any

# Required fields per spec (ts + timestamp count as the dual-field requirement)
REQUIRED_FIELDS = {"ts", "decision", "matched_rule", "command_or_tool", "task_id", "timestamp"}

VALID_DECISIONS = {"ALLOW", "DENY", "HOLD_FOR_CHAIR", "AUDIT_ONLY", "DRY_RUN_WOULD_DENY"}


def validate_record(record: Any) -> tuple[bool, list[str]]:
    """Validate a JSONL decision record against the v36 harness schema.

    Returns:
        (valid: bool, errors: list[str])
    """
    errors: list[str] = []

    if not isinstance(record, dict):
        return False, ["record must be a dict"]

    # Check required fields presence
    for field in REQUIRED_FIELDS:
        if field not in record:
            errors.append(f"missing required field: {field!r}")

    # Validate decision value
    decision = record.get("decision")
    if decision is not None and decision not in VALID_DECISIONS:
        errors.append(f"invalid decision value: {decision!r}; expected one of {sorted(VALID_DECISIONS)}")

    # Validate ts is a non-empty string
    ts = record.get("ts")
    if ts is not None and not isinstance(ts, str):
        errors.append(f"field 'ts' must be a string (ISO8601), got {type(ts).__name__}")
    if isinstance(ts, str) and not ts.strip():
        errors.append("field 'ts' must not be empty")

    # Validate timestamp is a number
    timestamp = record.get("timestamp")
    if timestamp is not None and not isinstance(timestamp, (int, float)):
        errors.append(f"field 'timestamp' must be numeric (epoch float), got {type(timestamp).__name__}")

    # For DENY / HOLD_FOR_CHAIR: matched_rule and reason should be non-null
    if decision in ("DENY", "HOLD_FOR_CHAIR"):
        if record.get("matched_rule") is None:
            errors.append(f"field 'matched_rule' must not be None for decision={decision!r}")
        if record.get("reason") is None:
            errors.append(f"field 'reason' must not be None for decision={decision!r}")

    valid = len(errors) == 0
    return valid, errors
