"""Idempotently generate the multilingual speech-content production workspace."""

from __future__ import annotations

import csv
import json
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1] / "content" / "speech"
PLAN = json.loads((ROOT / "plan" / "content-plan.json").read_text(encoding="utf-8"))


def once(path: Path, value: str) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    if not path.exists():
        path.write_text(value.rstrip() + "\n", encoding="utf-8")


def json_once(path: Path, value: dict) -> None:
    once(path, json.dumps(value, ensure_ascii=False, indent=2))


def csv_once(path: Path, header: list[str]) -> None:
    if path.exists():
        return
    path.parent.mkdir(parents=True, exist_ok=True)
    with path.open("w", encoding="utf-8", newline="") as stream:
        csv.writer(stream).writerow(header)


languages = {item["code"]: item for item in PLAN["languages"]}
levels = {item["number"]: item for item in PLAN["levels"]}
capabilities = {item["key"]: item for item in PLAN["capabilities"]}

once(ROOT / "shared" / "instruction.txt", """Purpose: shared production rules used by every capability, node and concept.

Read each standard before production. Keep stable IDs in English snake_case and author child-facing content natively per language. Never store identifiable child media, consent forms or clinical records here.""")

shared = {
    "activity-templates": "Define reusable exposure, matching, identification, discrimination, choice, instruction, imitation, requesting, labelling, video-question, sequence, conversation and generalisation patterns. Specify response mode, prompts, difficulty, feedback, scoring, event payload, accessibility fallback and stop conditions. Speech recognition must not be authoritative.",
    "accessibility": "Require large targets, low-distraction layouts, replay controls, no time pressure by default, switch/keyboard/touch/eye-gaze access, captions, audio description, colour-independent cues, AAC support and reduced-motion alternatives.",
    "media-standards": "Define formats, dimensions, duration, loudness, backgrounds, lighting, framing, naming, rights, checksum and derivative rules. Prefer real varied exemplars. Avoid watermarks, unsafe actions, stereotypes and embedded text.",
    "qa": "Require rights/provenance, technical QA, clinical review and native language/cultural review. Check clarity, distractors, prompts, accessibility, age appropriateness, dialect, privacy and representation.",
    "schemas": "Define contracts for concept, localization, media, node, activity, game, video-list and status records. Keep keys immutable and versioned. Reject unknown references on import.",
}
for folder, text in shared.items():
    once(ROOT / "shared" / folder / "instruction.txt", f"Purpose: {folder.replace('-', ' ').title()}.\n\n{text}")

for lang in PLAN["languages"]:
    base = ROOT / "languages" / lang["code"]
    json_once(base / "language.json", lang | {"status": "planned", "reviewer": "TODO"})
    once(base / "instruction.txt", f"""Language pack: {lang['name']} ({lang['native_name']})

Author from semantic intent, not English wording. Define regional variety, register, natural child-directed forms, grammar progression, morphology, cultural examples, fonts, line breaking, pronunciation and AAC label length. Record translator, native reviewer and SLP reviewer. Preserve contextual alternatives. Never approve machine translation without human review.""")
    once(base / "grammar" / "instruction.txt", "Describe this language's word order, inflection, agreement, pronouns, tense/aspect, plurality, politeness and appropriate combination stages. Link rules to semantic keys; do not force English stages onto this language.")
    once(base / "recording" / "instruction.txt", "Record a native speaker in a quiet space. Capture isolated word, natural phrase and instruction separately. Store variety, consent/release, transcript, take, sample rate, loudness and pronunciation review. No background music.")
    once(base / "review" / "instruction.txt", "Native and clinical reviewers must check meaning, naturalness, dialect, grammar, pronunciation, pacing, cultural fit, rendering and text/audio/video agreement before approval.")

capability_rows = [["order", "capability_key", "name", "status", "owner", "notes"]]
for index, capability in enumerate(PLAN["capabilities"], 1):
    base = ROOT / "capabilities" / capability["key"]
    json_once(base / "capability.json", capability | {"order": index})
    once(base / "instruction.txt", f"""Capability: {capability['name']}

Purpose: {capability['description']}

Keep node-specific work under nodes/<node_key>. Validate applicable response modes and retain accuracy, independence, prompt, latency, exemplar, context and partner evidence.""")
    once(base / "videos" / "instruction.txt", "Maintain videos-list.csv for capability modelling, assessment examples, caregiver coaching and generalisation. Specify purpose, nodes, concepts, shot list, language, accessibility, rights, safety and status. Concept clips belong in the canonical concept folder.")
    csv_once(base / "videos" / "videos-list.csv", ["video_key", "purpose", "target_node_keys", "target_concept_keys", "language_scope", "duration_seconds", "setting", "people", "shot_list", "audio_or_caption_requirements", "status", "owner", "rights", "review_notes"])
    capability_rows.append([index, capability["key"], capability["name"], "planned", "", ""])

