#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Generator desain feed Instagram The Skin Code Clinic — 1080x1350, gaya mengikuti
desain yang sudah tayang (tsc_design_* dan tsc_ig_baru_*).

Palet diambil dari desain tayang + tombol situs TSC:
  latar terang #F7F8FA · navy resmi #0F2557 · navy slate (desain gelap) #2A3549
  aksen biru muda #A9C7EC / #2563EB · aksen kuning #E9C64A

Isi slide ditulis dari artikel TSC sendiri (tidak mengarang klaim medis).
"""
from PIL import Image, ImageDraw, ImageFont
import os

W, H = 1080, 1350
WS = "/home/mantapman/.hermes/profiles/atun/workspace"
ASET = f"{WS}/tsc_aset"

BG_TERANG = "#F7F8FA"
NAVY = "#0F2557"
NAVY_DEEP = "#1B2436"
BIRU_MUDA = "#A9C7EC"
BIRU_AKSEN = "#2563EB"
KUNING = "#E9C64A"
ABU_LEMBUT = "#5A6B85"
ABU_TUBUH = "#46556B"

F_POPPINS = "/home/mantapman/.local/share/fonts/Poppins-{w}.ttf"
F_PLAYFAIR = "/home/mantapman/.local/share/fonts/tsc/playfair.ttf"
F_PLAYFAIR_I = "/home/mantapman/.local/share/fonts/tsc/playfairsc.ttf"

MARGIN = 90
LEBAR = W - 2 * MARGIN


def font(nama="Poppins-Regular", size=30):
    if nama.startswith("Playfair"):
        path = F_PLAYFAIR_I if nama.endswith("Italic") else F_PLAYFAIR
        f = ImageFont.truetype(path, size)
        try:
            f.set_variation_by_name("Bold" if "Bold" in nama else "SemiBold")
        except Exception:
            pass
        return f
    berat = nama.split("-")[-1]
    path = F_POPPINS.format(w=berat)
    if not os.path.exists(path):
        path = "/home/mantapman/.local/share/fonts/Poppins-Regular.ttf"
    return ImageFont.truetype(path, size)


# ───────────────────────── logo (transparan) ─────────────────────────

def _alpha_dari_crop(path_crop, warna="#0F2557"):
    im = Image.open(path_crop).convert("RGB")
    out = Image.new("RGBA", im.size)
    px_in, px_out = im.load(), out.load()
    rgb = tuple(int(warna[i:i + 2], 16) for i in (1, 3, 5))
    for y in range(im.size[1]):
        for x in range(im.size[0]):
            r, g, b = px_in[x, y]
            lum = 0.299 * r + 0.587 * g + 0.114 * b
            a = int(max(0.0, min(255.0, (246 - lum) * 1.6)))
            px_out[x, y] = (rgb[0], rgb[1], rgb[2], a)
    return out


def logo(navy=True, lebar=None):
    """Logo resmi TSC transparan (navy atau putih).

    Sumber utama: tsc_aset/logo_bos_{navy,putih}.png — hasil ekstraksi dari file logo
    resmi yang dikirim Bos 14 Okt 2026 (tagline «aesthetic»). Kalau aset itu tidak ada,
    jatuh ke crop lama dari desain tayang (tagline lama masih «esthetic»).
    """
    sumber = f"{ASET}/logo_bos_{'navy' if navy else 'putih'}.png"
    if not os.path.exists(sumber):
        p = f"{ASET}/logo_{'navy' if navy else 'putih'}.png"
        if not os.path.exists(p):
            dasar = _alpha_dari_crop(f"{ASET}/logo_gelap_di_putih_besar.png")
            if not navy:
                px = dasar.load()
                for y in range(dasar.size[1]):
                    for x in range(dasar.size[0]):
                        _, _, _, a = px[x, y]
                        px[x, y] = (255, 255, 255, a)
            dasar.save(p)
        sumber = p
    im = Image.open(sumber).convert("RGBA")
    if lebar:
        im = im.resize((lebar, max(1, round(im.size[1] * lebar / im.size[0]))), Image.LANCZOS)
    return im


# ───────────────────────── utilitas teks/gambar ─────────────────────────

def lipat(draw, teks, f, maks_lebar):
    baris = []
    for paragraf in teks.split("\n"):
        kata, kini = paragraf.split(), ""
        for k in kata:
            coba = f"{kini} {k}".strip()
            if draw.textlength(coba, font=f) <= maks_lebar or not kini:
                kini = coba
            else:
                baris.append(kini)
                kini = k
        baris.append(kini)
    return baris


def tinggi_teks(draw, teks, f, maks_lebar, spasi=12):
    return len(lipat(draw, teks, f, maks_lebar)) * (f.size + spasi)


def tulis(draw, teks, f, x, y, maks_lebar, warna, spasi=12, tengah=False):
    for baris in lipat(draw, teks, f, maks_lebar):
        xx = x + (maks_lebar - draw.textlength(baris, font=f)) / 2 if tengah else x
        draw.text((xx, y), baris, font=f, fill=warna)
        y += f.size + spasi
    return y


def centang_bulat(draw, cx, cy, r=15, warna=BIRU_AKSEN):
    draw.ellipse([cx - r, cy - r, cx + r, cy + r], outline=warna, width=3)
    draw.line([cx - r * 0.42, cy + r * 0.05, cx - r * 0.1, cy + r * 0.42], fill=warna, width=3)
    draw.line([cx - r * 0.12, cy + r * 0.42, cx + r * 0.45, cy - r * 0.38], fill=warna, width=3)


def globe(draw, cx, cy, r, warna):
    draw.ellipse([cx - r, cy - r, cx + r, cy + r], outline=warna, width=2)
    draw.ellipse([cx - r * 0.45, cy - r, cx + r * 0.45, cy + r], outline=warna, width=2)
    draw.line([cx - r, cy, cx + r, cy], fill=warna, width=2)


def lengkung(draw, geser=0, warna="#DCE8F8", tebal=3):
    draw.arc([760 + geser, -320, 1400 + geser, 760], start=140, end=250, fill=warna, width=tebal)
    draw.arc([760 + geser, 380, 1400 + geser, 1500], start=110, end=215, fill=warna, width=tebal)


def gradasi(warna_atas, warna_bawah):
    im = Image.new("RGB", (W, H), warna_atas)
    d = ImageDraw.Draw(im)
    atas = tuple(int(warna_atas[i:i + 2], 16) for i in (1, 3, 5))
    bawah = tuple(int(warna_bawah[i:i + 2], 16) for i in (1, 3, 5))
    for y in range(H):
        t = y / H
        d.line([(0, y), (W, y)], fill=tuple(int(atas[i] + (bawah[i] - atas[i]) * t) for i in range(3)))
    return im


def _kepala(draw, putih=False, counter=None, kicker=None):
    lg = logo(navy=not putih, lebar=205)
    draw.im.paste(lg, (MARGIN, 76), lg)
    if kicker:
        draw.text((MARGIN, 76 + lg.height + 12), kicker.upper(), font=font("Poppins-SemiBold", 23),
                  fill="#C9D6E8" if putih else ABU_LEMBUT)
    if counter:
        f = font("Poppins-Regular", 26)
        tw = draw.textlength(counter, font=f)
        draw.text((W - MARGIN - tw, 120), counter, font=f, fill="#93A3B8" if not putih else "#8FA0B8")


def _kaki(draw, putih=False):
    warna = "#8A98AE" if not putih else "#B9C6DA"
    globe(draw, MARGIN + 11, H - 90, 11, warna)
    draw.text((MARGIN + 32, H - 103), "www.theskincodeclinic.com", font=font("Poppins-Regular", 26), fill=warna)
    f2 = font("Poppins-SemiBold", 26)
    ig = "@theskincode_clinic"   # username Repliz = theskincode_clinic (desain lama salah tulis: cllinic)
    draw.text((W - MARGIN - draw.textlength(ig, font=f2), H - 103), ig, font=f2, fill=warna)


def _pil_cta(draw, x, y, teks, lebar=580, tinggi=98, fill=NAVY, teks_warna="#FFFFFF"):
    draw.rounded_rectangle([(x, y), (x + lebar, y + tinggi)], radius=tinggi // 2, fill=fill)
    ix, iy = x + 40, y + 30
    draw.rounded_rectangle([(ix, iy), (ix + 38, iy + 38)], radius=8, outline=teks_warna, width=3)
    draw.line([(ix, iy + 12), (ix + 38, iy + 12)], fill=teks_warna, width=3)
    draw.line([(ix + 11, iy - 6), (ix + 11, iy + 5)], fill=teks_warna, width=3)
    draw.line([(ix + 27, iy - 6), (ix + 27, iy + 5)], fill=teks_warna, width=3)
    f = font("Poppins-SemiBold", 30)
    baris = lipat(draw, teks, f, lebar - 140)
    tulis(draw, teks, f, x + 104, y + (tinggi - len(baris) * (f.size + 6)) / 2, lebar - 140, teks_warna, spasi=6)


# ───────────────────────── corak slide ─────────────────────────

def kotak_catatan(draw, teks, x, y, lebar, skala=1.0):
    """Strip biru muda untuk catatan/peringatan."""
    f = font("Poppins-Regular", max(22, int(28 * skala)))
    baris = lipat(draw, teks, f, lebar - 70)
    tinggi = len(baris) * (f.size + 9) + 44
    draw.rounded_rectangle([(x, y), (x + lebar, y + tinggi)], radius=16, fill="#E8F0FB")
    draw.rounded_rectangle([(x, y), (x + 7, y + tinggi)], radius=4, fill=BIRU_AKSEN)
    tulis(draw, teks, f, x + 32, y + 20, lebar - 70, "#24405F", spasi=9)
    return y + tinggi


def daftar_isi(draw, item, x, y, lebar, skala=1.0):
    """Daftar bernomor untuk cover (pengisi ruang bawah)."""
    f = font("Poppins-SemiBold", max(22, int(31 * skala)))
    fno = font("Poppins-Bold", max(20, int(25 * skala)))
    for i, it in enumerate(item, 1):
        cy = y + f.size / 2 + 4
        draw.ellipse([x, cy - 26, x + 52, cy + 26], fill="#EAF1FB")
        no = str(i)
        draw.text((x + 26 - draw.textlength(no, font=fno) / 2, cy - fno.size / 2 - 3), no, font=fno, fill=BIRU_AKSEN)
        yy = tulis(draw, it, f, x + 76, y, lebar - 76, NAVY, spasi=8)
        y = yy + 24
    return y


def _corak_terang(draw, data, s, hanya_ukur=True):
    """Hitung/gambar blok isi slide terang pada skala s; kembalikan y akhir."""
    y = 300
    f_judul = font("Playfair-Bold", max(48, int(data.get("ukuran_judul", 92) * max(s, 0.85))))
    while tinggi_teks(draw, data["judul"], f_judul, LEBAR - 60, 6) > data.get("tinggi_judul_maks", 300) and f_judul.size > 48:
        f_judul = font("Playfair-Bold", f_judul.size - 4)
    if not hanya_ukur:
        tulis(draw, data["judul"], f_judul, MARGIN, y, LEBAR - 60, NAVY, spasi=6)
    y += tinggi_teks(draw, data["judul"], f_judul, LEBAR - 60, 6) + 14

    if data.get("subjudul"):
        f_sub = font("Poppins-Light", max(24, int(34 * s)))
        if not hanya_ukur:
            tulis(draw, data["subjudul"], f_sub, MARGIN, y, LEBAR - 100, ABU_LEMBUT, spasi=8)
        y += tinggi_teks(draw, data["subjudul"], f_sub, LEBAR - 100, 8) + 28

    if not hanya_ukur:
        yd = y + 22
        draw.line([(MARGIN, yd), (MARGIN + 150, yd)], fill=BIRU_MUDA, width=4)
        draw.polygon([(MARGIN + 191, yd), (MARGIN + 182, yd - 9), (MARGIN + 173, yd), (MARGIN + 182, yd + 9)],
                     fill=BIRU_MUDA)
    y += 44  # divider
    if data.get("lead"):
        f_lead = font("Poppins-SemiBold", max(24, int(35 * s)))
        if not hanya_ukur:
            tulis(draw, data["lead"], f_lead, MARGIN, y, LEBAR, "#14264A", spasi=10)
        y += tinggi_teks(draw, data["lead"], f_lead, LEBAR, 10) + 18
    if data.get("paragraf"):
        f_par = font("Poppins-Regular", max(22, int(31 * s)))
        if not hanya_ukur:
            tulis(draw, data["paragraf"], f_par, MARGIN, y, LEBAR, ABU_TUBUH, spasi=14)
        y += tinggi_teks(draw, data["paragraf"], f_par, LEBAR, 14) + 16
    if data.get("poin"):
        f_poin = font("Poppins-Regular", max(22, int(30 * s)))
        for p in data["poin"]:
            if not hanya_ukur:
                h = len(lipat(draw, p, f_poin, LEBAR - 80))
                centang_bulat(draw, MARGIN + 17, y + (h * (f_poin.size + 10)) / 2 - 6, 15)
                tulis(draw, p, f_poin, MARGIN + 62, y, LEBAR - 80, "#2C3A4E", spasi=10)
            y += tinggi_teks(draw, p, f_poin, LEBAR - 80, 10) + 22
    if data.get("catatan"):
        if not hanya_ukur:
            y = kotak_catatan(draw, data["catatan"], MARGIN, y + 6, LEBAR, s)
        else:
            y += 18 + len(lipat(draw, data["catatan"], font("Poppins-Regular", max(22, int(28 * s))), LEBAR - 70)) * (
                max(22, int(28 * s)) + 9) + 44
    if data.get("daftar_isi"):
        y += 30
        if not hanya_ukur:
            y = daftar_isi(draw, data["daftar_isi"], MARGIN, y, LEBAR, s)
        else:
            for it in data["daftar_isi"]:
                y += tinggi_teks(draw, it, font("Poppins-SemiBold", max(22, int(31 * s))), LEBAR - 76, 8) + 24
    return y


def slide_terang(data):
    im = Image.new("RGB", (W, H), BG_TERANG)
    d = ImageDraw.Draw(im)
    d.im = im
    lengkung(d)
    _kepala(d, putih=False, counter=data.get("counter"), kicker=data.get("kicker"))

    batas = 1030 if data.get("cta_pil", True) else 1150
    s = 0.76
    for s in (1.0, 0.95, 0.9, 0.85, 0.8, 0.76):
        if _corak_terang(d, data, s) <= batas:
            break
    y = _corak_terang(d, data, s, hanya_ukur=False)
    if y > batas:
        print(f"⚠️  slide meluber: ujung konten y={y:.0f} > batas {batas} (skala {s}) — perpendek teks")

    if data.get("cta_pil", True):
        _pil_cta(d, MARGIN, max(min(y + 30, batas + 40), 1085), data.get("cta_teks", "Hubungi kami untuk jadwalkan konsultasi"))
    _kaki(d, putih=False)
    return im


def slide_gelap(data):
    im = gradasi("#2A3549", "#1B2436")
    d = ImageDraw.Draw(im)
    d.im = im
    lengkung(d, geser=-140, warna="#3C4C68", tebal=3)
    _kepala(d, putih=True, counter=data.get("counter"), kicker=data.get("kicker"))

    y = 470
    f_judul = font("Playfair-BoldItalic", data.get("ukuran_judul", 86))
    while tinggi_teks(d, data["judul"], f_judul, LEBAR - 130, 10) > 470 and f_judul.size > 46:
        f_judul = font("Playfair-BoldItalic", f_judul.size - 4)
    y = tulis(d, data["judul"], f_judul, MARGIN, y, LEBAR - 130, "#FFFFFF", spasi=10)
    d.line([(MARGIN, y + 22), (MARGIN + 120, y + 22)], fill=KUNING, width=5)
    y += 62
    if data.get("lead"):
        tulis(d, data["lead"], font("Poppins-Regular", 34), MARGIN, y, LEBAR - 130, "#C8D4E6", spasi=12)
    _kaki(d, putih=True)
    return im


def slide_cta(data):
    im = gradasi("#0F2557", "#20407F")
    d = ImageDraw.Draw(im)
    d.im = im
    lengkung(d, warna="#2C4470", tebal=4)
    _kepala(d, putih=True)

    y = tulis(d, data["judul"], font("Playfair-Bold", 88), MARGIN, 420, LEBAR - 60, "#FFFFFF", spasi=8)
    d.line([(MARGIN, y + 24), (MARGIN + 140, y + 24)], fill=KUNING, width=5)
    y += 72
    y = tulis(d, data["paragraf"], font("Poppins-Regular", 33), MARGIN, y, LEBAR - 80, "#C8D4E6", spasi=14) + 40

    y = min(y, H - 310)
    _pil_cta(d, MARGIN, y, "Chat WhatsApp 0851-1744-4417", lebar=690, tinggi=104,
             fill="#FFFFFF", teks_warna=NAVY)
    tulis(d, "Konsultasi bersama dokter spesialis kulit, kelamin, dan estetika.",
          font("Poppins-Regular", 27), MARGIN, y + 128, LEBAR - 60, "#9FB0C9", spasi=8)
    _kaki(d, putih=True)
    return im


STYLE = {"terang": slide_terang, "gelap": slide_gelap, "cta": slide_cta}


def render(data, path):
    im = STYLE[data.get("style", "terang")](data)
    im.save(path, quality=92)
    return path
