"""Generate public-safe wet-clean and surface-prep teaching datasets.

The generated files are conceptual, precomputed replays for SemiAgora pages.
They intentionally avoid chemical concentrations, process times, tool settings,
facility instructions, and qualified process-window claims.
"""

from __future__ import annotations

import json
from pathlib import Path


ROOT = Path(__file__).resolve().parent


SOURCES = [
    {
        "label": "Stanford SNF Pre-Diffusion Clean",
        "url": "https://snfguide.stanford.edu/taxonomy/term/712/all/feed?order=field_equipment_name&sort=desc",
        "note": "Public SNF guide page describing SC1, SC2, and optional HF dip roles for organics, particles, metals, and native oxide context.",
    },
    {
        "label": "Stanford SNF Standard Clean 1",
        "url": "https://snfguide.stanford.edu/guide/chemicals/acids/standard-clean-1",
        "note": "Public SNF chemical page anchoring SC1 as a particle and surface-preparation clean before growth furnaces.",
    },
    {
        "label": "Stanford SNF HMDS",
        "url": "https://snfguide.stanford.edu/guide/chemicals/primers/hmds",
        "note": "Public SNF guide page describing HMDS as a photoresist adhesion promoter.",
    },
    {
        "label": "NIST wet chemical cleaning publication",
        "url": "https://www.nist.gov/publications/wet-chemical-cleaning-plasma-oxide-grown-heated-001-inp-surfaces",
        "note": "Public NIST publication page anchoring wet cleaning as surface preparation before epitaxy, metal/dielectric deposition, and diffusion.",
    },
]


LIMITS = [
    "No recipe, concentration, bath timing, tool sequence, facility procedure, or endpoint-control instruction is included.",
    "No wafer-release, contamination-control, metrology qualification, safety approval, or qualified process-window claim is made.",
    "All curves are educational teaching proxies and must be replaced by facility-approved measurements before process decisions.",
    "Material compatibility, pattern sensitivity, queue time, and safety review must be handled by qualified local procedures.",
]


def write_json(filename: str, payload: dict) -> None:
    (ROOT / filename).write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")


def monotonic_decrease(values: list[float]) -> bool:
    return all(values[i] >= values[i + 1] for i in range(len(values) - 1))


def monotonic_increase(values: list[float]) -> bool:
    return all(values[i] <= values[i + 1] for i in range(len(values) - 1))


def common_payload(experiment_id: str, title: str, model_boundary: str) -> dict:
    return {
        "schema": "semiagora.process-simulation.v1",
        "experiment_id": experiment_id,
        "title": title,
        "execution_mode": "precomputed-only",
        "model_boundary": model_boundary,
        "limitations": LIMITS,
        "sources": SOURCES,
    }


