"""v3.6 Runtime Harness — Layer 0: Task MD SHA Normalize.

chair_authorization_id=CHAIR-AUTH-TASK-2705PLUS1-V36-TASK-MD-SHA-BOOTSTRAP-260528

Pure functions for normalizing task markdown bytes prior to sha comparison.
Mirrors dispatch.py L4518 `.read_text(utf-8).strip()` plus allowed sidecar /
retry-header strip per design spec v36_task_md_sha_contract_design_draft_260528.md.

Safe-fail: every public function catches all exceptions and returns a conservative
result (UNKNOWN / unverifiable) — never raises to the caller.
"""
from __future__ import annotations

import hashlib
import re
from typing import Optional, Tuple

PATCH_TYPE_NO_PATCH = "NO_PATCH"
PATCH_TYPE_DISPATCH_META_SIDECAR = "DISPATCH_META_SIDECAR"
PATCH_TYPE_RETRY_HEADER_PREPEND = "RETRY_HEADER_PREPEND"
PATCH_TYPE_WHITESPACE_NORMALIZATION = "WHITESPACE_NORMALIZATION"
PATCH_TYPE_FORBIDDEN_SEMANTIC_CHANGE = "FORBIDDEN_SEMANTIC_CHANGE"
PATCH_TYPE_UNKNOWN = "UNKNOWN"

VERBATIM_TRUE = "true"
VERBATIM_FALSE = "false"
VERBATIM_UNVERIFIABLE = "unverifiable"

_DISPATCH_META_RE = re.compile(
    rb"^<!--\s*DISPATCH_META[^>]*-->\s*\n?", re.IGNORECASE
)
_RETRY_HEADER_RE = re.compile(
    rb"^<!--\s*RETRY_HEADER[^>]*-->\s*\n?", re.IGNORECASE
)


def compute_sha256(content: Optional[bytes]) -> Optional[str]:
    """Return hex sha256 of ``content`` (None if content is None)."""
    if content is None:
        return None
    try:
        return hashlib.sha256(content).hexdigest()
    except Exception:
        return None


def normalize_whitespace(content: Optional[bytes]) -> Optional[bytes]:
    """Simulate dispatch.py L4518 ``read_text("utf-8").strip()`` then re-encode."""
    if content is None:
        return None
    try:
        text = content.decode("utf-8", errors="strict")
        return text.strip().encode("utf-8")
    except Exception:
        try:
            return content.strip()
        except Exception:
            return None


def _strip_dispatch_meta_sidecar(content: bytes) -> Tuple[bytes, bool]:
    """Strip a leading ``<!-- DISPATCH_META ... -->`` block. Returns (stripped, found)."""
    if not content:
        return content, False
    match = _DISPATCH_META_RE.match(content)
    if match:
        return content[match.end():], True
    return content, False


def _strip_retry_header(content: bytes) -> Tuple[bytes, bool]:
    """Strip a leading ``<!-- RETRY_HEADER ... -->`` block. Returns (stripped, found)."""
    if not content:
        return content, False
    match = _RETRY_HEADER_RE.match(content)
    if match:
        return content[match.end():], True
    return content, False


def detect_patch_type(
    pre_content: Optional[bytes], post_content: Optional[bytes]
) -> str:
    """Classify the difference between ``pre_content`` and ``post_content``."""
    try:
        if pre_content is None or post_content is None:
            return PATCH_TYPE_UNKNOWN

        if pre_content == post_content:
            return PATCH_TYPE_NO_PATCH

        pre_norm = normalize_whitespace(pre_content)
        post_norm = normalize_whitespace(post_content)
        if pre_norm is not None and pre_norm == post_norm:
            return PATCH_TYPE_WHITESPACE_NORMALIZATION

        pre_no_meta, pre_meta_found = _strip_dispatch_meta_sidecar(pre_content)
        post_no_meta, post_meta_found = _strip_dispatch_meta_sidecar(post_content)
        if pre_meta_found != post_meta_found:
            if normalize_whitespace(pre_no_meta) == normalize_whitespace(post_no_meta):
                return PATCH_TYPE_DISPATCH_META_SIDECAR

        pre_no_retry, pre_retry_found = _strip_retry_header(pre_content)
        post_no_retry, post_retry_found = _strip_retry_header(post_content)
        if pre_retry_found != post_retry_found:
            if normalize_whitespace(pre_no_retry) == normalize_whitespace(post_no_retry):
                return PATCH_TYPE_RETRY_HEADER_PREPEND

        return PATCH_TYPE_FORBIDDEN_SEMANTIC_CHANGE
    except Exception:
        return PATCH_TYPE_UNKNOWN


def content_verbatim_match(
    pre_content: Optional[bytes], post_content: Optional[bytes]
) -> str:
    """Return ``"true" | "false" | "unverifiable"`` after sidecar/retry strip + ws normalize."""
    try:
        if pre_content is None or post_content is None:
            return VERBATIM_UNVERIFIABLE

        if pre_content == post_content:
            return VERBATIM_TRUE

        pre_no_meta, _ = _strip_dispatch_meta_sidecar(pre_content)
        post_no_meta, _ = _strip_dispatch_meta_sidecar(post_content)
        pre_no_meta, _ = _strip_retry_header(pre_no_meta)
        post_no_meta, _ = _strip_retry_header(post_no_meta)

        pre_norm = normalize_whitespace(pre_no_meta)
        post_norm = normalize_whitespace(post_no_meta)
        if pre_norm is None or post_norm is None:
            return VERBATIM_UNVERIFIABLE

        return VERBATIM_TRUE if pre_norm == post_norm else VERBATIM_FALSE
    except Exception:
        return VERBATIM_UNVERIFIABLE
