"""
Fallback cover generator — AutoMate PRO blog images.

Usato SOLO quando Imagen 4 fallisce (billing/quota/errore API) — vedi
OS AutoMatePRO/website/CLAUDE.md STEP 4. Nessuna dipendenza da servizi AI
esterni: solo Pillow. Deterministico, gira identico su Windows e server Linux.

Uso:
    python gen-fallback-cover.py <slug> <icon> --out <path.png>

Icone disponibili (vedi mappatura "Catalogo metafore" in website/CLAUDE.md STEP 4):
    shield network clock chart chat search checklist matrix document flow
"""
import argparse
import hashlib
import random
from pathlib import Path
from PIL import Image, ImageDraw, ImageFilter, ImageFont

W, H = 1200, 630

# Palette coerente con i prompt Imagen (dark indigo + blue/cyan glow)
BG_TOP = (13, 13, 38)      # #0d0d26 quasi-nero indaco
BG_BOTTOM = (24, 24, 64)   # #181840 indaco più chiaro
ACCENT = (90, 150, 255)    # blue
ACCENT_CYAN = (110, 220, 255)
WHITE = (255, 255, 255)

FONT_CANDIDATES = [
    "C:/Windows/Fonts/segoeuisb.ttf",
    "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
    "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
]

ICONS = ["shield", "network", "clock", "chart", "chat", "search", "checklist", "matrix", "document", "flow"]


def load_font(size):
    for path in FONT_CANDIDATES:
        if Path(path).exists():
            return ImageFont.truetype(path, size)
    return ImageFont.load_default()


def blend(c1, c2, t):
    return tuple(int(c1[i] + (c2[i] - c1[i]) * t) for i in range(3))


def vertical_gradient(w, h, top, bottom):
    base = Image.new("RGB", (w, h), top)
    draw = ImageDraw.Draw(base)
    for y in range(h):
        draw.line([(0, y), (w, y)], fill=blend(top, bottom, y / h))
    return base


