#!/usr/bin/env python3
"""
The Auto SKUS Group - brand mark generator, v3.

WHY THIS EXISTS
    The v2 logos were HTML text layout saved as SVG: live <text> elements with
    font-family="Oswald, ...", no @font-face, no embedded font, zero outlined
    paths. Consequences, all verified:
      - the wordmark's width was decided at render time by the viewer's fonts,
        so the "width-matched" barcode could never actually match it;
      - fixed viewBoxes clipped the artwork whenever the fallback font was
        wider than Oswald (the monogram lost its A and S to the edges);
      - letter-spacing was applied after the final glyph of each anchored run,
        which is why AUTO and SKUS looked unevenly spaced around the divider.

    Every mark here is outlined vector geometry measured from the real Oswald
    700 outlines. The barcode is generated to span exactly the measured
    wordmark width, so width-match is true by construction rather than by
    eye on one machine.

    Re-run this file to regenerate the entire kit. The marks are derived, not
    hand-drawn, so they cannot drift apart.
"""

from fontTools.ttLib import TTFont
from fontTools.pens.svgPathPen import SVGPathPen
from fontTools.pens.transformPen import TransformPen
from fontTools.pens.boundsPen import BoundsPen
from fontTools.misc.transform import Transform
from pathlib import Path
import code128

# --------------------------------------------------------------------------
# Brand constants - v2 identity, unchanged. Colors are the contract.
# --------------------------------------------------------------------------
NAVY   = "#0F1E3D"   # Deep Navy      - primary
BLUE   = "#0B5FFF"   # Electric Blue  - accent
AMBER  = "#F6A800"   # Signal Amber   - campaign only, used sparingly
WHITE  = "#FFFFFF"
BLACK  = "#000000"
SLATE  = "#64748B"   # tagline grey

OSWALD = "/home/claude/node_modules/@fontsource/oswald/files/oswald-latin-700-normal.woff2"
INTER  = "/home/claude/node_modules/@fontsource/inter/files/inter-latin-500-normal.woff2"

OUT = Path("/home/claude/brandkit/logos")
OUT.mkdir(parents=True, exist_ok=True)

# --------------------------------------------------------------------------
# Construction grid. Cap height is the unit: CAP = 100.
# Every other dimension is expressed against it, so the system scales as one.
# --------------------------------------------------------------------------
CAP          = 100.0
TRACK        = 0.075   # letter-spacing, em. Applied BETWEEN glyphs only.
DIVIDER_W    = 8.0     # width of the blue divider bar
DIVIDER_GAP  = 26.0    # space either side of the divider
BAR_GAP      = 30.0    # vertical gap from wordmark baseline to barcode top
BAR_H        = 38.0    # barcode field height
TICK_W       = 4.0     # end-cap tick width
TICK_OVER    = 11.0    # how far the end ticks over/undershoot the bar field
PAYLOAD      = "AUTOSKUS"   # what the barcode actually encodes (Code 128B)
PAD          = 16.0    # clear space baked into the viewBox on all sides


def load(path):
    f = TTFont(path)
    return f, f.getGlyphSet(), f.getBestCmap(), f["head"].unitsPerEm, f["OS/2"].sCapHeight


class Wordmark:
    """A run of outlined glyphs on one baseline, measured in CAP units."""

    def __init__(self, font_path, text, cap_target=CAP, track=TRACK):
        self.font, self.gs, self.cmap, self.upem, self.capheight = load(font_path)
        self.scale = cap_target / self.capheight
        self.track = track * cap_target
        self.text = text
        self._layout()

    def _layout(self):
        """Place each glyph, tracking BETWEEN glyphs only - never trailing."""
        self.glyphs = []
        pen_x = 0.0
        for i, ch in enumerate(self.text):
            gn = self.cmap[ord(ch)]
            adv = self.gs[gn].width * self.scale
            self.glyphs.append((gn, pen_x))
            pen_x += adv
            if i < len(self.text) - 1:
                pen_x += self.track
        self.advance = pen_x

        # True inked extent, so the lockup aligns on the artwork not the metrics.
        xs = []
        for gn, x in self.glyphs:
            bp = BoundsPen(self.gs)
            self.gs[gn].draw(bp)
            if bp.bounds:
                xs.append((x + bp.bounds[0] * self.scale, x + bp.bounds[2] * self.scale))
        self.ink_left = min(a for a, _ in xs)
        self.ink_right = max(b for _, b in xs)
        self.ink_width = self.ink_right - self.ink_left

    def path(self, dx=0.0, dy=0.0):
        """Outlined path data. dy is the baseline in SVG space (y grows down)."""
        out = []
        for gn, x in self.glyphs:
            pen = SVGPathPen(self.gs)
            t = Transform(self.scale, 0, 0, -self.scale, x + dx, dy)
            self.gs[gn].draw(TransformPen(pen, t))
            d = pen.getCommands()
            if d:
                out.append(d)
        return " ".join(out)