def wet_removal() -> None:
    cases = [
        {
            "label": "incoming_surface",
            "organic_residue_percent": 100.0,
            "particle_index": 100.0,
            "metal_contamination_index": 100.0,
            "native_oxide_proxy_nm": 1.2,
            "review_note": "Incoming state before any public-safe conceptual clean.",
        },
        {
            "label": "solvent_degrease_proxy",
            "organic_residue_percent": 42.0,
            "particle_index": 88.0,
            "metal_contamination_index": 96.0,
            "native_oxide_proxy_nm": 1.2,
            "review_note": "Organic residue falls, but particle and metal evidence is still needed.",
        },
        {
            "label": "sc1_particle_clean_proxy",
            "organic_residue_percent": 18.0,
            "particle_index": 28.0,
            "metal_contamination_index": 74.0,
            "native_oxide_proxy_nm": 1.8,
            "review_note": "Particle proxy improves while oxide state remains part of the evidence.",
        },
        {
            "label": "sc2_metal_clean_proxy",
            "organic_residue_percent": 14.0,
            "particle_index": 24.0,
            "metal_contamination_index": 22.0,
            "native_oxide_proxy_nm": 1.9,
            "review_note": "Metal contamination proxy improves, but this does not remove native oxide.",
        },
        {
            "label": "rinse_dry_control_proxy",
            "organic_residue_percent": 12.0,
            "particle_index": 20.0,
            "metal_contamination_index": 20.0,
            "native_oxide_proxy_nm": 1.9,
            "review_note": "Final public-safe state still needs watermark, particle, metal, and oxide checks.",
        },
    ]
    organics = [case["organic_residue_percent"] for case in cases]
    particles = [case["particle_index"] for case in cases]
    metals = [case["metal_contamination_index"] for case in cases]
    payload = common_payload(
        "SA-PROC-CLEAN-WET-REMOVAL-001",
        "Wet clean contamination removal",
        "Educational wet-clean replay using normalized contamination proxies; not a wet-bench recipe or measured wafer result.",
    )
    payload.update(
        {
            "axes": ["conceptual clean stage"],
            "cases": cases,
            "derived_metrics": {
                "organic_residue_reduction_percent": round(100 - cases[-1]["organic_residue_percent"], 2),
                "particle_index_reduction_percent": round(100 - cases[-1]["particle_index"], 2),
                "metal_index_reduction_percent": round(100 - cases[-1]["metal_contamination_index"], 2),
                "native_oxide_final_proxy_nm": cases[-1]["native_oxide_proxy_nm"],
            },
            "verification": {
                "case_count": len(cases),
                "organic_decreases": monotonic_decrease(organics),
                "particle_decreases": monotonic_decrease(particles),
                "metal_decreases": monotonic_decrease(metals),
                "native_oxide_not_removed_by_sequence": cases[-1]["native_oxide_proxy_nm"] >= cases[0]["native_oxide_proxy_nm"],
                "all_cases_precomputed": True,
            },
        }
    )
    write_json("process-wet-clean-contamination-removal-web-v1.json", payload)


def native_oxide_window() -> None:
    exposure = [0, 1, 2, 3, 4, 5]
    oxide_nm = [1.8, 1.15, 0.58, 0.22, 0.08, 0.03]
    contact_angle = [18, 42, 65, 78, 84, 87]
    reoxidation = [0.05, 0.18, 0.34, 0.52, 0.68, 0.78]
    queue = [0.08, 0.15, 0.29, 0.46, 0.64, 0.76]
    samples = [
        {
            "normalized_exposure_index": index,
            "native_oxide_remaining_nm": oxide,
            "contact_angle_proxy_deg": angle,
            "reoxidation_sensitivity": risk,
            "queue_time_risk": queue_risk,
        }
        for index, oxide, angle, risk, queue_risk in zip(exposure, oxide_nm, contact_angle, reoxidation, queue)
    ]
    payload = common_payload(
        "SA-PROC-CLEAN-DHF-NATIVE-OXIDE-001",
        "Dilute HF native-oxide window",
        "Educational native-oxide window replay using normalized exposure; not a chemical process setting, qualified HF procedure, or measured wafer result.",
    )
    payload.update(
        {
            "axes": ["normalized exposure index"],
            "samples": samples,
            "derived_metrics": {
                "oxide_after_index_3_nm": oxide_nm[3],
                "hydrophobic_contact_angle_index_4_deg": contact_angle[4],
                "reoxidation_sensitivity_index_5": reoxidation[5],
            },
            "verification": {
                "sample_count": len(samples),
                "oxide_decreases": monotonic_decrease(oxide_nm),
                "hydrophobicity_increases": monotonic_increase(contact_angle),
                "reoxidation_risk_increases": monotonic_increase(reoxidation),
                "queue_risk_increases": monotonic_increase(queue),
            },
        }
    )
    write_json("process-dilute-hf-native-oxide-window-web-v1.json", payload)


