from datetime import date
MISSING={None,"","MISSING","UNKNOWN","N/A"}
VALID_COMPAT={"TESTED_SUPPORTED","UNTESTED","KNOWN_INCOMPATIBLE"}
VALID_SUPPORT={"FULL","SECURITY_ONLY","LIMITED","EOL"}
VALID_EOL={"ACTIVE","NEAR_EOL","EOL"}
VALID_DECISIONS={"SUPPORTED_UPGRADE_WITH_INTERMEDIATE_HOP","SUPPORTED_DIRECT_UPGRADE","CURRENT_RELEASE_SUPPORTED","PATCH_CANDIDATE","UNSUPPORTED"}

def missing(v): return v in MISSING

def parse_date(v):
    try: return date.fromisoformat(v)
    except Exception: return None

def semver(v):
    try:
        a=v.split('-')[0].split('+')[0].split('.')
        return len(a)==3 and all(x.isdigit() for x in a)
    except Exception: return False

def evaluate(x):
    # Required identity / support fields
    required=["release_id","product_version","target_release_id","target_product_version","release_channel","release_date","public_api_version","dependency_version","runtime_version","database_version","schema_version","os_or_container_ref","compatibility_range","compatibility_state","compatibility_evidence_ref","tested_matrix_id","deployment_fingerprint","upgrade_from_version","upgrade_to_version","upgrade_hop_state","migration_ref","backup_evidence_ref","rollback_ref","support_tier","security_fix_policy_ref","support_start","support_end","eol_state","known_incompatibility_ref","operator_ack_state","decision_state","audit_ref","review_due"]
    for f in required:
        if missing(x.get(f)): return "HOLD_REQUIRED_EVIDENCE_MISSING:"+f
    if not semver(x.get("product_version")) or not semver(x.get("target_product_version")): return "HOLD_VERSION_FORMAT_INVALID"
    if not isinstance(x.get("tested_runtime_versions"),list) or not x["tested_runtime_versions"]: return "HOLD_TESTED_RUNTIME_SET_MISSING"
    if not isinstance(x.get("tested_database_versions"),list) or not x["tested_database_versions"]: return "HOLD_TESTED_DATABASE_SET_MISSING"
    if not isinstance(x.get("supported_upgrade_from_versions"),list): return "HOLD_UPGRADE_SOURCE_SET_INVALID"
    if x.get("compatibility_state") not in VALID_COMPAT: return "HOLD_COMPATIBILITY_STATE_INVALID"
    if x.get("support_tier") not in VALID_SUPPORT: return "HOLD_SUPPORT_TIER_INVALID"
    if x.get("eol_state") not in VALID_EOL: return "HOLD_EOL_STATE_INVALID"
    if x.get("decision_state") not in VALID_DECISIONS: return "HOLD_DECISION_STATE_INVALID"
    if x.get("runtime_version") not in x["tested_runtime_versions"]: return "HOLD_RUNTIME_VERSION_UNTESTED"
    if x.get("database_version") not in x["tested_database_versions"]: 
        return "HOLD_PATCH_ON_UNTESTED_DATABASE" if x.get("decision_kind")=="PATCH_ONLY" else "HOLD_DATABASE_VERSION_UNTESTED"
    if x.get("compatibility_state")!="TESTED_SUPPORTED": return "HOLD_COMPATIBILITY_NOT_PROVEN"
    # Date/support consistency
    sd=parse_date(x.get("support_start")); ed=parse_date(x.get("support_end")); dd=parse_date(x.get("decision_date","2026-09-14"))
    if not sd or not ed or not dd or sd>ed: return "HOLD_SUPPORT_WINDOW_INVALID"
    if dd>ed and x.get("support_tier")!="EOL": return "HOLD_SUPPORT_WINDOW_EXPIRED"
    if x.get("eol_state")=="EOL" and x.get("patch_eligible") is True: return "HOLD_EOL_PATCH_CONFLICT"
    if x.get("support_tier")=="EOL" and x.get("eol_state")!="EOL": return "HOLD_SUPPORT_EOL_STATE_MISMATCH"
    if x.get("operator_ack_state")!="ACKNOWLEDGED": return "HOLD_OPERATOR_ACK_MISSING"
    # Evidence assertions
    if x.get("rollback_supported") is True and x.get("rollback_ref") in MISSING|{"NONE","NOT_IMPLEMENTED"}: return "HOLD_ROLLBACK_EVIDENCE_MISSING"
    if x.get("backup_required") is True and x.get("backup_evidence_ref") in MISSING|{"NONE","NOT_REQUIRED"}: return "HOLD_BACKUP_EVIDENCE_MISSING"
    if x.get("migration_required") is True and x.get("migration_ref") in MISSING|{"NONE","NOT_REQUIRED"}: return "HOLD_MIGRATION_EVIDENCE_MISSING"
    # Upgrade path semantics
    kind=x.get("decision_kind")
    if kind=="UPGRADE":
        if x.get("upgrade_from_version")!=x.get("product_version") or x.get("upgrade_to_version")!=x.get("target_product_version"): return "HOLD_UPGRADE_IDENTITY_MISMATCH"
        direct_ok=x.get("upgrade_from_version") in x.get("supported_upgrade_from_versions",[])
        hop=x.get("upgrade_hop_state")
        if x.get("direct_upgrade_attempted") is True and not direct_ok: return "HOLD_DIRECT_UPGRADE_UNSUPPORTED"
        if not direct_ok:
            if hop!="INTERMEDIATE_REQUIRED_AND_DECLARED": return "HOLD_REQUIRED_INTERMEDIATE_HOP_MISSING"
            if missing(x.get("intermediate_hop_version")) or x.get("intermediate_hop_version") not in x.get("supported_upgrade_from_versions",[]): return "HOLD_INTERMEDIATE_HOP_INVALID"
        if x.get("migration_required") is not True: return "HOLD_REQUIRED_MIGRATION_NOT_DECLARED"
        if x.get("backup_required") is not True: return "HOLD_REQUIRED_BACKUP_NOT_DECLARED"
        if x.get("decision_state") not in {"SUPPORTED_UPGRADE_WITH_INTERMEDIATE_HOP","SUPPORTED_DIRECT_UPGRADE"}: return "HOLD_UPGRADE_DECISION_STATE_MISMATCH"
    elif kind=="PATCH_ONLY":
        if x.get("baseline_decision_reused") is True: return "HOLD_TRANSFER_BASELINE_ORACLE_REUSE"
        if x.get("transfer_variant") not in {None,"BASELINE","NONE"} and x.get("transfer_recomputed") is not True: return "HOLD_TRANSFER_NOT_RECOMPUTED"
        if x.get("support_tier") not in {"FULL","SECURITY_ONLY"}: return "HOLD_PATCH_TIER_NOT_ELIGIBLE"
        if x.get("patch_eligible") is not True: return "HOLD_PATCH_NOT_ELIGIBLE"
        if x.get("decision_state")!="PATCH_CANDIDATE": return "HOLD_PATCH_DECISION_STATE_MISMATCH"
    elif kind=="STAY":
        if x.get("decision_state")!="CURRENT_RELEASE_SUPPORTED": return "HOLD_STAY_DECISION_STATE_MISMATCH"
    else: return "HOLD_DECISION_KIND_INVALID"
    # Explicit incompatibility evidence cannot coexist with positive result.
    if str(x.get("known_incompatibility_ref")).startswith("BLOCKING_"): return "HOLD_KNOWN_INCOMPATIBILITY"
    if kind=="PATCH_ONLY": return "PATCH_REVIEW_READY"
    if kind=="STAY": return "CURRENT_RELEASE_SUPPORT_REVIEW_READY"
    return "UPGRADE_PATH_REVIEW_READY"
