#!/usr/bin/env python3
"""scaffold_bundle.py — Creates the skeleton of an OKF (Open Knowledge Format) bundle for a company.

Generates the folder tree of the 12 phases, with an `index.md` in each folder, plus the
root `index.md` (phase dashboard) and the root `log.md`. Reserved files
(index.md / log.md) do NOT receive a `type`, per the OKF spec.

The `06-produto` and `08-tech` folders are only created with --has-product / --has-tech.

Deterministic. No LLM calls. Standard library only.

Usage:
    python scaffold_bundle.py                      # preview (dry-run) of "Example Company"
    python scaffold_bundle.py "My Company" --out ./my-company
    python scaffold_bundle.py "Acme" --out ./acme --has-product --has-tech
    python scaffold_bundle.py "Acme" --out ./acme --dry-run --output json
    python scaffold_bundle.py --sample             # same as the first (preview, does not write)
"""

import argparse
import json
import os
import re
import sys
import unicodedata

# Phase folders. (slug, label, conditional?)
FOLDERS = [
    ("00-fundacao", "Foundation", None),
    ("01-estrategia", "Strategy", None),
    ("02-mercado", "Market", None),
    ("03-financeiro", "Financial", None),
    ("04-comercial", "Sales", None),
    ("05-marketing", "Marketing", None),
    ("06-produto", "Product", "has_product"),
    ("07-operacoes", "Operations", None),
    ("08-tech", "Tech", "has_tech"),
    ("09-pessoas", "People", None),
    ("10-juridico", "Legal", None),
    ("11-governanca", "Governance", None),
]

# Dashboard: (phase number, area) — phase 0 = discovery, no folder of its own.
DASHBOARD = [
    (0, "Discovery"), (1, "Foundation"), (2, "Strategy"), (3, "Market"),
    (4, "Financial"), (5, "Sales"), (6, "Marketing"), (7, "Product"),
    (8, "Operations"), (9, "Tech"), (10, "People"), (11, "Legal"),
    (12, "Governance"),
]


def slugify(name):
    """lowercase, no accents, hyphen instead of space."""
    nfkd = unicodedata.normalize("NFKD", name)
    ascii_only = "".join(c for c in nfkd if not unicodedata.combining(c))
    ascii_only = ascii_only.lower()
    ascii_only = re.sub(r"[^a-z0-9]+", "-", ascii_only).strip("-")
    return ascii_only or "company"


def planned_folders(has_product, has_tech):
    flags = {"has_product": has_product, "has_tech": has_tech}
    out = []
    for slug, label, cond in FOLDERS:
        if cond is None or flags.get(cond):
            out.append((slug, label))
    return out


def root_index(name, folders):
    rows = "\n".join(f"| {n} | {area} | ⬜ |" for n, area in DASHBOARD)
    folder_rows = "\n".join(f"| [{slug}]({slug}/index.md) | {label} |" for slug, label in folders)
    return (
        f"# {name} — OKF Bundle\n\n"
        "Company documented as code (Open Knowledge Format v0.1). "
        "Each file is a concept; relations are markdown links; `index.md`/`log.md` are reserved.\n\n"
        "## Company data\n\n"
        f"- **Name:** {name}\n- **Stage:** _(to be filled in PHASE 0)_\n"
        "- **Model:** _(service / product / SaaS / marketplace / hybrid)_\n\n"
        "## Progress of the 12 phases\n\n"
        "| Phase | Area | Status |\n|---|---|---|\n"
        f"{rows}\n\n"
        "Legend: ✅ done · 🚧 in progress · ⬜ pending.\n\n"
        "**Suggested next step:** start PHASE 0 (discovery).\n\n"
        "## Folders\n\n"
        "| Folder | Area |\n|---|---|\n"
        f"{folder_rows}\n"
    )