node_rows = [["order", "level", "capability_key", "node_key", "name", "status", "owner", "clinical_reviewer", "language_review_complete", "notes"]]
for index, node in enumerate(PLAN["nodes"], 1):
    level = levels[node["level"]]
    base = ROOT / "capabilities" / node["capability"] / "nodes" / f"l{node['level']:02d}_{node['key']}"
    node_record = node | {
        "level_key": level["key"], "minimum_examples": 6,
        "response_modes": ["touch", "pointing", "gesture", "eye_gaze", "aac", "sign", "vocalisation", "speech", "therapist_observed", "caregiver_observed"],
        "status": "planned",
    }
    json_once(base / "node.json", node_record)
    once(base / "instruction.txt", f"""Node: {node['name']}
Level: L{node['level']} - {level['name']}
Capability: {capabilities[node['capability']]['name']}
Goal: {node['goal']}

1. SLP confirms observable goal, exclusions, prerequisites, supports and regression path.
2. Select meaningful concepts from concept-links.json.
3. Author language expressions from semantic intent.
4. Produce at least six varied exemplars and suitable distractors.
5. Build exposure-through-generalisation activities without requiring speech.
6. Separate prompt, raw correctness and independence scoring.
7. Test applicable clinic and home contexts.
8. Complete clinical, accessibility, language/cultural and rights reviews.

Do not treat this node as a rigid gate unless an edge is explicitly mandatory.""")
    json_once(base / "concept-links.json", {"schema_version": 1, "selection": "by_group", "concept_groups": node["concept_groups"], "include": [], "exclude": [], "notes": "Review relevance per child, culture, language and context."})
    node_parts = {
        "text": "Create semantic instruction intents, prompts, cues, feedback, teaching models and caregiver directions. Localize natively; include short AAC and natural spoken variants.",
        "games": "Design playable activities using shared templates. Specify target/distractors, field size, prompts, response modes, difficulty adjustment, retries, reinforcement, stop behaviour, trial events and accessibility. Include non-audio and non-speech paths where meaningful.",
        "videos": "List short, single-purpose clips needed to model or test this node. Vary actor, object, angle and setting. Record target moment, distractors, language, captions/audio description, consent, rights and review.",
        "activities": "Create briefs joining node, concepts and reusable template. State session purpose, semantic instruction, target, distractor policy, response modes, prompts, difficulty, scoring, mastery evidence and trial payload.",
    }
    for folder, text in node_parts.items():
        once(base / folder / "instruction.txt", text)
    csv_once(base / "games" / "games-list.csv", ["game_key", "template_key", "purpose", "concept_selection", "difficulty", "response_modes", "prompt_levels", "trial_events", "status", "owner", "review_notes"])
    csv_once(base / "videos" / "videos-list.csv", ["video_key", "purpose", "concept_keys", "language_scope", "duration_seconds", "setting", "people", "target_moment", "shot_list", "captions_or_audio", "status", "owner", "rights", "review_notes"])
    json_once(base / "status.json", {"status": "planned", "owner": None, "clinical_reviewer": None, "updated_at": None, "blockers": [], "notes": ""})
    node_rows.append([index, node["level"], node["capability"], node["key"], node["name"], "planned", "", "", "no", ""])

