#!/usr/bin/env python3
"""OKELIS · diagram & icon generation (part 2)."""
import math, os, re

OUT = os.path.join(os.path.dirname(__file__), "..", "assets", "gfx")
os.makedirs(OUT, exist_ok=True)

NAVY, BLUE, BLUE2, BLUE3 = "#021849", "#1B5AA8", "#3D79C4", "#7BA3D6"
SKY, RED, MUTED, LINE = "#B9CDE8", "#E1330F", "#8590A6", "#DDE1E8"
TXT, DSP = "SF Pro Text", "SF Pro Display"


def write(name, body, w, h, extra="", fscale=1.0):
    body = re.sub(r"&(?!(amp|lt|gt|quot|apos|#)\w*;)", "&amp;", body)
    if fscale != 1.0:
        body = re.sub(r'font-size="([\d.]+)"',
                      lambda m: f'font-size="{float(m.group(1))*fscale:.2f}"', body)
    with open(os.path.join(OUT, name), "w") as f:
        f.write(f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {h}" '
                f'width="{w}" height="{h}" fill="none">{extra}{body}</svg>')
    print("·", name)


# ------------------------------------------------------------------
# ECOSYSTEM · six disciplines, one integrated outcome
# ------------------------------------------------------------------
def ecosystem():
    W, H = 540, 540
    cx, cy, R = 270, 268, 192
    nodes = [
        ("GREEN BUILDING", "Certification",       "01"),
        ("ENERGY",         "Modelling & daylight", "02"),
        ("CARBON",         "GHG & net zero",       "03"),
        ("ESG",            "Reporting & advisory", "04"),
        ("LCA",            "Environmental impact", "05"),
        ("LCC",            "Whole-life cost",      "06"),
    ]
    pos = []
    for i in range(6):
        a = math.radians(-90 + i * 60)
        pos.append((cx + R * math.cos(a), cy + R * math.sin(a)))

    g = []
    # integration chords · every discipline informs every other
    for i in range(6):
        for j in range(i + 1, 6):
            x1, y1 = pos[i]; x2, y2 = pos[j]
            g.append(f'<path d="M{x1:.1f} {y1:.1f}Q{cx} {cy} {x2:.1f} {y2:.1f}" '
                     f'stroke="{SKY}" stroke-width=".8" opacity=".55"/>')
    # orbit
    g.append(f'<circle cx="{cx}" cy="{cy}" r="{R}" stroke="{LINE}" stroke-width=".8" '
             f'stroke-dasharray="2 4"/>')
    # centre
    g.append(f'<circle cx="{cx}" cy="{cy}" r="82" fill="{NAVY}"/>')
    g.append(f'<text x="{cx}" y="{cy-16}" text-anchor="middle" fill="#7BA3D6" '
             f'font-family="{TXT}" font-size="8" font-weight="600" letter-spacing="1.6">OUTCOME</text>')
    for k, ln in enumerate(["Measurable", "sustainable", "performance"]):
        g.append(f'<text x="{cx}" y="{cy+4+k*17}" text-anchor="middle" fill="#fff" '
                 f'font-family="{DSP}" font-size="15" font-weight="500" letter-spacing="-.4">{ln}</text>')
    # nodes
    for (nm, sub, no), (x, y) in zip(nodes, pos):
        g.append(f'<circle cx="{x:.1f}" cy="{y:.1f}" r="54" fill="#fff" stroke="{NAVY}" stroke-width="1.4"/>')
        g.append(f'<text x="{x:.1f}" y="{y-16:.1f}" text-anchor="middle" fill="{RED}" '
                 f'font-family="{DSP}" font-size="8" font-weight="600" letter-spacing=".8">{no}</text>')
        g.append(f'<text x="{x:.1f}" y="{y+2:.1f}" text-anchor="middle" fill="{NAVY}" '
                 f'font-family="{DSP}" font-size="11.5" font-weight="600" letter-spacing="-.25">{nm}</text>')
        g.append(f'<text x="{x:.1f}" y="{y+18:.1f}" text-anchor="middle" fill="{MUTED}" '
                 f'font-family="{TXT}" font-size="7.4" letter-spacing=".1">{sub}</text>')
    write("ecosystem.svg", "".join(g), W, H, fscale=1.22)


