# -*- coding: utf-8 -*-
"""
build_system_breakdown.py — generates 01_System/SYSTEM_BREAKDOWN.md (GOV-B4.10).

OWNER: 01_System/build_system_breakdown.py
REVIEW: regenerate whenever COMPONENTS or IF_REG changes in project_data.py.

GOV-B4.10 requires a decomposition into named subsystems and functions with dependencies mapped
and interfaces defined, and forbids starting a build you cannot draw as parts and interfaces.
The breakdown is GENERATED from the component and interface registers rather than hand-drawn, so
it cannot drift from them — a hand-drawn architecture diagram is out of date the day after it is
drawn, and nobody notices.
"""
import os, sys, datetime
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import project_data as P

OUT = os.path.join(HERE, "SYSTEM_BREAKDOWN.md")


def build():
    L = []
    L.append("# SYSTEM BREAKDOWN\n")
    L.append("OWNER: `01_System/build_system_breakdown.py` — this file is GENERATED, do not hand-edit.  ")
    L.append("REVIEW: regenerate whenever a component or an interface changes in `project_data.py`.  ")
    L.append("Generated %s from the component register (%d components) and the interface register "
             "(%d interfaces).\n" % (datetime.date.today().isoformat(), len(P.COMPONENTS), len(P.IF_REG)))
    L.append("Mandated by **GOV-B4.10**: a system that cannot be drawn as parts and interfaces must not be "
             "built. This is that drawing, and it is generated from the registers rather than drawn by hand, "
             "so it cannot quietly stop being true.\n")

    L.append("---\n")
    L.append("## 1. Subsystems\n")
    L.append("| ID | Component | The one thing it is responsible for | What it consumes | Where it lives | Owner | Requirements |")
    L.append("|---|---|---|---|---|---|---|")
    for cid, name, purpose, consumes, lives, owner, reqs in P.COMPONENTS:
        L.append("| %s | **%s** | %s | %s | `%s` | %s | %s |"
                 % (cid, name, purpose, consumes, lives, owner, ", ".join(reqs)))
    L.append("")

    L.append("## 2. Interfaces\n")
    L.append("Every arrow between two subsystems is a row here. An arrow that is not a row, or a row that is "
             "not an arrow, is a defect (GOV-B4.9).\n")
    L.append("| ID | From | To | Direction | What crosses | Form | When | Owner |")
    L.append("|---|---|---|---|---|---|---|---|")
    for r in P.IF_REG:
        L.append("| %s | %s | %s | %s | %s | %s | %s | %s |" % (r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]))
    L.append("")

    L.append("## 3. Dependency map\n")
    L.append("Read down the left column for the producer and across for the consumer. A mark means the "
             "producer sends something to the consumer.\n")
    names = [c[1] for c in P.COMPONENTS]
    short = {n: n.split()[0][:9] for n in names}
    # build the adjacency from the interface register by matching component names in the endpoint text
    edges = set()
    for r in P.IF_REG:
        a = next((n for n in names if n.lower() in str(r[1]).lower()), None)
        b = next((n for n in names if n.lower() in str(r[2]).lower()), None)
        if a and b and a != b:
            edges.add((a, b))
    L.append("| produces \\\\ consumes | " + " | ".join(short[n] for n in names) + " |")
    L.append("|---" * (len(names) + 1) + "|")
    for a in names:
        row = ["**%s**" % short[a]]
        for b in names:
            row.append("—" if a == b else ("→" if (a, b) in edges else ""))
        L.append("| " + " | ".join(row) + " |")
    L.append("")
    L.append("%d directed dependencies were derived from the interface register. A blank cell means no "
             "interface row connects those two components in that direction; if one is missing, the fix is a "
             "row in the interface register, never a line added to this file, because this file is "
             "regenerated and would lose it.\n" % len(edges))

    L.append("## 4. Build order\n")
    L.append("GOV-B4.11 forbids integrating an unverified part. The order below is the order the interfaces "
             "impose: nothing is built before what it consumes.\n")
    order = [
        ("1", "C1 Source of Truth", "Everything else is a projection of it. Nothing can be built first."),
        ("2", "The financial models", "They compute the figures every artefact quotes. Built against the source of truth, verified before anything reads them."),
        ("3", "The register projections", "The workbook and its plain-text CSVs. Generated only."),
        ("4", "The deliverables", "Study, financial workbook, decision pack, business plan twin and its A3 page."),
        ("5", "The surfaces", "Dashboard, Help Hub, README, transfer pack. They read everything above and originate nothing."),
        ("6", "The checker suite", "Built last and run first at every gate. It is the only part that is allowed to fail the build."),
    ]
    L.append("| Step | What is built | Why it cannot come earlier |")
    L.append("|---|---|---|")
    for a, b, c in order:
        L.append("| %s | %s | %s |" % (a, b, c))
    L.append("")

    L.append("## 5. The web-application function slot (GOV-B7.1)\n")
    L.append("GOV-B7.1 requires every project to carry the web-application function in its requirements from "
             "framing — a deploy-anywhere self-contained container, a named-user login with passwords hashed "
             "at rest, and a pluggable AI-engine connector — and says the slot applies **retroactively to "
             "every existing project**. GOV-B7.2 says the slot is mandatory but the build timing belongs to "
             "the Owner.\n")
    L.append("**Status in this project: SLOT DECLARED, NOT BUILT.** It is carried as REQ-WEB-01 in the "
             "requirements register and as BKL-011 in the backlog, not as a delivered component, because "
             "Zaid has not asked for it running. The reference implementation named by GOV-B7.4 is the "
             "Flask application in the governance project's own outputs, which is connected to this session "
             "but has not been read into this project — reading it in would be a Class 2 change and it has "
             "not been requested.\n")
    L.append("**The three constraints that already bind, whether or not it is ever built:** AI-engine "
             "credentials live in server environment variables only and a key in any client-served file is a "
             "Class 1 defect (GOV-B7.3, INV-5); server-side requests are http or https with the host "
             "validated and localhost, loopback, private and reserved addresses refused (GOV-B7.3); and the "
             "checker suite already scans every generated artefact for credential material (C08).\n")
    return "\n".join(L) + "\n"


if __name__ == "__main__":
    with open(OUT, "w", encoding="utf-8") as f:
        f.write(build())
    print("wrote %s" % os.path.relpath(OUT, os.path.dirname(HERE)))