def hmds_prime() -> None:
    cases = [
        {
            "label": "humid_no_prime",
            "moisture_index": 1.0,
            "contact_angle_proxy_deg": 32,
            "adhesion_score": 0.32,
            "defect_risk": 0.42,
        },
        {
            "label": "dehydrate_only",
            "moisture_index": 0.35,
            "contact_angle_proxy_deg": 52,
            "adhesion_score": 0.58,
            "defect_risk": 0.25,
        },
        {
            "label": "balanced_hmds_prime",
            "moisture_index": 0.12,
            "contact_angle_proxy_deg": 76,
            "adhesion_score": 0.91,
            "defect_risk": 0.08,
        },
        {
            "label": "overprime_or_delay_risk",
            "moisture_index": 0.18,
            "contact_angle_proxy_deg": 88,
            "adhesion_score": 0.74,
            "defect_risk": 0.26,
        },
    ]
    payload = common_payload(
        "SA-PROC-CLEAN-HMDS-ADHESION-001",
        "HMDS adhesion-prime readiness",
        "Educational HMDS adhesion readiness replay using normalized surface-state proxies; not a lithography track recipe or measured wafer result.",
    )
    payload.update(
        {
            "axes": ["surface-state case"],
            "cases": cases,
            "derived_metrics": {
                "best_adhesion_case": "balanced_hmds_prime",
                "balanced_adhesion_score": 0.91,
                "overprime_risk_delta": round(cases[-1]["defect_risk"] - cases[2]["defect_risk"], 2),
            },
            "verification": {
                "case_count": len(cases),
                "best_adhesion_case_is_balanced": max(cases, key=lambda x: x["adhesion_score"])["label"] == "balanced_hmds_prime",
                "moisture_lower_after_dehydrate": cases[1]["moisture_index"] < cases[0]["moisture_index"],
                "hydrophobicity_increases_with_prime": cases[2]["contact_angle_proxy_deg"] > cases[1]["contact_angle_proxy_deg"],
                "risk_increases_for_overprime": cases[-1]["defect_risk"] > cases[2]["defect_risk"],
            },
        }
    )
    write_json("process-hmds-adhesion-prime-web-v1.json", payload)


def clean_sequence_queue() -> None:
    cases = [
        {
            "downstream_intent": "oxidation_or_diffusion_preclean",
            "surface_target": "hydrophilic controlled oxide",
            "evidence_need": ["particle trend", "metal contamination proxy", "native oxide state", "furnace compatibility review"],
            "risk_flags": ["metal carryover", "particle redeposition", "facility qualification gap"],
            "sequence_fit_score": 0.82,
        },
        {
            "downstream_intent": "deposition_preclean",
            "surface_target": "low residue and known oxide condition",
            "evidence_need": ["organic residue proxy", "particle trend", "watermark check", "film nucleation note"],
            "risk_flags": ["residue-driven nucleation shift", "queue-time drift", "material compatibility gap"],
            "sequence_fit_score": 0.78,
        },
        {
            "downstream_intent": "lithography_hmds",
            "surface_target": "dry hydrophobic adhesion-ready surface",
            "evidence_need": ["dehydration state", "contact-angle proxy", "adhesion score", "delay-to-coat note"],
            "risk_flags": ["moisture return", "overprime risk", "resist compatibility gap"],
            "sequence_fit_score": 0.88,
        },
        {
            "downstream_intent": "contact_or_surface_sensitive",
            "surface_target": "controlled native oxide or hydrogen-terminated state",
            "evidence_need": ["native oxide proxy", "contact resistance proxy", "queue-time risk", "metrology boundary"],
            "risk_flags": ["reoxidation", "surface damage", "unqualified contact claim"],
            "sequence_fit_score": 0.73,
        },
    ]
    payload = common_payload(
        "SA-PROC-CLEAN-SEQUENCE-QUEUE-001",
        "Clean sequence decision queue",
        "Educational clean-sequence queue map for evidence planning; not a wet-bench flow, tool route, or facility-approved traveler.",
    )
    payload.update(
        {
            "axes": ["downstream intent"],
            "cases": cases,
            "derived_metrics": {
                "case_count": len(cases),
                "total_evidence_needs": sum(len(case["evidence_need"]) for case in cases),
                "average_sequence_fit_score": round(sum(case["sequence_fit_score"] for case in cases) / len(cases), 3),
            },
            "verification": {
                "case_count": len(cases),
                "all_cases_have_evidence_need": all(len(case["evidence_need"]) >= 4 for case in cases),
                "all_cases_have_risk_flags": all(len(case["risk_flags"]) >= 3 for case in cases),
                "scores_are_public_planning_proxies": True,
            },
        }
    )
    write_json("process-clean-sequence-queue-web-v1.json", payload)


def main() -> None:
    wet_removal()
    native_oxide_window()
    hmds_prime()
    clean_sequence_queue()


if __name__ == "__main__":
    main()