# ------------------------------------------------------------------
# LCA LOOP · cradle to grave, with the reuse return arc
# ------------------------------------------------------------------
def lca_loop():
    W, H = 560, 520
    cx, cy, R = 280, 262, 170
    stages = [("A1–A3", "Raw materials"), ("A3", "Manufacturing"), ("A4", "Transport"),
              ("A5", "Construction"), ("B1–B7", "Operation & use"),
              ("B4", "Replacement"), ("C1–C4", "End of life")]
    n = len(stages)
    g = []
    span = 318.0                      # leave a gap at the top for the return arc
    for i, (code, nm) in enumerate(stages):
        a0 = math.radians(-71 + i * span / n)
        a1 = math.radians(-71 + (i + 1) * span / n - 4)
        x0, y0 = cx + R*math.cos(a0), cy + R*math.sin(a0)
        x1, y1 = cx + R*math.cos(a1), cy + R*math.sin(a1)
        t = i / (n - 1)
        col = ["#021849", "#0A2A66", "#143C82", "#1B5AA8", "#3D79C4", "#5E8FCB", "#7BA3D6"][i]
        g.append(f'<path d="M{x0:.2f} {y0:.2f}A{R} {R} 0 0 1 {x1:.2f} {y1:.2f}" '
                 f'stroke="{col}" stroke-width="26" fill="none"/>')
        am = (a0 + a1) / 2
        lx, ly = cx + (R + 40)*math.cos(am), cy + (R + 40)*math.sin(am)
        anc = "middle"
        if math.cos(am) > .35: anc = "start"
        elif math.cos(am) < -.35: anc = "end"
        g.append(f'<text x="{lx:.1f}" y="{ly:.1f}" text-anchor="{anc}" fill="{NAVY}" '
                 f'font-family="{DSP}" font-size="12.5" font-weight="600" letter-spacing="-.28">{nm}</text>')
        g.append(f'<text x="{lx:.1f}" y="{ly+12:.1f}" text-anchor="{anc}" fill="{RED}" '
                 f'font-family="{TXT}" font-size="8" font-weight="600" letter-spacing="1">{code}</text>')
        # step tick
        mx, my = cx + R*math.cos(am), cy + R*math.sin(am)
        g.append(f'<text x="{mx:.1f}" y="{my+3.4:.1f}" text-anchor="middle" fill="#fff" '
                 f'font-family="{DSP}" font-size="10.5" font-weight="600">{i+1}</text>')

    # return / circularity arc (module D)
    ae, ab = math.radians(-71 + span), math.radians(-71)
    xe, ye = cx + (R-40)*math.cos(ae), cy + (R-40)*math.sin(ae)
    xb, yb = cx + (R-40)*math.cos(ab), cy + (R-40)*math.sin(ab)
    g.append(f'<path d="M{xe:.1f} {ye:.1f}A{R-40} {R-40} 0 0 1 {xb:.1f} {yb:.1f}" '
             f'stroke="{RED}" stroke-width="1.8" stroke-dasharray="5 3.5" fill="none"/>')
    g.append(f'<path d="M{xb:.1f} {yb:.1f}l-9 -3.5l1.5 9Z" fill="{RED}"/>')
    g.append(f'<text x="{cx}" y="{cy-R+52}" text-anchor="middle" fill="{RED}" '
             f'font-family="{TXT}" font-size="8" font-weight="600" letter-spacing="1.2">'
             f'MODULE D · REUSE AND RECOVERY</text>')
    # centre readout
    g.append(f'<text x="{cx}" y="{cy-6}" text-anchor="middle" fill="{NAVY}" '
             f'font-family="{DSP}" font-size="17" font-weight="500" letter-spacing="-.45">Whole-life</text>')
    g.append(f'<text x="{cx}" y="{cy+12}" text-anchor="middle" fill="{NAVY}" '
             f'font-family="{DSP}" font-size="17" font-weight="500" letter-spacing="-.45">impact</text>')
    g.append(f'<text x="{cx}" y="{cy+32}" text-anchor="middle" fill="{MUTED}" '
             f'font-family="{TXT}" font-size="7.2" font-weight="600" letter-spacing="1.2">EN 15978 · ISO 14040/44</text>')
    write("lca-loop.svg", "".join(g), W, H, fscale=1.68)


