"""
Sprockett's community cover + welcome hero composites.
Source: welcome to the party.png (1280x720)
Outputs:
  - cover-1920x1080.jpg  (Kanamé group cover)
  - welcome-hero-1600x900.jpg  (welcome post hero)
  - _cover-preview.png  (with light/dark mode surround test)

Design principles:
  - Full bleed (no transparent edges) — works on light + dark mode
  - Bottom gradient panel for text legibility
  - Subtle 4-edge vignette
  - Outfit ExtraBold headline, DM Sans Medium sub
  - Sprocketts paw mark accent
"""
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import os

OUT = os.path.dirname(os.path.abspath(__file__))
SRC = os.path.join(OUT, "welcome to the party.png")

BLUE = (25, 116, 206, 255)
WHITE = (255, 255, 255, 255)

OUTFIT = os.path.join(OUT, "fonts", "Outfit-ExtraBold.ttf")
DMSANS = os.path.join(OUT, "fonts", "DMSans-Medium.ttf")


def draw_paw(draw, cx, cy, scale, color):
    """5-piece paw — same shape language as the favicon."""
    pad_w = int(scale * 0.95); pad_h = int(scale * 0.78)
    pad_top = cy + int(scale * 0.10)
    draw.ellipse([cx - pad_w // 2, pad_top, cx + pad_w // 2, pad_top + pad_h], fill=color)
    toe_w = int(scale * 0.40); toe_h = int(scale * 0.50)
    inner_dx = int(scale * 0.22); inner_y = cy - int(scale * 0.55)
    draw.ellipse([cx - inner_dx - toe_w // 2, inner_y, cx - inner_dx + toe_w // 2, inner_y + toe_h], fill=color)
    draw.ellipse([cx + inner_dx - toe_w // 2, inner_y, cx + inner_dx + toe_w // 2, inner_y + toe_h], fill=color)
    outer_w = int(scale * 0.36); outer_h = int(scale * 0.46)
    outer_dx = int(scale * 0.62); outer_y = cy - int(scale * 0.32)
    draw.ellipse([cx - outer_dx - outer_w // 2, outer_y, cx - outer_dx + outer_w // 2, outer_y + outer_h], fill=color)
    draw.ellipse([cx + outer_dx - outer_w // 2, outer_y, cx + outer_dx + outer_w // 2, outer_y + outer_h], fill=color)


def vertical_gradient(size, top_alpha, bottom_alpha, color=(0, 0, 0)):
    """Vertical gradient (alpha varies top→bottom)."""
    w, h = size
    grad = Image.new("RGBA", (1, h))
    for y in range(h):
        t = y / max(h - 1, 1)
        # smoother ease (cubic-ish) so the panel doesn't have a hard top edge
        t_eased = t * t * (3 - 2 * t)
        a = int(top_alpha + (bottom_alpha - top_alpha) * t_eased)
        grad.putpixel((0, y), color + (a,))
    return grad.resize((w, h), Image.BILINEAR)


def vignette(size, strength=0.18):
    """Soft radial darken on the four edges."""
    w, h = size
    vig = Image.new("RGBA", (w, h), (0, 0, 0, 0))
    d = ImageDraw.Draw(vig)
    # Draw a big white-to-transparent radial then invert via overlay; simpler:
    # Build by stacking 4 directional gradients at low strength.
    edge_alpha = int(255 * strength)
    # Top
    top = vertical_gradient((w, int(h * 0.18)), edge_alpha, 0)
    vig.alpha_composite(top, (0, 0))
    # Bottom (covered by text panel anyway, but keep small for symmetry on dark mode)
    bot = vertical_gradient((w, int(h * 0.18)), 0, edge_alpha)
    vig.alpha_composite(bot, (0, h - bot.height))
    # Left (rotate vertical gradient 90deg)
    left = vertical_gradient((h, int(w * 0.10)), edge_alpha, 0).rotate(-90, expand=True)
    vig.alpha_composite(left, (0, 0))
    # Right
    right = vertical_gradient((h, int(w * 0.10)), 0, edge_alpha).rotate(-90, expand=True)
    vig.alpha_composite(right, (w - right.width, 0))
    return vig


def render_cover(src_img, out_w, out_h, headline, subline, headline_px, sub_px,
                 paw_px, panel_height_pct=0.50, text_pad_pct=0.05):
    # 1. Resize source to fill (preserve aspect, crop center if needed)
    src_w, src_h = src_img.size
    scale = max(out_w / src_w, out_h / src_h)
    new_w, new_h = int(src_w * scale), int(src_h * scale)
    img = src_img.resize((new_w, new_h), Image.LANCZOS).convert("RGBA")
    # Center crop
    left = (new_w - out_w) // 2
    top = (new_h - out_h) // 2
    img = img.crop((left, top, left + out_w, top + out_h))

    # 2. Bottom gradient panel for text legibility
    panel_h = int(out_h * panel_height_pct)
    panel = vertical_gradient((out_w, panel_h), 0, int(255 * 0.78))
    img.alpha_composite(panel, (0, out_h - panel_h))

    # 3. Subtle 4-edge vignette (mode-agnostic edge softening)
    img.alpha_composite(vignette((out_w, out_h), strength=0.16))

    # 4. Text + paw mark (bottom-left)
    d = ImageDraw.Draw(img)
    pad = int(out_w * text_pad_pct)
    # Paw — small white mark above the headline
    paw_size = paw_px
    paw_y_offset = headline_px + sub_px + int(headline_px * 0.55)  # vertical room above headline
    paw_cx = pad + paw_size // 2
    paw_cy = out_h - paw_y_offset - paw_size  # baseline above headline
    draw_paw(d, paw_cx, paw_cy + paw_size // 2, paw_size, (255, 255, 255, 240))

    # Headline
    h_font = ImageFont.truetype(OUTFIT, headline_px)
    s_font = ImageFont.truetype(DMSANS, sub_px)
    try:
        s_font.set_variation_by_name("Medium")
    except Exception:
        pass

    # Sub line — wrap to width (~70% of frame)
    max_text_w = int(out_w * 0.70)
    sub_lines = wrap_text(subline, s_font, max_text_w, d)

    # Compute heights
    h_bbox = h_font.getbbox(headline)
    h_h = h_bbox[3] - h_bbox[1]
    line_h = sub_px * 1.30
    sub_total_h = int(line_h * len(sub_lines))

    # Vertical layout from bottom
    bottom_pad = int(out_h * 0.07)
    sub_y = out_h - bottom_pad - sub_total_h
    head_y = sub_y - h_h - int(headline_px * 0.18)

    # Headline shadow + fill
    d.text((pad + 2, head_y + 3), headline, font=h_font, fill=(0, 0, 0, 120))
    d.text((pad, head_y), headline, font=h_font, fill=WHITE)

    # Sub lines
    for i, line in enumerate(sub_lines):
        ly = sub_y + int(i * line_h)
        d.text((pad + 1, ly + 2), line, font=s_font, fill=(0, 0, 0, 110))
        d.text((pad, ly), line, font=s_font, fill=(255, 255, 255, 235))

    return img


def wrap_text(text, font, max_w, draw):
    words = text.split()
    lines, cur = [], ""
    for w in words:
        trial = (cur + " " + w).strip()
        bbox = font.getbbox(trial)
        if bbox[2] - bbox[0] <= max_w:
            cur = trial
        else:
            if cur:
                lines.append(cur)
            cur = w
    if cur:
        lines.append(cur)
    return lines


HEADLINE = "The Dog House"
SUBLINE  = "Welcome to the Sprockett's pack — book, manage, stay in the loop."

src = Image.open(SRC).convert("RGBA")

# 1920×1080 group cover
cover = render_cover(src, 1920, 1080, HEADLINE, SUBLINE,
                     headline_px=128, sub_px=38, paw_px=68)
cover.convert("RGB").save(os.path.join(OUT, "cover-1920x1080.jpg"),
                          "JPEG", quality=92, optimize=True, progressive=True)

# 1600×900 welcome hero (same comp, slightly smaller)
hero = render_cover(src, 1600, 900, HEADLINE, SUBLINE,
                    headline_px=108, sub_px=32, paw_px=58)
hero.convert("RGB").save(os.path.join(OUT, "welcome-hero-1600x900.jpg"),
                         "JPEG", quality=92, optimize=True, progressive=True)

# Mode-test preview: same cover shown on light + dark surrounds
prev = Image.new("RGB", (2000, 1300), (250, 250, 250))
pd = ImageDraw.Draw(prev)
# light bg top
prev.paste(cover.resize((900, 506)), (60, 60))
# dark bg bottom
pd.rectangle([0, 660, 2000, 1300], fill=(20, 22, 30))
prev.paste(cover.resize((900, 506)), (60, 720))
# labels
lbl = ImageFont.truetype(DMSANS, 22)
pd.text((1010, 80), "LIGHT MODE SURROUND", font=lbl, fill=(80, 80, 80))
pd.text((1010, 740), "DARK MODE SURROUND", font=lbl, fill=(220, 220, 220))
prev.save(os.path.join(OUT, "_cover-preview.png"), optimize=True)

print("Built:")
for f in ["cover-1920x1080.jpg", "welcome-hero-1600x900.jpg", "_cover-preview.png"]:
    p = os.path.join(OUT, f)
    print(f"  {f}  ({os.path.getsize(p)//1024} KB)")
