from PIL import Image, ImageDraw, ImageFont, ImageFilter
from pathlib import Path
import json, hashlib, textwrap, datetime

ROOT = Path.cwd()
ORIG = ROOT / 'data' / 'generated-assets' / 'top3-originals'
OUT = ROOT / 'data' / 'generated-assets' / 'top3-carousel'
OUT.mkdir(parents=True, exist_ok=True)
FONT_DIR = Path('C:/Windows/Fonts')
REG = str(FONT_DIR / 'segoeui.ttf')
BOLD = str(FONT_DIR / 'segoeuib.ttf')
SEMIBOLD = str(FONT_DIR / 'seguisb.ttf') if (FONT_DIR / 'seguisb.ttf').exists() else BOLD

def font(size, bold=False):
    return ImageFont.truetype(BOLD if bold else REG, size)

products = {
    'JV-TURMERIC500': {
        'name': 'Turmeric with BioPerine',
        'short': 'Turmeric + BioPerine',
        'color': (238, 149, 32),
        'dark': (42, 33, 24),
        'accent': (42, 160, 82),
        'outcome': 'A clearer daily turmeric routine',
        'value': 'High-strength turmeric with absorption support',
        'proof': 'Built around 95% curcuminoids + BioPerine',
        'feature': '475mg curcuminoids per tablet',
        'problem': 'From unclear turmeric labels to clear strength facts',
        'identity': 'For supplement buyers who check the details first',
        'bullets': ['95% curcuminoids', 'BioPerine included', 'Vegetarian + vegan'],
        'offer': 'Choose your pack size',
        'source': 'JV truth + Amazon/Reddit objections'
    },
    'JV-DEFF1000': {
        'name': 'Vitamin D3 Effervescent 1000iu',
        'short': 'Vitamin D3 Effervescent',
        'color': (24, 151, 74),
        'dark': (14, 62, 38),
        'accent': (242, 176, 92),
        'outcome': 'An easy daily vitamin D routine',
        'value': '1000iu D3 in an effervescent format',
        'proof': 'Peach & passion fruit flavour, 20 tablets',
        'feature': 'Food supplement with sweetener',
        'problem': 'From forgotten tablets to a simple fizzy routine',
        'identity': 'For people who want supplements to feel effortless',
        'bullets': ['1000iu Vitamin D3', 'Effervescent format', 'Peach & passion fruit'],
        'offer': 'Simple daily support',
        'source': 'JV truth + competitor-context marketplace evidence'
    },
    'JV-VISISOFT': {
        'name': 'Visisoft Original 10mg',
        'short': 'Visisoft Original',
        'color': (27, 153, 194),
        'dark': (10, 43, 62),
        'accent': (41, 160, 86),
        'outcome': 'A considered eyecare supplement routine',
        'value': 'Eyecare complex including lutein & zeaxanthin',
        'proof': 'Vegetarian and vegan friendly',
        'feature': 'Lutein + zeaxanthin formula',
        'problem': 'From generic eye supplements to a focused eyecare complex',
        'identity': 'For people who are proactive about eye health routines',
        'bullets': ['Lutein included', 'Zeaxanthin included', 'Vegetarian + vegan'],
        'offer': 'Focused eyecare complex',
        'source': 'JV truth + Reddit/category language'
    }
}

image_types = [
    ('01-hero-outcome', 'Hero Outcome Image', 'Outcome first', 'outcome'),
    ('02-offer-value-prop', 'Offer / Value Proposition Image', 'Why buy this format', 'value'),
    ('03-social-proof-trust', 'Social Proof / Trust Image', 'Evidence-backed trust', 'proof'),
    ('04-product-clarity-feature', 'Product Clarity / Feature Image', 'What exactly is it?', 'feature'),
    ('05-problem-solution', 'Problem / Solution Transformation Image', 'Problem to clearer routine', 'problem'),
    ('06-lifestyle-identity', 'Lifestyle / Identity Image', 'Identity and routine', 'identity'),
]

def sha256(path):
    h=hashlib.sha256()
    with open(path,'rb') as f:
        for chunk in iter(lambda:f.read(1024*1024), b''):
            h.update(chunk)
    return h.hexdigest()

def draw_round_rect(draw, box, radius, fill, outline=None, width=1):
    draw.rounded_rectangle(box, radius=radius, fill=fill, outline=outline, width=width)

def wrap_lines(text, fnt, max_width):
    words = text.split()
    lines=[]; line=''
    dummy=Image.new('RGB',(10,10)); d=ImageDraw.Draw(dummy)
    for w in words:
        test=(line+' '+w).strip()
        if d.textbbox((0,0), test, font=fnt)[2] <= max_width:
            line=test
        else:
            if line: lines.append(line)
            line=w
    if line: lines.append(line)
    return lines

def draw_text_block(draw, xy, text, fnt, fill, max_width, line_gap=8):
    x,y=xy
    for line in wrap_lines(text, fnt, max_width):
        draw.text((x,y), line, font=fnt, fill=fill)
        y += fnt.size + line_gap
    return y

def make_bg(base, accent, variant):
    W=H=2000
    img=Image.new('RGB',(W,H),(248,248,245))
    px=img.load()
    for y in range(H):
        for x in range(W):
            t=(x/W*0.55 + y/H*0.45)
            r=int((248*(1-t)+base[0]*t*0.18+255*t*0.08))
            g=int((248*(1-t)+base[1]*t*0.18+255*t*0.08))
            b=int((245*(1-t)+base[2]*t*0.18+255*t*0.08))
            px[x,y]=(min(255,r),min(255,g),min(255,b))
    overlay=Image.new('RGBA',(W,H),(0,0,0,0)); d=ImageDraw.Draw(overlay)
    for i in range(7):
        x=120+i*260; y=150+(i%3)*320
        col=accent if i%2 else base
        d.ellipse((x,y,x+520,y+520), fill=(*col, 20))
    if variant in ['03-social-proof-trust','06-lifestyle-identity']:
        d.rectangle((0,1450,2000,2000), fill=(*base, 30))
    return Image.alpha_composite(img.convert('RGBA'), overlay)

