from __future__ import annotations

import re
from pathlib import Path
from typing import Any

from docx import Document

from .static_forms import REVIEW_WARNING


def write_docx_form(document_path: Path, form: dict[str, Any]) -> None:
    document_path.parent.mkdir(parents=True, exist_ok=True)
    document = Document()
    document.add_heading(str(form.get("title", "")), level=1)
    document.add_paragraph(f"Form ID: {form.get('form_id', '')}")
    document.add_paragraph(f"Type: {form.get('form_type', '')}")
    document.add_paragraph(f"Family: {form.get('family', '')}")

    document.add_heading("Structured fields", level=2)
    table = document.add_table(rows=1, cols=5)
    table.style = "Table Grid"
    headers = ["Section", "Field", "Key", "Default layer", "Required"]
    for index, header in enumerate(headers):
        table.rows[0].cells[index].text = header
    for field in form.get("fields", []):
        row = table.add_row().cells
        row[0].text = str(field.get("section", ""))
        row[1].text = str(field.get("label", ""))
        row[2].text = str(field.get("key", ""))
        row[3].text = str(field.get("default_layer", ""))
        row[4].text = "Required" if field.get("required") else "Optional"

    document.add_heading("Narrative template", level=2)
    for paragraph in str(form.get("narrative_template") or form.get("template") or "").split("\n"):
        document.add_paragraph(paragraph)
    document.add_paragraph(REVIEW_WARNING)
    document.save(document_path)


def write_docx_outputs(data: dict[str, Any], output_dir: Path) -> dict[str, str]:
    procedure_dir = output_dir / "Procedure_DOCX"
    condition_dir = output_dir / "Condition_Folders"
    procedure_dir.mkdir(parents=True, exist_ok=True)
    condition_dir.mkdir(parents=True, exist_ok=True)

    for stale_file in [*procedure_dir.glob("*.docx"), *condition_dir.glob("*")]:
        if stale_file.is_file():
            stale_file.unlink()
        elif stale_file.is_dir():
            for child in stale_file.rglob("*"):
                if child.is_file():
                    child.unlink()
            for child_dir in sorted((p for p in stale_file.rglob("*") if p.is_dir()), reverse=True):
                child_dir.rmdir()
            stale_file.rmdir()

    forms_by_id = {form.get("form_id"): form for form in data.get("forms", [])}
    for form in data.get("forms", []):
        if form.get("form_type") == "Procedure":
            write_docx_form(procedure_dir / f"{form['form_id']}.docx", form)

    for condition in data.get("conditions", []):
        folder = condition_dir / _safe_folder_name(str(condition.get("condition_id") or condition.get("condition")))
        folder.mkdir(parents=True, exist_ok=True)
        history_form = forms_by_id.get(condition.get("history_form_id"))
        exam_form = forms_by_id.get(condition.get("exam_form_id"))
        if history_form:
            write_docx_form(folder / "History_Template.docx", history_form)
        if exam_form:
            write_docx_form(folder / "Physical_Exam_Template.docx", exam_form)
        (folder / "Procedure_Map.md").write_text(_procedure_map(condition, forms_by_id), encoding="utf-8")

    return {
        "procedure_docx": str(procedure_dir),
        "condition_folders": str(condition_dir),
    }


def _safe_folder_name(value: str) -> str:
    normalized = re.sub(r"[^A-Za-z0-9_-]+", "_", value.strip())
    return normalized.strip("_") or "condition"


def _procedure_map(condition: dict[str, Any], forms_by_id: dict[str, dict[str, Any]]) -> str:
    lines = [
        f"# {condition.get('condition', condition.get('condition_id', 'Condition'))}",
        "",
        f"- Condition ID: `{condition.get('condition_id', '')}`",
        f"- History form: `{condition.get('history_form_id', '')}`",
        f"- Physical exam form: `{condition.get('exam_form_id', '')}`",
        "",
        "## Applicable Procedures",
        "",
    ]
    for procedure_id in condition.get("procedure_ids", []):
        procedure = forms_by_id.get(procedure_id, {})
        title = procedure.get("title", procedure_id)
        lines.append(f"- `{procedure_id}` - {title}")
    if condition.get("prompts"):
        lines.extend(["", "## Condition Prompts", "", str(condition["prompts"])])
    return "\n".join(lines) + "\n"
