#!/usr/bin/env python3
import argparse, math, random
from PIL import Image, ImageDraw, ImageFilter

def draw_crab(draw, cx, cy, scale, body_color, claw_color):
    bw = int(90*scale); bh = int(60*scale)
    draw.ellipse([cx-bw, cy-bh, cx+bw, cy+bh], fill=body_color, outline=(255,255,255,180), width=2)
    sh = int(40*scale)
    draw.ellipse([cx-int(70*scale), cy-sh, cx+int(70*scale), cy+sh], fill=body_color, outline=(255,255,255,120), width=2)
    for side in [-1, 1]:
        px = cx + side*int(100*scale)
        py = cy - int(40*scale)
        pw = int(35*scale); ph = int(25*scale)
        draw.ellipse([px-pw, py-ph, px+pw, py+ph], fill=claw_color, outline=(255,255,255,180), width=2)
        tipx = px + side*int(20*scale)
        draw.line([(px, py-ph), (tipx, py-ph-int(20*scale))], fill=claw_color, width=int(4*scale))
        draw.line([(px, py-ph), (tipx-side*int(15*scale), py-ph-int(15*scale))], fill=claw_color, width=int(4*scale))
        armx = cx + side*int(75*scale)
        draw.line([(armx, cy), (px, py)], fill=body_color, width=int(8*scale))
    for i in range(3):
        for side in [-1, 1]:
            angle = math.radians(150 + i*25) if side == -1 else math.radians(30 - i*25)
            lx = cx + side*int(65*scale)
            ly = cy + int((15 + i*15)*scale)
            ex = lx + int(math.cos(angle)*50*scale)
            ey = ly + int(math.sin(angle)*50*scale)
            draw.line([(lx, ly), (ex, ey)], fill=body_color, width=int(3*scale))
    for side in [-1, 1]:
        sx = cx + side*int(25*scale)
        sy = cy - int(55*scale)
        draw.line([(sx, cy - int(40*scale)), (sx, sy)], fill=body_color, width=int(3*scale))
        draw.ellipse([sx-int(7*scale), sy-int(7*scale), sx+int(7*scale), sy+int(7*scale)], fill=(255,255,255,240))
        draw.ellipse([sx-int(3*scale), sy-int(3*scale), sx+int(3*scale), sy+int(3*scale)], fill=(0,0,0,255))

def bent_grid(draw, w, h, intensity, rng):
    for i in range(0, w, 20):
        pts = []
        for y in range(0, h+1, 10):
            dx = int(rng.gauss(0, intensity*5))
            pts.append((i+dx, y))
        if len(pts) > 1:
            draw.line(pts, fill=(0, 255, 255, int(100*intensity)), width=2)
    for j in range(0, h, 20):
        pts = []
        for x in range(0, w+1, 10):
            dy = int(rng.gauss(0, intensity*5))
            pts.append((x, j+dy))
        if len(pts) > 1:
            draw.line(pts, fill=(255, 0, 255, int(85*intensity)), width=2)

def chromatic_ghosts(base, intensity, rng):
    off = int(6 * intensity)
    r , g, b, a = base.split()
    zero = Image.new('L', base.size, 0)
    red_layer = Image.merge('RGBA', (r, zero, zero, a))
    blue_layer = Image.merge('RGBA', (zero, zero, b, a))
    out = base.copy()
    out.paste(red_layer, (off, 0), red_layer)
    out.paste(blue_layer, (-off, 0), blue_layer)
    for _ in range(int(3*intensity)):
        ghost = base.copy().filter(ImageFilter.GaussianBlur(radius=4))
        ghost.putalpha(Image.new('L', base.size, 40))
        dx = rng.randint(-12, 12)
        dy = rng.randint(-12, 12)
        out.paste(ghost, (dx, dy), ghost)
    return out

def scanlines_and_pixels(draw, w, h, intensity, rng, glow_color):
    for y in range(0, h, 4):
        draw.line([(0, y), (w, y)], fill=(0, 0, 0, int(40*intensity)), width=2)
    for _ in range(int(150*intensity)):
        px = rng.randint(0, w-1)
        py = rng.randint(0, h-1)
        sz = rng.randint(1, 3)
        c = rng.choice([glow_color, (255,255,255,200), (255,0,255,180)])
        draw.rectangle([px, py, px+sz, py+sz], fill=c)

def generate_crab_pfp(size=512, body_color=(180, 40, 60, 240), claw_color=(220, 50, 220, 240), glow_color=(0, 255, 255, 200), intensity=1.0, seed=42, outpath=None):
    rng = random.Random(seed)
    img = Image.new('RGBA', (size, size), (5, 5, 15, 255))
    draw = ImageDraw.Draw(img)
    # grid moved after ghosts
    cx, cy = size//2, size//2 + int(20*(size/512))
    scale = size / 512
    draw_crab(draw, cx, cy, scale, body_color, claw_color)
    img = chromatic_ghosts(img, intensity, rng)
    draw2 = ImageDraw.Draw(img)
    bent_grid(draw2, size, size, intensity, rng)
    scanlines_and_pixels(draw2, size, size, intensity, rng, glow_color)
    path = outpath or f'/tmp/crab_pfp_{seed}.png'
    img.convert('RGB').save(path)
    return path

if __name__ == '__main__':
    p = argparse.ArgumentParser(description='Crab PFP generator v4 - fever dream style')
    p.add_argument('--size', type=int, default=512)
    p.add_argument('--seed', type=int, default=42)
    p.add_argument('--intensity', type=float, default=1.0)
    p.add_argument('--out', type=str, default=None)
    args = p.parse_args()
    path = generate_crab_pfp(size=args.size, seed=args.seed, intensity=args.intensity, outpath=args.out)
    print(f'Saved: {path}')
