from pathlib import Path
from collections import deque
from PIL import Image, ImageFilter, ImageOps, ImageEnhance

ROOT = Path(__file__).resolve().parents[1]
web = ROOT / 'work' / 'assets' / 'web'
out = ROOT / 'work' / 'assets' / 'generated'
out.mkdir(parents=True, exist_ok=True)

# 1) Connected-edge white-background removal for the final product set.
src = web / 'p16_719A1022.jpg'
im = Image.open(src).convert('RGBA')
w, h = im.size
pix = im.load()
# Pure studio background: sampled from four corners.
corners = [pix[0,0], pix[w-1,0], pix[0,h-1], pix[w-1,h-1]]
bg = tuple(sum(c[i] for c in corners)//len(corners) for i in range(3))

def dist(c):
    return sum((c[i]-bg[i])**2 for i in range(3)) ** 0.5

# Flood-fill only background connected to the outer border so pale product interiors are preserved.
visited = bytearray(w*h)
q = deque()
for x in range(w):
    q.append((x,0)); q.append((x,h-1))
for y in range(h):
    q.append((0,y)); q.append((w-1,y))
mask = Image.new('L', (w,h), 0)
mp = mask.load()
threshold = 62
while q:
    x,y = q.popleft()
    if x < 0 or x >= w or y < 0 or y >= h: continue
    idx = y*w+x
    if visited[idx]: continue
    visited[idx] = 1
    r,g,b,a = pix[x,y]
    # background is pale studio paper connected to the border; use a generous threshold
    # to remove the residual cream rectangle and original photo shadow, while preserving
    # non-border product surfaces such as the light gift-box face.
    if a and dist((r,g,b)) <= threshold and min(r,g,b) > 188:
        mp[x,y] = 255
        q.append((x+1,y)); q.append((x-1,y)); q.append((x,y+1)); q.append((x,y-1))

# Expand/soften background mask slightly, then convert to alpha. Product stays opaque.
mask = mask.filter(ImageFilter.MaxFilter(5)).filter(ImageFilter.GaussianBlur(1.2))
alpha = Image.eval(mask, lambda v: 255 - v)
rgba = im.copy()
rgba.putalpha(alpha)
# Crop to non-transparent bbox with safe padding.
bbox = alpha.getbbox()
if bbox:
    pad = 30
    x1,y1,x2,y2 = bbox
    x1=max(0,x1-pad); y1=max(0,y1-pad); x2=min(w,x2+pad); y2=min(h,y2+pad)
    rgba = rgba.crop((x1,y1,x2,y2))
    alpha = alpha.crop((x1,y1,x2,y2))
cutout_path = out / 'closing_product_cutout_v04.png'
rgba.save(cutout_path)

# QA preview on yellow/gold field (not final, just for checking edges).
preview_bg = Image.new('RGBA', rgba.size, (221,204,172,255))
preview = Image.alpha_composite(preview_bg, rgba)
preview.save(out / 'closing_product_cutout_v04_on_gold_preview.png')

# 2) Cup-body Liangzhu motif crop, processed as a subtle warm texture.
pat_src = web / 'p13_719A0999.jpg'
pat = Image.open(pat_src).convert('RGB')
# Claude visual crop: [590, 660, 770, 630]
pat = pat.crop((590, 660, 590+770, 660+630))
# Convert to warm low-contrast texture; remove unrelated color contrast.
pat = ImageOps.grayscale(pat)
pat = ImageOps.autocontrast(pat, cutoff=1)
pat = ImageEnhance.Contrast(pat).enhance(0.9)
pat = ImageEnhance.Brightness(pat).enhance(1.12)
# colorize into dark-ochre lines on transparent-friendly pale field (CSS opacity handles subtlety)
pat_rgb = ImageOps.colorize(pat, black='#7a5128', white='#f5ead7')
# resize to useful tiled/background panel dimensions
pat_rgb = pat_rgb.resize((900, 736), Image.Resampling.LANCZOS)
pat_path = out / 'cup_body_pattern_texture_v04.jpg'
pat_rgb.save(pat_path, quality=92)

print({
    'cutout': str(cutout_path),
    'cutout_size': rgba.size,
    'alpha_extrema': alpha.getextrema(),
    'pattern': str(pat_path),
    'pattern_size': pat_rgb.size,
})
