#!/usr/bin/env python3
"""
Auto SKUS brand kit v3 - raster exports and the LinkedIn kit.

Run after build_kit.py. Everything here is DERIVED from the SVG masters, so a
change to the marks propagates by re-running, never by hand-editing a PNG.

Light variants export with a TRANSPARENT background so they can sit on any
light surface. Dark variants carry their own Deep Navy plate.
"""

import io
from pathlib import Path
import cairosvg
from PIL import Image

KIT      = Path("/home/claude/brandkit")
LOGOS    = KIT / "logos"
EXPORTS  = KIT / "exports"
FAVICON  = KIT / "favicon"
LINKEDIN = KIT / "linkedin"
for d in (EXPORTS, FAVICON, LINKEDIN):
    d.mkdir(parents=True, exist_ok=True)

NAVY = "#0F1E3D"


def png(svg_path, out, width=None, height=None):
    cairosvg.svg2png(url=str(svg_path), write_to=str(out),
                     output_width=width, output_height=height)
    return out


def render(svg_path, width):
    """Render to a PIL image at a target width, preserving aspect."""
    buf = io.BytesIO()
    cairosvg.svg2png(url=str(svg_path), write_to=buf, output_width=width)
    buf.seek(0)
    return Image.open(buf).convert("RGBA")


# --------------------------------------------------------------------------
# 1. Raster exports
# --------------------------------------------------------------------------
EXPORT_SPEC = {
    "auto-skus-primary-light":          [1200, 2400],
    "auto-skus-primary-dark":           [1200, 2400],
    "auto-skus-primary-light-tagline":  [1200, 2400],
    "auto-skus-primary-dark-tagline":   [1200],
    "auto-skus-stacked-light":          [1200],
    "auto-skus-stacked-dark":           [1200],
    # 400 and 600 exist for email signatures: Gmail cannot render SVG, and at
    # signature scale the barcode closes up, so the wordmark is the right mark.
    # 600 is the 2x asset for a ~300px display width.
    "auto-skus-wordmark-light":         [400, 600, 1200],
    "auto-skus-wordmark-dark":          [400, 600, 1200],
    "auto-skus-mono-black":             [1200],
    "auto-skus-mono-white":             [1200],
    "auto-skus-mono-blue":              [1200],
    "auto-skus-amber-accent":           [1200],
    "auto-skus-social-avatar":          [400, 1024],
}

made = []
for name, widths in EXPORT_SPEC.items():
    src = LOGOS / f"{name}.svg"
    for w in widths:
        out = EXPORTS / f"{name}-{w}.png"
        png(src, out, width=w)
        made.append(out)

# --------------------------------------------------------------------------
# 2. Favicon set - square, from the motif-only mark
# --------------------------------------------------------------------------
FAV = LOGOS / "auto-skus-favicon.svg"
for size in (16, 32, 48, 192, 512):
    png(FAV, FAVICON / f"favicon-{size}.png", width=size, height=size)
    made.append(FAVICON / f"favicon-{size}.png")

png(FAV, FAVICON / "apple-touch-icon.png", width=180, height=180)
made.append(FAVICON / "apple-touch-icon.png")

# Multi-resolution .ico for legacy chrome
ico_sizes = [(16, 16), (32, 32), (48, 48)]
base = render(FAV, 256)
base.save(FAVICON / "favicon.ico", format="ICO", sizes=ico_sizes)
made.append(FAVICON / "favicon.ico")

# The SVG favicon ships as-is
(FAVICON / "favicon.svg").write_bytes(FAV.read_bytes())
made.append(FAVICON / "favicon.svg")


# --------------------------------------------------------------------------
# 3. LinkedIn kit
#
# Company page cover is 1128x191. That is an extreme 5.9:1 letterbox, so the
# mark is placed at a fixed proportion of the height rather than the width,
# with generous left padding, which is where LinkedIn's own overlays are not.
# --------------------------------------------------------------------------
COVER_W, COVER_H = 1128, 191


def cover(mark_name, out_name, dark, mark_h_frac=0.42):
    """
    CENTRED, deliberately.

    Two constraints pull in opposite directions on a LinkedIn company cover:

      1. The page's profile logo is overlaid on the LOWER LEFT of the cover, so
         roughly the first 200px is unusable on desktop. A left-aligned mark
         gets partly hidden behind it.
      2. Mobile crops the cover horizontally from the CENTRE, so anything
         pushed to an edge is the first thing cut.

    Centring is the only placement that survives both. It costs a little of the
    asymmetry the mark has on other surfaces; being visible is worth more.
    """
    bg = NAVY if dark else "#FFFFFF"
    src = LOGOS / f"{mark_name}.svg"

    # size the mark by height, not width, because the canvas is a letterbox
    probe = render(src, 1000)
    aspect = probe.width / probe.height

    def compose(scale):
        w, h = COVER_W * scale, COVER_H * scale
        target_h = int(h * mark_h_frac)
        target_w = int(target_h * aspect)
        c = Image.new("RGBA", (w, h), bg)
        m = render(src, target_w)
        c.alpha_composite(m, ((w - m.width) // 2, (h - m.height) // 2))
        return c

    compose(1).convert("RGB").save(LINKEDIN / f"{out_name}.png", "PNG")
    compose(2).convert("RGB").save(LINKEDIN / f"{out_name}@2x.png", "PNG")
    return out_name


cover("auto-skus-primary-light",         "linkedin-cover-light",          dark=False)
cover("auto-skus-primary-dark",          "linkedin-cover-dark",           dark=True)
cover("auto-skus-primary-light-tagline", "linkedin-cover-tagline-light",  dark=False, mark_h_frac=0.60)
cover("auto-skus-primary-dark-tagline",  "linkedin-cover-tagline-dark",   dark=True,  mark_h_frac=0.60)

# Profile image. LinkedIn displays it small and round-cropped on some surfaces,
# so this uses the social avatar (full name, navy plate), never an abbreviation.
for size in (400, 1024):
    png(LOGOS / "auto-skus-social-avatar.svg",
        LINKEDIN / f"linkedin-profile-{size}.png", width=size, height=size)
    made.append(LINKEDIN / f"linkedin-profile-{size}.png")

for p in sorted(LINKEDIN.glob("*.png")):
    if p not in made:
        made.append(p)


if __name__ == "__main__":
    total = 0
    for d, label in ((EXPORTS, "exports"), (FAVICON, "favicon"), (LINKEDIN, "linkedin")):
        files = sorted(d.iterdir())
        print(f"\n{label}/  ({len(files)} files)")
        for f in files:
            print(f"  {f.name:<44} {f.stat().st_size:>8,} bytes")
            total += 1
    print(f"\n{total} files written.")