# --------------------------------------------------------------------------
# Build the two halves once. Every mark reuses these measurements.
# --------------------------------------------------------------------------
AUTO = Wordmark(OSWALD, "AUTO")
SKUS = Wordmark(OSWALD, "SKUS")

# Lockup laid out on inked edges: AUTO | SKUS
AUTO_DX = -AUTO.ink_left
DIVIDER_X = AUTO.ink_width + DIVIDER_GAP
SKUS_DX = DIVIDER_X + DIVIDER_W + DIVIDER_GAP - SKUS.ink_left
LOCKUP_W = DIVIDER_X + DIVIDER_W + DIVIDER_GAP + SKUS.ink_width


def barcode(width, y, accent=BLUE, base=NAVY, tick=BLUE, payload=None):
    """
    A REAL Code 128 symbol spanning EXACTLY `width`.

    This is not a decorative rhythm. It carries a start character, the payload,
    a mod-103 checksum and a stop pattern, and it scans. The module width is
    derived by dividing the available span by the symbol's module count plus
    both quiet zones, so the symbol fills the wordmark exactly AND keeps the
    quiet zones a scanner needs. Width-match and readability are both
    properties of the construction rather than things nudged by eye.
    """
    payload = payload or PAYLOAD
    elements, total_modules = code128.encode(payload)

    # Solve for module size including the two mandatory quiet zones:
    #   width = 2*TICK_W + m*(total + 2*QUIET)
    m = (width - 2 * TICK_W) / (total_modules + 2 * code128.QUIET_MODULES)
    field_x0 = TICK_W + code128.QUIET_MODULES * m

    parts = []
    # End-cap ticks mark the true wordmark edges. They sit outside the quiet
    # zones so they cannot interfere with a read.
    parts.append(f'<rect x="0" y="{y - TICK_OVER:.2f}" width="{TICK_W:.2f}" '
                 f'height="{BAR_H + TICK_OVER * 2:.2f}" fill="{tick}"/>')
    parts.append(f'<rect x="{width - TICK_W:.2f}" y="{y - TICK_OVER:.2f}" width="{TICK_W:.2f}" '
                 f'height="{BAR_H + TICK_OVER * 2:.2f}" fill="{tick}"/>')

    # Accent bars: a few, spread through the run. Electric Blue absorbs red
    # light so it still reads to a laser scanner. Signal Amber does not, which
    # is why the amber variant is explicitly documented as non-scanning.
    bar_positions = [i for i, (_, b) in enumerate(elements) if b]
    accents = {bar_positions[int(len(bar_positions) * k / 6)] for k in range(1, 6)}

    x = field_x0
    for i, (w, is_bar) in enumerate(elements):
        bw = w * m
        if is_bar:
            fill = accent if i in accents else base
            parts.append(f'<rect x="{x:.2f}" y="{y:.2f}" width="{bw:.2f}" '
                         f'height="{BAR_H:.2f}" fill="{fill}"/>')
        x += bw
    return "\n    ".join(parts)


def svg(width, height, body, bg=None, title="", desc=""):
    b = f'<rect width="{width:.2f}" height="{height:.2f}" fill="{bg}"/>\n    ' if bg else ""
    return (
        f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {width:.2f} {height:.2f}" '
        f'width="{width:.0f}" height="{height:.0f}" role="img" aria-labelledby="t d">\n'
        f'  <title id="t">{title}</title>\n'
        f'  <desc id="d">{desc}</desc>\n'
        f'  <g>\n    {b}{body}\n  </g>\n</svg>\n'
    )


def write(name, content):
    (OUT / name).write_text(content, encoding="utf-8")
    return len(content)


# --------------------------------------------------------------------------
# PRIMARY - horizontal lockup with the shelf-edge barcode
# --------------------------------------------------------------------------
def primary(auto_c, skus_c, div_c, bar_base, bar_accent, tick_c, bg=None, name=""):
    baseline = PAD + CAP
    w = LOCKUP_W + PAD * 2
    bar_y = baseline + BAR_GAP
    h = bar_y + BAR_H + TICK_OVER + PAD

    body = (
        f'<path d="{AUTO.path(PAD + AUTO_DX, baseline)}" fill="{auto_c}"/>\n    '
        f'<rect x="{PAD + DIVIDER_X:.2f}" y="{PAD:.2f}" width="{DIVIDER_W:.2f}" '
        f'height="{CAP:.2f}" fill="{div_c}"/>\n    '
        f'<path d="{SKUS.path(PAD + SKUS_DX, baseline)}" fill="{skus_c}"/>\n    '
        f'<g transform="translate({PAD:.2f},0)">\n    '
        f'{barcode(LOCKUP_W, bar_y, bar_accent, bar_base, tick_c)}\n    </g>'
    )
    return svg(w, h, body, bg,
               "The Auto SKUS Group",
               "AUTO SKUS wordmark with the shelf-edge barcode, width-matched to the wordmark.")


