from PIL import Image, ImageDraw, ImageFont
import math

W, H = 1200, 630

# ── fonts ─────────────────────────────────────────────────────────────────────
def F(path, size):
    try: return ImageFont.truetype(path, size)
    except: return ImageFont.load_default()

BD = "C:/Windows/Fonts/arialbd.ttf"
RG = "C:/Windows/Fonts/arial.ttf"
f_pmi  = F(BD, 80)
f_ops  = F(RG, 17)
f_lbl  = F(BD, 19)
f_icon = F(BD, 13)

def rgba(h, a=255):
    h = h.lstrip("#")
    return tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) + (a,)

# ── base image ────────────────────────────────────────────────────────────────
img = Image.new("RGBA", (W, H), rgba("#0f0f2a"))

# dot grid
gd = ImageDraw.Draw(img)
for gx in range(0, W+1, 48):
    for gy in range(0, H+1, 48):
        gd.ellipse([gx-1.5, gy-1.5, gx+1.5, gy+1.5], fill=(255,255,255,18))

# ── center PMI glow ───────────────────────────────────────────────────────────
cx, cy = W//2, H//2
for r, a in [(160,4),(120,9),(90,16),(70,28),(55,40)]:
    gl = Image.new("RGBA", (W, H), (0,0,0,0))
    ImageDraw.Draw(gl).ellipse([cx-r, cy-r, cx+r, cy+r], fill=(99,102,241,a))
    img = Image.alpha_composite(img, gl)

draw = ImageDraw.Draw(img)

# ── agents config ─────────────────────────────────────────────────────────────
#  gaze_dx/dy = direction pupils shift to "look at center"
agents = [
    {"label":"Ricerca Web",     "icon":"SEARCH", "x":200,   "y":155,   "col":"#38bdf8",
     "hair":"#38bdf8", "gaze_dx":+4, "gaze_dy":+3, "icon_sym":"⌕"},
    {"label":"Analisi Dati",    "icon":"DATA",   "x":200,   "y":H-155, "col":"#34d399",
     "hair":"#34d399", "gaze_dx":+4, "gaze_dy":-3, "icon_sym":"▦"},
    {"label":"Scrittura",       "icon":"WRITE",  "x":W-200, "y":155,   "col":"#f472b6",
     "hair":"#f472b6", "gaze_dx":-4, "gaze_dy":+3, "icon_sym":"✎"},
    {"label":"Verifica Output", "icon":"CHECK",  "x":W-200, "y":H-155, "col":"#fb923c",
     "hair":"#fb923c", "gaze_dx":-4, "gaze_dy":-3, "icon_sym":"✓"},
]

CARD_W, CARD_H = 230, 245

# ── helper: task icon drawn with Pillow primitives ────────────────────────────
def draw_task_icon(drw, bx, by, icon_key, col):
    """Small icon in top-right corner of card."""
    c = rgba(col)
    if icon_key == "SEARCH":
        # magnifier: circle + handle
        drw.ellipse([bx-11, by-11, bx+5, by+5], outline=c, width=2)
        drw.line([bx+3, by+3, bx+11, by+11], fill=c, width=2)
    elif icon_key == "DATA":
        # bar chart
        for i, bh in enumerate([14, 10, 18]):
            rx = bx - 10 + i*10
            drw.rectangle([rx, by-bh, rx+7, by], fill=c)
    elif icon_key == "WRITE":
        # document + pen
        drw.rounded_rectangle([bx-12, by-18, bx+8, by+2], radius=2, outline=c, width=2)
        for i in range(3):
            drw.line([bx-9, by-14+i*6, bx+5, by-14+i*6], fill=rgba(col, 150), width=1)
        # pen tip
        drw.polygon([(bx+10, by+6),(bx+14, by-4),(bx+18, by+6)], fill=c)
    elif icon_key == "CHECK":
        # shield + checkmark
        drw.polygon([(bx, by-18),(bx-12, by-10),(bx-12, by+2),(bx, by+10),(bx+12, by+2),(bx+12, by-10)],
                    outline=c, width=2)
        drw.line([bx-5, by, bx, by+6, bx+8, by-6], fill=c, width=2)