def root_log(name):
    return (
        f"# Decision log — {name}\n\n"
        "Append-only history. Most recent entry at the top. ISO 8601 timestamp.\n\n"
        "## 2026-01-01T00:00:00Z — Bundle created\n\n"
        "- **What changed:** OKF skeleton generated by scaffold_bundle.py.\n"
        "- **Decision:** _(to be recorded)_.\n"
        "- **Discarded alternatives:** _(to be recorded)_.\n"
        "- **Rationale:** _(to be recorded)_.\n"
    )


def folder_index(label):
    return (
        f"# {label}\n\n"
        "_(1 paragraph: purpose of this area.)_\n\n"
        "## Concepts\n\n"
        "| Concept | What it is | type | status |\n|---|---|---|---|\n"
        "<!-- okf:index:start -->\n"
        "<!-- (no concepts yet — generated by index_generator.py) -->\n"
        "<!-- okf:index:end -->\n"
    )


def build_plan(name, out_dir, has_product, has_tech):
    """Returns a list of (relative_path, content) that would be written."""
    folders = planned_folders(has_product, has_tech)
    files = [
        ("index.md", root_index(name, folders)),
        ("log.md", root_log(name)),
    ]
    for slug, label in folders:
        files.append((f"{slug}/index.md", folder_index(label)))
    return files


def write_plan(out_dir, files, force):
    written, skipped = [], []
    for rel, content in files:
        dest = os.path.join(out_dir, rel)
        os.makedirs(os.path.dirname(dest), exist_ok=True)
        if os.path.exists(dest) and not force:
            skipped.append(rel)
            continue
        with open(dest, "w", encoding="utf-8") as f:
            f.write(content)
        written.append(rel)
    return written, skipped


def main():
    try:
        sys.stdout.reconfigure(encoding="utf-8")
    except Exception:
        pass

    p = argparse.ArgumentParser(
        description="Creates the skeleton of an OKF bundle for a company.",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=__doc__,
    )
    p.add_argument("name", nargs="?", help="Company name (omitted = example preview)")
    p.add_argument("--out", help="Destination folder (default: ./<name-slug>)")
    p.add_argument("--has-product", action="store_true", help="Includes the 06-produto folder")
    p.add_argument("--has-tech", action="store_true", help="Includes the 08-tech folder")
    p.add_argument("--force", action="store_true", help="Overwrites existing files")
    p.add_argument("--dry-run", action="store_true", help="Does not write; only shows the plan")
    p.add_argument("--sample", action="store_true", help="Preview of 'Example Company' (does not write)")
    p.add_argument("--output", choices=("text", "json"), default="text")
    args = p.parse_args()

    sample_mode = args.sample or not args.name
    name = args.name or "Example Company"
    dry = args.dry_run or sample_mode
    out_dir = args.out or os.path.join(".", slugify(name))

    files = build_plan(name, out_dir, args.has_product, args.has_tech)

    if dry:
        written, skipped = [], []
        action = "PREVIEW (nothing written)"
    else:
        written, skipped = write_plan(out_dir, files, args.force)
        action = "WRITTEN"

    result = {
        "name": name,
        "out_dir": out_dir,
        "action": action,
        "planned_files": [rel for rel, _ in files],
        "written": written,
        "skipped_existing": skipped,
        "has_product": args.has_product,
        "has_tech": args.has_tech,
    }

    if args.output == "json":
        print(json.dumps(result, indent=2, ensure_ascii=False))
    else:
        print("=" * 64)
        print("SCAFFOLD OKF BUNDLE")
        print(f"Company: {name}")
        print(f"Destination: {out_dir}   [{action}]")
        print("=" * 64)
        for rel, _ in files:
            mark = "+" if (dry or rel in written) else ("=" if rel in skipped else " ")
            print(f"  [{mark}] {rel}")
        if skipped:
            print(f"\n{len(skipped)} file(s) preserved (use --force to overwrite).")
        if dry:
            print("\n(dry-run/sample: nothing was written. Run with a name + --out to generate.)")
    return 0


if __name__ == "__main__":
    sys.exit(main())