# --------------------------------------------------------------------------
# STACKED - AUTO over SKUS, centred, barcode spanning the wider of the two.
# The vertical divider cannot do its job here, so the barcode becomes the rule
# that binds the two words instead.
# --------------------------------------------------------------------------
STACK_LEAD = 9.0    # space between the two baselines, beyond cap height


def stacked(auto_c, skus_c, bar_base, bar_accent, tick_c, bg=None):
    inner = max(AUTO.ink_width, SKUS.ink_width)
    w = inner + PAD * 2
    base1 = PAD + CAP
    base2 = base1 + CAP + STACK_LEAD
    bar_y = base2 + BAR_GAP
    h = bar_y + BAR_H + TICK_OVER + PAD

    ax = PAD + (inner - AUTO.ink_width) / 2 - AUTO.ink_left
    sx = PAD + (inner - SKUS.ink_width) / 2 - SKUS.ink_left

    body = (
        f'<path d="{AUTO.path(ax, base1)}" fill="{auto_c}"/>\n    '
        f'<path d="{SKUS.path(sx, base2)}" fill="{skus_c}"/>\n    '
        f'<g transform="translate({PAD:.2f},0)">\n    '
        f'{barcode(inner, bar_y, bar_accent, bar_base, tick_c)}\n    </g>'
    )
    return svg(w, h, body, bg, "The Auto SKUS Group",
               "Stacked AUTO SKUS lockup with the shelf-edge barcode. For square placements.")


# --------------------------------------------------------------------------
# TAGLINE LOCKUP - primary with the descriptor set beneath, also outlined
# --------------------------------------------------------------------------
TAGLINE = "MANAGED SERVICES FOR LINE REVIEW OPTIMIZATION"
TAG_CAP = 13.0
TAG_TRACK = 0.16
TAG_GAP = 26.0


def tagline_lockup(auto_c, skus_c, div_c, bar_base, bar_accent, tick_c, tag_c, bg=None):
    tag = Wordmark(INTER, TAGLINE, cap_target=TAG_CAP, track=TAG_TRACK)
    baseline = PAD + CAP
    bar_y = baseline + BAR_GAP
    tag_base = bar_y + BAR_H + TICK_OVER + TAG_GAP
    w = LOCKUP_W + PAD * 2
    h = tag_base + PAD

    tx = PAD + (LOCKUP_W - tag.ink_width) / 2 - tag.ink_left
    body = (
        f'<path d="{AUTO.path(PAD + AUTO_DX, baseline)}" fill="{auto_c}"/>\n    '
        f'<rect x="{PAD + DIVIDER_X:.2f}" y="{PAD:.2f}" width="{DIVIDER_W:.2f}" '
        f'height="{CAP:.2f}" fill="{div_c}"/>\n    '
        f'<path d="{SKUS.path(PAD + SKUS_DX, baseline)}" fill="{skus_c}"/>\n    '
        f'<g transform="translate({PAD:.2f},0)">\n    '
        f'{barcode(LOCKUP_W, bar_y, bar_accent, bar_base, tick_c)}\n    </g>\n    '
        f'<path d="{tag.path(tx, tag_base)}" fill="{tag_c}"/>'
    )
    return svg(w, h, body, bg, "The Auto SKUS Group",
               "AUTO SKUS lockup with descriptor: managed services for line review optimization.")


# --------------------------------------------------------------------------
# SOCIAL AVATAR - square, stacked lockup on navy
# --------------------------------------------------------------------------
def social_avatar():
    S = 1024.0
    inner = max(AUTO.ink_width, SKUS.ink_width)
    base1 = CAP
    base2 = base1 + CAP + STACK_LEAD
    bar_y = base2 + BAR_GAP
    art_h = bar_y + BAR_H + TICK_OVER
    art_w = inner

    scale = (S * 0.70) / art_w
    ox = (S - art_w * scale) / 2
    oy = (S - art_h * scale) / 2

    ax = (inner - AUTO.ink_width) / 2 - AUTO.ink_left
    sx = (inner - SKUS.ink_width) / 2 - SKUS.ink_left

    inner_body = (
        f'<path d="{AUTO.path(ax, base1)}" fill="{WHITE}"/>\n    '
        f'<path d="{SKUS.path(sx, base2)}" fill="{BLUE}"/>\n    '
        f'{barcode(inner, bar_y, BLUE, WHITE, BLUE)}'
    )
    body = (f'<rect width="{S:.0f}" height="{S:.0f}" fill="{NAVY}"/>\n    '
            f'<g transform="translate({ox:.2f},{oy:.2f}) scale({scale:.4f})">\n    '
            f'{inner_body}\n    </g>')
    return svg(S, S, body, None, "The Auto SKUS Group",
               "Square social avatar: stacked lockup on Deep Navy.")