def add_product(canvas, prod_path, x=1030, y=390):
    prod = Image.open(prod_path).convert('RGBA')
    # Product source is pasted at native decoded pixel size. No resizing, no retouching.
    shadow=Image.new('RGBA', canvas.size, (0,0,0,0))
    sd=ImageDraw.Draw(shadow)
    sd.ellipse((x+90,y+1135,x+810,y+1210), fill=(0,0,0,32))
    shadow=shadow.filter(ImageFilter.GaussianBlur(20))
    canvas.alpha_composite(shadow)
    canvas.alpha_composite(prod, (x,y))
    return {'x':x,'y':y,'w':prod.width,'h':prod.height}

def draw_layout(sku, cfg, slug, name, subtitle, key):
    W=H=2000
    bg=make_bg(cfg['color'], cfg['accent'], slug)
    d=ImageDraw.Draw(bg)
    dark=cfg['dark']; color=cfg['color']; accent=cfg['accent']
    # safe content card
    draw_round_rect(d, (105,170,940,1750), 44, (255,255,255,232), (230,230,226,255), 2)
    d.text((165,235), name.upper(), font=font(30, True), fill=color)
    y=310
    y=draw_text_block(d, (165,y), cfg[key], font(76, True), dark, 690, 10)
    y+=30
    y=draw_text_block(d, (165,y), subtitle, font(36), (75,75,75), 680, 8)
    y+=38
    for b in cfg['bullets']:
        draw_round_rect(d, (165,y,830,y+72), 36, (*color, 22), (*color, 90), 2)
        d.ellipse((190,y+25,212,y+47), fill=accent)
        d.text((235,y+17), b, font=font(28, True), fill=dark)
        y+=92
    # evidence chip
    y=max(y+18, 1240)
    draw_round_rect(d, (165,y,845,y+118), 28, (17,24,39,236), None)
    d.text((205,y+22), 'SOURCE-BACKED PDP ANGLE', font=font(22, True), fill=(190,200,230))
    d.text((205,y+60), cfg['source'], font=font(28, True), fill=(255,255,255))
    # product card
    draw_round_rect(d, (980,310,1940,1665), 54, (255,255,255,245), (232,232,228,255), 2)
    placement=add_product(bg, ORIG / f'{sku}-original.jpg', 1010, 380)
    # bottom text band
    draw_round_rect(d, (1020,1705,1900,1848), 36, (*dark, 235), None)
    d.text((1070,1732), cfg['short'], font=font(36, True), fill=(255,255,255))
    d.text((1070,1784), 'Original product image preserved exactly', font=font(24), fill=(220,226,235))
    return bg.convert('RGB'), placement

manifest={'generatedAt': datetime.datetime.utcnow().isoformat()+'Z', 'principle':'The product packshot is never redrawn by AI. Original decoded pixels are pasted at native size into each 2000x2000 PNG so product label/pack identity remains exact.', 'products':{}}
prompts=[]
for sku,cfg in products.items():
    sku_out=OUT/sku; sku_out.mkdir(parents=True, exist_ok=True)
    prod_path=ORIG/f'{sku}-original.jpg'
    source_img=Image.open(prod_path).convert('RGBA')
    manifest['products'][sku]={'sourceImage':str(prod_path),'sourceSha256':sha256(prod_path),'outputs':[]}
    for slug,name,subtitle,key in image_types:
        img, placement=draw_layout(sku,cfg,slug,name,subtitle,key)
        out=sku_out/f'{slug}.png'
        img.save(out, 'PNG', optimize=True)
        # exact pixel verification on pasted source region
        check=Image.open(out).convert('RGBA').crop((placement['x'],placement['y'],placement['x']+placement['w'],placement['y']+placement['h']))
        exact=list(check.getdata()) == list(source_img.getdata())
        rec={'type':name,'path':str(out),'sha256':sha256(out),'productPasteRegion':placement,'productPixelsMatchOriginalDecoded':exact,'size':'2000x2000'}
        manifest['products'][sku]['outputs'].append(rec)
        prompts.append({
            'sku': sku,
            'imageType': name,
            'outputPath': str(out),
            'imagegenPrompt': f"Use case: ads-marketing. Asset type: Shopify PDP carousel image. Create a premium DTC ecommerce {name} for {cfg['name']}. CRITICAL PRODUCT INVARIANT: do not redraw, reinterpret, relabel, resize, crop, or alter the provided original product packshot; preserve every visible label, logo, tablet/tube, color, and pixel exactly. Generate only the surrounding campaign environment, typography layout, and supporting visual treatment. Product truth: {cfg['value']}; {cfg['feature']}. Customer angle: {cfg[key]}. On-image copy must be short, compliant, and not medical. 1:1 square, 2000x2000, mobile-first Shopify carousel, premium clean composition."
        })

(OUT/'top3-carousel-manifest.json').write_text(json.dumps(manifest, indent=2), encoding='utf-8')
(OUT/'top3-imagegen-prompts.json').write_text(json.dumps(prompts, indent=2), encoding='utf-8')
print(json.dumps({
    'outRoot': str(OUT),
    'products': len(products),
    'images': sum(len(v['outputs']) for v in manifest['products'].values()),
    'allProductPixelsExact': all(o['productPixelsMatchOriginalDecoded'] for p in manifest['products'].values() for o in p['outputs'])
}, indent=2))