# ------------------------------------------------------------------
# SECTOR ICONS · 10 custom line marks, single consistent grammar
# ------------------------------------------------------------------
def sector_icons():
    """Each icon is drawn on a 48×48 grid, 1.6 stroke, navy."""
    S = 48
    I = {}
    I["Residential"] = 'M6 22L24 8l18 14M11 20v20h26V20M20 40v-11h8v11'
    I["Commercial"]  = 'M8 42V10h18v32M26 42V20h14v22M12 16h4M20 16h4M12 24h4M20 24h4M12 32h4M20 32h4M31 26h4M31 34h4'
    I["Hospitality"] = 'M8 42V16h32v26M8 24h32M14 20h3M22 20h3M30 20h3M14 30h20M14 36h20'
    I["Education"]   = 'M4 18L24 9l20 9-20 9-20-9ZM12 22v12c0 3 5.4 5.5 12 5.5S36 37 36 34V22M42 19v11'
    I["Healthcare"]  = 'M9 42V14h30v28M24 20v14M17 27h14M9 42h30'
    I["Retail"]      = 'M7 17h34l-3 25H10L7 17ZM17 17v-4a7 7 0 0 1 14 0v4M7 24h34'
    I["Mixed-Use"]   = 'M5 42V22h13v20M18 42V10h12v32M30 42V26h13v16M9 28h5M9 34h5M22 16h4M22 24h4M22 32h4M34 32h5'
    I["Infrastructure"] = 'M4 34h40M12 34V16M36 34V16M4 20c8-8 32-8 40 0M12 20l6 14M36 20l-6 14M24 17v17'
    I["Industrial"]  = 'M6 42V22l12 7V22l12 7V14h12v28ZM6 42h36M38 22h4'
    I["Government"]  = 'M6 20 24 9l18 11M9 20v18M17 20v18M31 20v18M39 20v18M5 42h38M6 38h36'
    out = []
    for nm, d in I.items():
        body = (f'<path d="{d}" stroke="{NAVY}" stroke-width="1.7" stroke-linecap="round" '
                f'stroke-linejoin="round"/>')
        key = nm.lower().replace("-", "").replace(" ", "")
        write(f"icon-{key}.svg", body, S, S)
        out.append(nm)
    return out


# ------------------------------------------------------------------
# SERVICE ICONS · one per core service
# ------------------------------------------------------------------
def service_icons():
    S = 48
    ic = {
        # A · certification · building inside a certification frame
        "cert": 'M10 40V16l14-8 14 8v24M17 40V26h14v14M24 13v6M12 40h24',
        # B · ESG · three governance pillars rising
        "esg": 'M8 40V26M20 40V16M32 40V21M44 40V10M6 44h40',
        # C · carbon · emissions cloud reducing to a datum
        "carbon": 'M12 22a8 8 0 0 1 15-3 7 7 0 0 1 9 9H14a6 6 0 0 1-2-6ZM10 38h28M16 32v6M24 32v6M32 32v6',
        # D · LCA · closed material loop
        "lca": 'M24 8a16 16 0 1 1-13 25M11 33l-1-8M11 33l8-2M24 8l-6 4M24 8l-6-4',
        # E · LCC · cost stacked over time
        "lcc": 'M8 40h34M10 40V30M18 40V22M26 40V14M34 40V24M8 10c10 2 18 8 26 4',
        # F · energy · building with a flow signal through it
        "energy": 'M10 40V14l14-6 14 6v26M10 40h28M26 18l-7 10h6l-4 8 8-11h-6l3-7Z',
        # G · daylight · sun path into a section
        "daylight": 'M12 40V18h24v22M12 40h24M8 12l6 5M24 6v7M40 12l-6 5M18 40V26h8v14',
    }
    for k, d in ic.items():
        write(f"svc-{k}.svg",
              f'<path d="{d}" stroke="{NAVY}" stroke-width="1.7" stroke-linecap="round" '
              f'stroke-linejoin="round"/>', S, S)


if __name__ == "__main__":
    ecosystem(); lca_loop(); sector_icons(); service_icons()
    print("done")