# ── helper: draw stylized human face + card ───────────────────────────────────
def draw_agent(drw, ax, ay, col, hair_col, task_label, icon_key, gaze_dx, gaze_dy):
    tc  = rgba(col)
    hc  = rgba(hair_col)
    SKIN    = rgba("#f0c090")
    SKIN_D  = rgba("#d4956a")
    WHITE   = (255,255,255,255)
    DARK    = (25, 20, 15, 255)

    # card background
    drw.rounded_rectangle(
        [ax-CARD_W//2, ay-CARD_H//2, ax+CARD_W//2, ay+CARD_H//2],
        radius=16, fill=rgba("#0d0d28", 230), outline=tc, width=2)

    # task icon — top-right corner of card
    draw_task_icon(drw, ax + CARD_W//2 - 22, ay - CARD_H//2 + 26, icon_key, col)

    # portrait circle
    pr = 72
    fy = ay - 14   # face center y

    drw.ellipse([ax-pr-2, fy-pr-2, ax+pr+2, fy+pr+2], fill=rgba("#181836"))
    drw.ellipse([ax-pr, fy-pr, ax+pr, fy+pr],
                fill=rgba("#1c1c44"), outline=hc, width=2)

    # ── face: hair first, then head, then features ──────────────────────────
    hr = 43  # head radius

    # top hair block
    drw.ellipse([ax-hr-6, fy-hr-20, ax+hr+6, fy-4], fill=hc)
    # side sideburns
    drw.ellipse([ax-hr-14, fy-hr+8, ax-hr+6, fy+hr-10], fill=hc)
    drw.ellipse([ax+hr-6, fy-hr+8, ax+hr+14, fy+hr-10], fill=hc)

    # head oval
    drw.ellipse([ax-hr, fy-hr, ax+hr, fy+hr], fill=SKIN)

    # ears
    drw.ellipse([ax-hr-7, fy-10, ax-hr+4, fy+14], fill=SKIN)
    drw.ellipse([ax+hr-4, fy-10, ax+hr+7, fy+14], fill=SKIN)
    # inner ear shade
    drw.ellipse([ax-hr-4, fy-6, ax-hr+2, fy+10], fill=SKIN_D)
    drw.ellipse([ax+hr-2, fy-6, ax+hr+4, fy+10], fill=SKIN_D)

    # eyebrows
    brow_y = fy - 22
    for ex_off in (-17, 17):
        for bk in range(2):
            draw.arc([ax+ex_off-13, brow_y+bk, ax+ex_off+13, brow_y+bk+9],
                     start=210, end=330, fill=rgba("#6b4226"), width=2)

    # eyes
    ey = fy - 10
    for ex_off in (-17, 17):
        # white
        drw.ellipse([ax+ex_off-11, ey-8, ax+ex_off+11, ey+8], fill=WHITE)
        # iris
        drw.ellipse([ax+ex_off-6, ey-6, ax+ex_off+6, ey+6], fill=rgba("#3b5fa0"))
        # pupil (offset toward center = gaze)
        px = ax + ex_off + gaze_dx
        py_p = ey + gaze_dy
        drw.ellipse([px-4, py_p-4, px+4, py_p+4], fill=DARK)
        # glint
        drw.ellipse([px+1, py_p-3, px+4, py_p], fill=WHITE)

    # eyelids (top line)
    for ex_off in (-17, 17):
        drw.arc([ax+ex_off-11, ey-8, ax+ex_off+11, ey+8],
                start=200, end=340, fill=rgba("#6b4226"), width=1)

    # nose
    ny = fy + 10
    drw.arc([ax-7, ny, ax+7, ny+9], start=0, end=180, fill=SKIN_D, width=2)
    drw.ellipse([ax-5, ny+6, ax-1, ny+10], fill=SKIN_D)
    drw.ellipse([ax+1, ny+6, ax+5, ny+10], fill=SKIN_D)

    # mouth (gentle smile)
    my = fy + 23
    drw.arc([ax-14, my, ax+14, my+12], start=5, end=175, fill=rgba("#c07050"), width=2)

    # neck
    drw.rectangle([ax-11, fy+hr-6, ax+11, fy+hr+16], fill=SKIN)

    # shirt/collar
    drw.ellipse([ax-50, fy+hr+8, ax+50, fy+hr+55],
                fill=rgba(col, 160))
    # collar V
    drw.polygon([(ax-12, fy+hr+12),(ax, fy+hr+26),(ax+12, fy+hr+12)],
                fill=rgba("#0d0d28", 200))

    # label below portrait
    label_y = ay + CARD_H//2 - 26
    drw.text((ax, label_y), task_label, font=f_lbl, fill=WHITE, anchor="mm")

# ── draw agents ───────────────────────────────────────────────────────────────
for a in agents:
    draw_agent(draw, a["x"], a["y"], a["col"], a["hair"],
               a["label"], a["icon"], a["gaze_dx"], a["gaze_dy"])

# ── center PMI circle + text ──────────────────────────────────────────────────
draw.ellipse([cx-68, cy-68, cx+68, cy+68],
             fill=rgba("#0d0d28", 230), outline=rgba("#818cf8"), width=3)
draw.text((cx, cy-14), "PMI", font=f_pmi, fill=(255,255,255,255), anchor="mm")
draw.text((cx, cy+38), "AI Ops", font=f_ops, fill=rgba("#818cf8"), anchor="mm")

# ── arrows from PMI to each agent ─────────────────────────────────────────────
PMI_R = 72

def dashed_arrow(drw, x1, y1, x2, y2, col, width=2, dash=10, gap=7):
    c = rgba(col)
    dx, dy = x2-x1, y2-y1
    dist = math.hypot(dx, dy)
    if dist < 1: return
    ux, uy = dx/dist, dy/dist
    pos, on = 0.0, True
    while pos < dist - 16:
        seg = dash if on else gap
        end = min(pos + seg, dist - 16)
        if on:
            drw.line([(x1+ux*pos, y1+uy*pos),(x1+ux*end, y1+uy*end)], fill=c, width=width)
        pos, on = end, not on
    # arrowhead
    ang = math.atan2(dy, dx)
    sz = 13
    tip = (x2, y2)
    p1 = (x2 - sz*math.cos(ang-0.42), y2 - sz*math.sin(ang-0.42))
    p2 = (x2 - sz*math.cos(ang+0.42), y2 - sz*math.sin(ang+0.42))
    drw.polygon([tip, p1, p2], fill=c)

for a in agents:
    tx, ty = a["x"], a["y"]
    dx, dy = tx - cx, ty - cy
    dist = math.hypot(dx, dy)
    ux, uy = dx/dist, dy/dist

    # start: PMI circle edge
    sx, sy = cx + ux * PMI_R, cy + uy * PMI_R

    # end: card edge
    abs_ux, abs_uy = abs(ux), abs(uy)
    hw, hh = CARD_W/2 + 5, CARD_H/2 + 5
    clip = (hw/abs_ux) if abs_ux*hh > abs_uy*hw else (hh/abs_uy)
    ex, ey = tx - ux*(clip), ty - uy*(clip)

    dashed_arrow(draw, sx, sy, ex, ey, a["col"], width=2)

# ── save ──────────────────────────────────────────────────────────────────────
out = "/home/deploy/Business/OS AutoMatePRO/website/public/blog-images/sistemi-multi-agente-ai-pmi-2026.png"
img.convert("RGB").save(out, optimize=True)
print(f"Saved: {out}")