def add_glow(img, cx, cy, radius, color, intensity=180):
    glow = Image.new("RGBA", img.size, (0, 0, 0, 0))
    gd = ImageDraw.Draw(glow)
    gd.ellipse([cx - radius, cy - radius, cx + radius, cy + radius], fill=color + (intensity,))
    glow = glow.filter(ImageFilter.GaussianBlur(radius // 2))
    img.paste(Image.alpha_composite(img.convert("RGBA"), glow).convert("RGB"), (0, 0))
    return img


def add_dust(draw, w, h, bg, n=35, seed=42):
    rnd = random.Random(seed)
    for _ in range(n):
        x, y = rnd.randint(0, w), rnd.randint(0, h)
        r = rnd.choice([1, 1, 1, 2])
        col = blend(bg, WHITE, rnd.uniform(0.10, 0.28))
        draw.ellipse([x - r, y - r, x + r, y + r], fill=col)


def draw_icon(draw, cx, cy, icon, color, size=100):
    lw = max(4, size // 22)
    s = size
    if icon == "shield":
        pts = [(cx, cy - s), (cx + s * 0.75, cy - s * 0.55), (cx + s * 0.75, cy + s * 0.25),
               (cx, cy + s), (cx - s * 0.75, cy + s * 0.25), (cx - s * 0.75, cy - s * 0.55)]
        draw.polygon(pts, outline=color, width=lw)
        draw.line([(cx - s * 0.32, cy), (cx - s * 0.05, cy + s * 0.3), (cx + s * 0.4, cy - s * 0.35)],
                   fill=color, width=lw, joint="curve")
    elif icon == "network":
        nodes = [(cx, cy - s), (cx - s, cy + s * 0.5), (cx + s, cy + s * 0.5), (cx, cy + s * 0.1)]
        for i in range(len(nodes)):
            for j in range(i + 1, len(nodes)):
                draw.line([nodes[i], nodes[j]], fill=color, width=max(2, lw - 2))
        for (x, y) in nodes:
            r = s * 0.12
            draw.ellipse([x - r, y - r, x + r, y + r], fill=color)
    elif icon == "clock":
        draw.ellipse([cx - s, cy - s, cx + s, cy + s], outline=color, width=lw)
        draw.line([(cx, cy), (cx, cy - s * 0.6)], fill=color, width=lw)
        draw.line([(cx, cy), (cx + s * 0.45, cy + s * 0.15)], fill=color, width=lw)
    elif icon == "chart":
        base_y = cy + s * 0.7
        bars = [0.4, 0.65, 0.55, 0.9, 1.1]
        bw = s * 0.32
        start_x = cx - (len(bars) * bw) / 1.3
        for i, h_ in enumerate(bars):
            x0 = start_x + i * bw * 1.3
            bh = s * h_
            draw.rounded_rectangle([x0, base_y - bh, x0 + bw, base_y], radius=bw * 0.25, outline=color, width=lw)
    elif icon == "chat":
        draw.rounded_rectangle([cx - s, cy - s * 0.75, cx + s * 0.35, cy + s * 0.35],
                                radius=s * 0.28, outline=color, width=lw)
        draw.polygon([(cx - s * 0.55, cy + s * 0.35), (cx - s * 0.2, cy + s * 0.35), (cx - s * 0.55, cy + s * 0.75)],
                     outline=color, width=lw)
        draw.rounded_rectangle([cx - s * 0.15, cy - s * 0.15, cx + s * 0.95, cy + s * 0.85],
                                radius=s * 0.25, outline=ACCENT_CYAN, width=lw)
    elif icon == "search":
        r = s * 0.65
        draw.ellipse([cx - r - s * 0.15, cy - r - s * 0.15, cx + r - s * 0.15, cy + r - s * 0.15],
                     outline=color, width=lw)
        hx, hy = cx + r * 0.55 - s * 0.15, cy + r * 0.55 - s * 0.15
        draw.line([(hx, hy), (cx + s * 0.9, cy + s * 0.9)], fill=color, width=lw + 2)
    elif icon == "checklist":
        draw.rounded_rectangle([cx - s * 0.6, cy - s, cx + s * 0.6, cy + s], radius=s * 0.15, outline=color, width=lw)
        for dy in [-s * 0.5, 0, s * 0.5]:
            y = cy + dy
            draw.ellipse([cx - s * 0.4, y - 8, cx - s * 0.4 + 16, y + 8], outline=color, width=max(2, lw - 2))
            draw.line([(cx - s * 0.15, y), (cx + s * 0.4, y)], fill=color, width=max(2, lw - 2))
    elif icon == "matrix":
        half = s * 0.85
        draw.line([(cx - half, cy), (cx + half, cy)], fill=color, width=lw)
        draw.line([(cx, cy - half), (cx, cy + half)], fill=color, width=lw)
        draw.rectangle([cx - half, cy - half, cx + half, cy + half], outline=color, width=lw)
        r = s * 0.18
        draw.ellipse([cx + half * 0.45 - r, cy - half * 0.45 - r, cx + half * 0.45 + r, cy - half * 0.45 + r],
                     fill=ACCENT_CYAN)
    elif icon == "document":
        draw.rounded_rectangle([cx - s * 0.6, cy - s, cx + s * 0.6, cy + s], radius=s * 0.1, outline=color, width=lw)
        for dy in [-s * 0.5, -s * 0.2, s * 0.1, s * 0.4]:
            draw.line([(cx - s * 0.35, cy + dy), (cx + s * 0.35, cy + dy)], fill=color, width=max(2, lw - 2))
    else:  # flow
        for i, x in enumerate([cx - s, cx, cx + s]):
            r = s * 0.22
            draw.ellipse([x - r, cy - r, x + r, cy + r], outline=color, width=lw)
            if i < 2:
                nx = x + r + (s - r)
                draw.line([(x + r, cy), (nx - r, cy)], fill=color, width=lw)
                draw.polygon([(nx - r - 14, cy - 10), (nx - r - 14, cy + 10), (nx - r, cy)], fill=color)


def generate(out_path, icon="shield", slug=""):
    # Seed derivato dallo slug (non più fisso a 42): stessa identità grafica
    # (palette/font/logica) ma polvere e posizione del glow variano per articolo,
    # cosi' 90 cover della stessa icona non sono visivamente cloni.
    seed = int(hashlib.md5(slug.encode("utf-8")).hexdigest()[:8], 16) if slug else 42
    rnd = random.Random(seed)

    icon = icon if icon in ICONS else "shield"
    img = vertical_gradient(W, H, BG_TOP, BG_BOTTOM)
    cx = W // 2 + rnd.randint(-60, 60)
    cy = H // 2 - 20 + rnd.randint(-40, 40)
    img = add_glow(img, cx, cy, rnd.randint(230, 290), ACCENT, intensity=90)
    img = add_glow(img, cx, cy, rnd.randint(130, 170), ACCENT_CYAN, intensity=70)

    draw = ImageDraw.Draw(img)
    bg_mid = blend(BG_TOP, BG_BOTTOM, 0.5)
    grid_color = blend(bg_mid, WHITE, 0.045)
    for x in range(0, W, 100):
        draw.line([(x, 0), (x, H)], fill=grid_color, width=1)
    for y in range(0, H, 100):
        draw.line([(0, y), (W, y)], fill=grid_color, width=1)

    add_dust(draw, W, H, bg_mid, n=rnd.randint(28, 45), seed=seed)
    draw_icon(draw, W // 2, H // 2 - 20, icon, ACCENT)
    draw.text((40, H - 50), "AUTOMATE PRO", font=load_font(22), fill=blend(bg_mid, WHITE, 0.55))

    Path(out_path).parent.mkdir(parents=True, exist_ok=True)
    img.save(out_path)
    print("Saved:", out_path)


if __name__ == "__main__":
    p = argparse.ArgumentParser()
    p.add_argument("slug")
    p.add_argument("icon", nargs="?", default="shield", choices=ICONS)
    p.add_argument("--out", required=True, help="path completo del PNG di output")
    args = p.parse_args()
    generate(args.out, args.icon, slug=args.slug)