concept_rows = [["order", "category", "type", "concept_key", "name", "status", "owner", "media_complete", "language_packs_complete", "clinical_review", "notes"]]
for index, concept in enumerate(PLAN["concepts"], 1):
    base = ROOT / "concepts" / Path(*concept["category"].split(".")) / concept["key"]
    json_once(base / "concept.json", concept | {"schema_version": 1, "meaning": "TODO: language-independent definition", "not_this": [], "relations": [], "status": "planned"})
    once(base / "instruction.txt", f"""Concept: {concept['name']}
Key: {concept['key']}
Type: {concept['type']}
Category: {concept['category']}

Define meaning before media or translation: what counts, exclusions, confusions, safety/cultural notes and useful relations. Then complete every subfolder. Prefer real-world diversity over cosmetic duplicates.""")
    parts = {
        "images": "Create at least 6 examples: isolated view, natural context, meaningful variation, different viewpoint, different instance/person and unfamiliar generalisation. Record purpose, difficulty, depiction, context, consent, rights, alt-text key, dimensions, checksum and status. Avoid embedded text, watermarks and ambiguity.",
        "videos": "Create 3-5 short contextual examples when motion/function adds meaning. Vary actor/object/setting and include generalisation. Record target timecode, duration, language, accessibility, consent, rights, checksum and review. If no video is useful, document why.",
        "audio": "Keep non-speech concept sounds here. Spoken labels belong in locales/<language>/audio. Record purpose, duration, creator, rights, loudness and checksum. Never make sound the sole cue.",
        "text": "Define language-independent semantic intents: label, identify, request, combinations, questions and natural use as relevant. Child-facing text belongs in locales/<language>; do not assume English word order.",
        "games": "List concept-specific playable uses linked to a node and shared template. Define clear contrast, same-category discrimination, advanced discrimination, functional use and generalisation. Justify distractors.",
        "qa": "Verify definition, target clarity, diversity, distractors, cultural fit, safety, accessibility, rights, technical quality and cross-media consistency. Clinical and native-language approvals are separate.",
    }
    for folder, text in parts.items():
        once(base / folder / "instruction.txt", text)
    csv_once(base / "images" / "assets.csv", ["asset_key", "filename", "purpose", "difficulty", "depiction", "context", "people", "language_scope", "source_or_creator", "licence_or_release", "alt_semantic_key", "width", "height", "checksum", "status", "review_notes"])
    csv_once(base / "videos" / "videos-list.csv", ["video_key", "filename", "purpose", "difficulty", "setting", "people", "target_action", "target_timecode", "duration_seconds", "language_scope", "captions_or_audio", "source_or_creator", "licence_or_release", "checksum", "status", "review_notes"])
    csv_once(base / "audio" / "assets.csv", ["asset_key", "filename", "purpose", "duration_ms", "source_or_creator", "licence_or_release", "loudness_lufs", "checksum", "status", "review_notes"])
    json_once(base / "text" / "semantic-intents.json", {"schema_version": 1, "concept_key": concept["key"], "intents": []})
    csv_once(base / "games" / "games-list.csv", ["game_key", "node_key", "template_key", "purpose", "target_asset_policy", "distractor_policy", "difficulty", "response_modes", "status", "owner", "review_notes"])
    for code, lang in languages.items():
        locale = base / "locales" / code
        once(locale / "instruction.txt", f"Localize '{concept['key']}' for {lang['name']} ({lang['native_name']}) from meaning. Include variety, alternatives, optional transliteration, grammar, identify instruction, AAC-short and request forms. Record translator, native and SLP reviewers. Record approved expressions in audio/.")
        json_once(locale / "text.json", {"schema_version": 1, "concept_key": concept["key"], "language": code, "preferred_term": "TODO", "display_text": "TODO", "alternates": [], "phonetic_text": None, "grammar": [], "expressions": [], "review": {"status": "planned", "translator": None, "native_reviewer": None, "clinical_reviewer": None}})
        once(locale / "audio" / "instruction.txt", "Record a native speaker for each approved expression in text.json. One clean utterance per file; no music. Store variety, release, transcript key, take, sample rate, loudness, duration, checksum and pronunciation review.")
        csv_once(locale / "audio" / "assets.csv", ["asset_key", "filename", "expression_key", "speaker_variety", "speaker_release", "sample_rate", "loudness_lufs", "duration_ms", "checksum", "status", "review_notes"])
    json_once(base / "status.json", {"status": "planned", "owner": None, "media": {"images": "planned", "videos": "planned", "audio": "planned"}, "languages": {code: "planned" for code in languages}, "clinical_review": "planned", "updated_at": None, "blockers": [], "notes": ""})
    concept_rows.append([index, concept["category"], concept["type"], concept["key"], concept["name"], "planned", "", "no", "no", "planned", ""])

tracking = ROOT / "tracking"
once(tracking / "instruction.txt", "Use CSV files as production queues and status.json as item evidence. Stable keys join records. Do not approve until clinical, native-language/cultural, accessibility, rights and technical checks are recorded.")
for filename, rows in [("capabilities.csv", capability_rows), ("nodes.csv", node_rows), ("concepts.csv", concept_rows)]:
    if not (tracking / filename).exists():
        with (tracking / filename).open("w", encoding="utf-8", newline="") as stream:
            csv.writer(stream).writerows(rows)
steps = [
    ["phase", "work_item", "scope", "exit_criteria"],
    [1, "Approve semantic architecture", "capabilities, levels, nodes and graph", "SLP approves goals, boundaries and non-speech pathways"],
    [2, "Pilot concept set", "apple, ball, cup and distractors", "Definitions, relations and 6+ images approved"],
    [3, "Pilot language packs", "English and one home language", "Native text/audio and grammar reviewed"],
    [4, "Pilot activities", "identify_familiar_object", "Exposure through discrimination and trial payload tested"],
    [5, "Functional communication", "request_desired_object", "AAC, gesture, pointing, vocalisation and speech paths verified"],
    [6, "Trial/progress integration", "pilot nodes and concepts", "Raw response, prompt, latency and independence retained"],
    [7, "Generalisation pack", "new people, exemplars and contexts", "Evidence spans partners, settings and retention"],
    [8, "Scale content", "remaining V1 concepts and nodes", "Per-item reviews complete; no untracked assets"],
    [9, "Publish version", "speech_core_v1", "Immutable manifest, checksums and approvals exported"],
]
if not (tracking / "production-order.csv").exists():
    with (tracking / "production-order.csv").open("w", encoding="utf-8", newline="") as stream:
        csv.writer(stream).writerows(steps)

print(f"Speech content scaffold ready: {len(PLAN['capabilities'])} capabilities, {len(PLAN['nodes'])} nodes, {len(PLAN['concepts'])} concepts, {len(PLAN['languages'])} languages")