# --------------------------------------------------------------------------
# FAVICON - no typography. At 16px the wordmark is unreadable, so the mark
# reduces to the motif alone: the shelf edge, which is the idea anyway.
# --------------------------------------------------------------------------
def favicon():
    S = 64.0
    pad = 11.0
    field_w = S - pad * 2
    bars = [(3, 1), (2, 0), (2, 1), (2, 0), (5, 1), (2, 0), (3, 1), (2, 0),
            (2, 1), (2, 0), (4, 1), (2, 0), (3, 1)]
    total = sum(w for w, _ in bars)
    m = field_w / total
    accent_at = {4, 8}

    parts = [f'<rect width="{S:.0f}" height="{S:.0f}" rx="7" fill="{NAVY}"/>']
    x = pad
    i = 0
    for w, is_bar in bars:
        bw = w * m
        if is_bar:
            parts.append(f'<rect x="{x:.2f}" y="16" width="{bw:.2f}" height="32" '
                         f'fill="{BLUE if i in accent_at else WHITE}"/>')
            i += 1
        x += bw
    return svg(S, S, "\n    ".join(parts), None, "The Auto SKUS Group",
               "Favicon mark: the shelf-edge motif alone, legible at 16px.")


# --------------------------------------------------------------------------
# WORDMARK ONLY - no motif, for tight horizontal spaces
# --------------------------------------------------------------------------
def wordmark(auto_c, skus_c, div_c, bg=None):
    baseline = PAD + CAP
    w = LOCKUP_W + PAD * 2
    h = CAP + PAD * 2
    body = (
        f'<path d="{AUTO.path(PAD + AUTO_DX, baseline)}" fill="{auto_c}"/>\n    '
        f'<rect x="{PAD + DIVIDER_X:.2f}" y="{PAD:.2f}" width="{DIVIDER_W:.2f}" '
        f'height="{CAP:.2f}" fill="{div_c}"/>\n    '
        f'<path d="{SKUS.path(PAD + SKUS_DX, baseline)}" fill="{skus_c}"/>'
    )
    return svg(w, h, body, bg, "The Auto SKUS Group",
               "AUTO SKUS wordmark, no motif. For nav bars, signatures and tight spaces.")


if __name__ == "__main__":
    print(f"AUTO ink width : {AUTO.ink_width:8.2f}")
    print(f"SKUS ink width : {SKUS.ink_width:8.2f}")
    print(f"LOCKUP width   : {LOCKUP_W:8.2f}  (cap height = {CAP})")
    print(f"ratio W:H      : {LOCKUP_W / CAP:8.3f}")

    files = {
        "auto-skus-primary-light.svg": primary(NAVY, BLUE, BLUE, NAVY, BLUE, BLUE),
        "auto-skus-primary-dark.svg":  primary(WHITE, BLUE, BLUE, WHITE, BLUE, BLUE, bg=NAVY),
        "auto-skus-wordmark-light.svg": wordmark(NAVY, BLUE, BLUE),
        "auto-skus-wordmark-dark.svg":  wordmark(WHITE, BLUE, BLUE, bg=NAVY),
        "auto-skus-mono-black.svg":     primary(BLACK, BLACK, BLACK, BLACK, BLACK, BLACK),
        "auto-skus-mono-white.svg":     primary(WHITE, WHITE, WHITE, WHITE, WHITE, WHITE, bg=NAVY),
        "auto-skus-mono-blue.svg":      primary(BLUE, BLUE, BLUE, BLUE, BLUE, BLUE),
        "auto-skus-amber-accent.svg":   primary(NAVY, BLUE, BLUE, NAVY, AMBER, AMBER),
        "auto-skus-stacked-light.svg":  stacked(NAVY, BLUE, NAVY, BLUE, BLUE),
        "auto-skus-stacked-dark.svg":   stacked(WHITE, BLUE, WHITE, BLUE, BLUE, bg=NAVY),
        "auto-skus-primary-light-tagline.svg":
            tagline_lockup(NAVY, BLUE, BLUE, NAVY, BLUE, BLUE, SLATE),
        "auto-skus-primary-dark-tagline.svg":
            tagline_lockup(WHITE, BLUE, BLUE, WHITE, BLUE, BLUE, "#94A3B8", bg=NAVY),
        "auto-skus-social-avatar.svg":  social_avatar(),
        "auto-skus-favicon.svg":        favicon(),
    }
    for n, c in files.items():
        print(f"  wrote {n:<34} {write(n, c):6d} bytes")
