import { Graphics } from 'pixi.js';
import { EnemyType } from './types';

export type BodyShape = 'diamond' | 'round' | 'wide' | 'tall' | 'spiky';
export type HeadShape = 'circle' | 'horns' | 'crown' | 'none' | 'fangs' | 'helmet';

export interface EnemyVisualConfig {
  bodyColor: number;
  strokeColor: number;
  headColor: number;
  headStrokeColor: number;
  size: number;
  bodyShape: BodyShape;
  headShape: HeadShape;
  glowColor?: number;
  isElite: boolean;
  drawExtras?: (gfx: Graphics, cx: number, cy: number, size: number, now: number) => void;
}

function getBodyTopY(cy: number, size: number, shape: BodyShape): number {
  switch (shape) {
    case 'diamond': return cy - size;
    case 'round': return cy - size * 0.75;
    case 'wide': return cy - size * 0.6;
    case 'tall': return cy - size * 1.1;
    case 'spiky': return cy - size * 1.1;
  }
}

function drawBody(
  gfx: Graphics, cx: number, cy: number, size: number,
  shape: BodyShape, color: number, strokeColor: number,
): void {
  switch (shape) {
    case 'diamond':
      gfx.poly([cx, cy - size, cx + size * 0.7, cy, cx, cy + size * 0.6, cx - size * 0.7, cy]);
      break;
    case 'round':
      gfx.ellipse(cx, cy - size * 0.2, size * 0.65, size * 0.55);
      break;
    case 'wide':
      gfx.poly([cx, cy - size * 0.6, cx + size, cy, cx, cy + size * 0.4, cx - size, cy]);
      break;
    case 'tall':
      gfx.poly([cx, cy - size * 1.1, cx + size * 0.45, cy, cx, cy + size * 0.5, cx - size * 0.45, cy]);
      break;
    case 'spiky':
      gfx.poly([
        cx, cy - size * 1.1,
        cx + size * 0.35, cy - size * 0.4,
        cx + size * 0.8, cy - size * 0.15,
        cx + size * 0.4, cy + size * 0.15,
        cx, cy + size * 0.6,
        cx - size * 0.4, cy + size * 0.15,
        cx - size * 0.8, cy - size * 0.15,
        cx - size * 0.35, cy - size * 0.4,
      ]);
      break;
  }
  gfx.fill({ color });
  gfx.stroke({ color: strokeColor, width: 2 });
}

function drawHead(
  gfx: Graphics, cx: number, bodyTop: number,
  shape: HeadShape, color: number, strokeColor: number,
): void {
  if (shape === 'none') return;

  const headY = bodyTop - 5;
  const r = 5;

  switch (shape) {
    case 'circle':
      gfx.circle(cx, headY, r);
      gfx.fill({ color });
      gfx.stroke({ color: strokeColor, width: 1.5 });
      break;

    case 'horns':
      gfx.circle(cx, headY, r);
      gfx.fill({ color });
      gfx.stroke({ color: strokeColor, width: 1.5 });
      gfx.poly([cx - 4, headY - 2, cx - 7, headY - 10, cx - 1, headY - 4]);
      gfx.fill({ color: strokeColor });
      gfx.poly([cx + 4, headY - 2, cx + 7, headY - 10, cx + 1, headY - 4]);
      gfx.fill({ color: strokeColor });
      break;

    case 'crown':
      gfx.circle(cx, headY, r);
      gfx.fill({ color });
      gfx.stroke({ color: strokeColor, width: 1.5 });
      gfx.poly([
        cx - 6, headY - 3,
        cx - 4, headY - 10,
        cx - 1, headY - 6,
        cx, headY - 12,
        cx + 1, headY - 6,
        cx + 4, headY - 10,
        cx + 6, headY - 3,
      ]);
      gfx.fill({ color: 0xFFDD44 });
      gfx.stroke({ color: 0xCCAA22, width: 1 });
      break;

    case 'fangs':
      gfx.circle(cx, headY, r);
      gfx.fill({ color });
      gfx.stroke({ color: strokeColor, width: 1.5 });
      gfx.poly([cx - 3, headY + 3, cx - 1.5, headY + 8, cx, headY + 3]);
      gfx.fill({ color: 0xEEEEDD });
      gfx.poly([cx, headY + 3, cx + 1.5, headY + 8, cx + 3, headY + 3]);
      gfx.fill({ color: 0xEEEEDD });
      break;

    case 'helmet':
      gfx.rect(cx - 6, headY - 6, 12, 10);
      gfx.fill({ color });
      gfx.stroke({ color: strokeColor, width: 1.5 });
      gfx.rect(cx - 4, headY - 1, 8, 2.5);
      gfx.fill({ color: 0x222233 });
      gfx.rect(cx - 1.5, headY - 8, 3, 4);
      gfx.fill({ color: strokeColor });
      break;
  }
}

// ---------------------------------------------------------------------------
// Visual configs for all 13 enemy types
// ---------------------------------------------------------------------------

export const ENEMY_VISUALS: Record<EnemyType, EnemyVisualConfig> = {

  // =======================================================================
  //  BASE ENEMIES
  // =======================================================================

  [EnemyType.Wolf]: {
    bodyColor: 0x808075,
    strokeColor: 0x5A5A50,
    headColor: 0x909085,
    headStrokeColor: 0x6A6A60,
    size: 12,
    bodyShape: 'diamond',
    headShape: 'fangs',
    isElite: false,
    drawExtras(gfx, cx, cy, size, now) {
      const headY = cy - size - 5;
      // Pointed ears
      gfx.poly([cx - 3, headY - 2, cx - 5, headY - 7, cx - 1, headY - 3]);
      gfx.fill({ color: 0x707065 });
      gfx.poly([cx + 3, headY - 2, cx + 5, headY - 7, cx + 1, headY - 3]);
      gfx.fill({ color: 0x707065 });
      // Wagging tail
      const wag = Math.sin(now * 0.01) * 3;
      gfx.poly([
        cx - size * 0.5, cy + size * 0.3,
        cx - size * 0.9 + wag, cy + size * 0.1,
        cx - size * 0.5, cy + size * 0.45,
      ]);
      gfx.fill({ color: 0x6A6A5A });
    },
  },

  [EnemyType.Boar]: {
    bodyColor: 0x8B6544,
    strokeColor: 0x6A4C33,
    headColor: 0x9B7554,
    headStrokeColor: 0x7A5C43,
    size: 16,
    bodyShape: 'wide',
    headShape: 'circle',
    isElite: false,
    drawExtras(gfx, cx, cy, size) {
      const headY = cy - size * 0.6 - 5;
      // Upward-curving tusks
      gfx.poly([cx - 4, headY + 1, cx - 6, headY - 6, cx - 2, headY]);
      gfx.fill({ color: 0xEEEEDD });
      gfx.poly([cx + 4, headY + 1, cx + 6, headY - 6, cx + 2, headY]);
      gfx.fill({ color: 0xEEEEDD });
      // Muscular back hump
      gfx.ellipse(cx, cy - size * 0.45, size * 0.4, size * 0.18);
      gfx.fill({ color: 0x7A5534, alpha: 0.7 });
    },
  },

  [EnemyType.Zombie]: {
    bodyColor: 0x5A7A4A,
    strokeColor: 0x3A5A2A,
    headColor: 0x6A8A5A,
    headStrokeColor: 0x4A6A3A,
    size: 14,
    bodyShape: 'diamond',
    headShape: 'circle',
    isElite: false,
    drawExtras(gfx, cx, cy, size, now) {
      // Green poison fog at feet
      const pulse = Math.sin(now * 0.003) * 0.15 + 0.3;
      gfx.ellipse(cx - 3, cy + size * 0.5, size * 0.8, 3);
      gfx.fill({ color: 0x44AA33, alpha: pulse });
      gfx.ellipse(cx + 4, cy + size * 0.55, size * 0.6, 2.5);
      gfx.fill({ color: 0x33BB22, alpha: pulse * 0.8 });
    },
  },

  [EnemyType.Spider]: {
    bodyColor: 0x6B3A7A,
    strokeColor: 0x4A2A5A,
    headColor: 0x6B3A7A,
    headStrokeColor: 0x4A2A5A,
    size: 11,
    bodyShape: 'round',
    headShape: 'none',
    isElite: false,
    drawExtras(gfx, cx, cy, size, now) {
      const wiggle = Math.sin(now * 0.008) * 1.5;
      // 3 legs per side (6 total, thin triangles)
      for (let i = 0; i < 3; i++) {
        const yOff = (i - 1) * 4;
        const baseY = cy - size * 0.2 + yOff;
        const spread = size * 0.6 + i * 2;
        const tipY = baseY - 2 + wiggle * (i % 2 === 0 ? 1 : -1);
        // Left leg
        gfx.poly([
          cx - size * 0.5, baseY,
          cx - size * 0.5 - spread, tipY,
          cx - size * 0.5 - spread + 0.8, tipY + 1.5,
        ]);
        gfx.fill({ color: 0x5A2A6A, alpha: 0.9 });
        // Right leg
        gfx.poly([
          cx + size * 0.5, baseY,
          cx + size * 0.5 + spread, tipY,
          cx + size * 0.5 + spread - 0.8, tipY + 1.5,
        ]);
        gfx.fill({ color: 0x5A2A6A, alpha: 0.9 });
      }
      // Red eyes
      gfx.circle(cx - 2.5, cy - size * 0.4, 1.5);
      gfx.fill({ color: 0xFF2222 });
      gfx.circle(cx + 2.5, cy - size * 0.4, 1.5);
      gfx.fill({ color: 0xFF2222 });
    },
  },

  [EnemyType.Orc]: {
    bodyColor: 0x4A7A3A,
    strokeColor: 0x2A5A1A,
    headColor: 0x888899,
    headStrokeColor: 0x666677,
    size: 15,
    bodyShape: 'wide',
    headShape: 'helmet',
    isElite: false,
    drawExtras(gfx, cx, cy, size) {
      // Shoulder armor plates
      gfx.rect(cx - size - 2, cy - size * 0.3, 5, 6);
      gfx.fill({ color: 0x666677 });
      gfx.stroke({ color: 0x555566, width: 1 });
      gfx.rect(cx + size - 3, cy - size * 0.3, 5, 6);
      gfx.fill({ color: 0x666677 });
      gfx.stroke({ color: 0x555566, width: 1 });
    },
  },

  [EnemyType.SkeletonArcher]: {
    bodyColor: 0xD4C8AA,
    strokeColor: 0xAA9E80,
    headColor: 0xE0D8BB,
    headStrokeColor: 0xBBB099,
    size: 13,
    bodyShape: 'tall',
    headShape: 'circle',
    isElite: false,
    drawExtras(gfx, cx, cy, size) {
      // Bow on right side
      const bowX = cx + size * 0.6;
      const bowMid = cy - size * 0.3;
      gfx.poly([bowX, bowMid - 8, bowX + 3, bowMid, bowX, bowMid + 8, bowX + 2, bowMid]);
      gfx.stroke({ color: 0x8B7355, width: 1.5 });
      // Bowstring
      gfx.poly([bowX, bowMid - 8, bowX - 1, bowMid, bowX, bowMid + 8]);
      gfx.stroke({ color: 0xCCCCBB, width: 0.7, alpha: 0.6 });
      // Rib lines for skeletal look
      const ribs: [number, number][] = [[-0.5, 4], [-0.2, 3.5], [0.1, 3]];
      for (const [yFrac, w] of ribs) {
        gfx.rect(cx - w / 2, cy + size * yFrac, w, 1);
        gfx.fill({ color: 0xBBB099, alpha: 0.5 });
      }
    },
  },

  [EnemyType.BattleLizard]: {
    bodyColor: 0x6B7A3A,
    strokeColor: 0x4B5A1A,
    headColor: 0x6B7A3A,
    headStrokeColor: 0x4B5A1A,
    size: 16,
    bodyShape: 'wide',
    headShape: 'none',
    isElite: false,
    drawExtras(gfx, cx, cy, size) {
      // Scale pattern (small diamonds across body)
      const sc = 0x5A6A2A;
      for (let row = 0; row < 2; row++) {
        for (let col = -1; col <= 1; col++) {
          const sx = cx + col * 6;
          const sy = cy - size * 0.15 + row * 5;
          gfx.poly([sx, sy - 2, sx + 2.5, sy, sx, sy + 2, sx - 2.5, sy]);
          gfx.fill({ color: sc, alpha: 0.5 });
        }
      }
      // Snout bump (head substitute)
      const topY = cy - size * 0.6;
      gfx.ellipse(cx, topY - 4, 4.5, 3);
      gfx.fill({ color: 0x7B8A4A });
      gfx.stroke({ color: 0x5B6A2A, width: 1 });
      // Yellow reptile eyes
      gfx.circle(cx - 2, topY - 5, 1.2);
      gfx.fill({ color: 0xDDAA22 });
      gfx.circle(cx + 2, topY - 5, 1.2);
      gfx.fill({ color: 0xDDAA22 });
      // Tail extending behind
      gfx.poly([
        cx - size * 0.7, cy + size * 0.2,
        cx - size - 5, cy + size * 0.45,
        cx - size * 0.6, cy + size * 0.35,
      ]);
      gfx.fill({ color: 0x5A6A2A });
    },
  },

  // =======================================================================
  //  ELITE ENEMIES
  // =======================================================================

  [EnemyType.FireDemon]: {
    bodyColor: 0xCC4422,
    strokeColor: 0xAA2211,
    headColor: 0xDD5533,
    headStrokeColor: 0xBB3322,
    size: 15,
    bodyShape: 'spiky',
    headShape: 'horns',
    glowColor: 0xFF6600,
    isElite: true,
    drawExtras(gfx, cx, cy, size, now) {
      const headY = cy - size * 1.1 - 5;
      const f1 = Math.sin(now * 0.008) * 3;
      const f2 = Math.cos(now * 0.011) * 2;
      const f3 = Math.sin(now * 0.014 + 1) * 2.5;
      // Main flame
      gfx.poly([cx - 3, headY - 6, cx, headY - 14 + f1, cx + 3, headY - 6]);
      gfx.fill({ color: 0xFF6600, alpha: 0.85 });
      // Side flames
      gfx.poly([cx + 3, headY - 4, cx + 5, headY - 11 + f2, cx + 7, headY - 4]);
      gfx.fill({ color: 0xFFAA00, alpha: 0.7 });
      gfx.poly([cx - 7, headY - 4, cx - 5, headY - 10 + f3, cx - 3, headY - 4]);
      gfx.fill({ color: 0xFF4400, alpha: 0.65 });
      // Bright inner core
      gfx.poly([cx - 1.5, headY - 4, cx, headY - 9 + f2, cx + 1.5, headY - 4]);
      gfx.fill({ color: 0xFFDD44, alpha: 0.9 });
    },
  },

  [EnemyType.IceGuardian]: {
    bodyColor: 0x44AADD,
    strokeColor: 0x2288BB,
    headColor: 0x99CCDD,
    headStrokeColor: 0x77AABB,
    size: 16,
    bodyShape: 'diamond',
    headShape: 'helmet',
    glowColor: 0x44CCFF,
    isElite: true,
    drawExtras(gfx, cx, cy, size, now) {
      const pulse = Math.sin(now * 0.003) * 0.2 + 0.8;
      // Left ice crystal
      gfx.poly([
        cx - size * 0.7 - 1, cy - 2,
        cx - size * 0.7 - 6, cy - 10,
        cx - size * 0.7 - 3, cy,
      ]);
      gfx.fill({ color: 0xAADDFF, alpha: pulse });
      gfx.stroke({ color: 0x88CCFF, width: 0.8, alpha: pulse });
      // Right ice crystal
      gfx.poly([
        cx + size * 0.7 + 1, cy - 3,
        cx + size * 0.7 + 7, cy - 9,
        cx + size * 0.7 + 3, cy,
      ]);
      gfx.fill({ color: 0x99CCEE, alpha: pulse });
      gfx.stroke({ color: 0x77AADD, width: 0.8, alpha: pulse });
      // Top crystal spike
      gfx.poly([cx - 2, cy - size - 12, cx, cy - size - 18, cx + 2, cy - size - 12]);
      gfx.fill({ color: 0xBBEEFF, alpha: pulse * 0.9 });
      // Frost sparkles (blink on/off)
      if (Math.sin(now * 0.006) > 0.5) {
        gfx.circle(cx - size * 0.5, cy - size * 0.7, 1);
        gfx.fill({ color: 0xFFFFFF, alpha: 0.8 });
        gfx.circle(cx + size * 0.6, cy - size * 0.3, 1);
        gfx.fill({ color: 0xFFFFFF, alpha: 0.7 });
      }
    },
  },

  [EnemyType.SkeletonKing]: {
    bodyColor: 0xCCBB77,
    strokeColor: 0xAA9955,
    headColor: 0xDDCC88,
    headStrokeColor: 0xBBAA66,
    size: 16,
    bodyShape: 'tall',
    headShape: 'crown',
    glowColor: 0xAA44FF,
    isElite: true,
    drawExtras(gfx, cx, cy, size, now) {
      // Orbiting bone fragments
      const angle = now * 0.002;
      const orbitR = size + 10;
      for (let i = 0; i < 3; i++) {
        const a = angle + (i * Math.PI * 2) / 3;
        const bx = cx + Math.cos(a) * orbitR;
        const by = cy - size * 0.3 + Math.sin(a) * orbitR * 0.4;
        gfx.rect(bx - 1, by - 2.5, 2, 5);
        gfx.fill({ color: 0xDDCCAA, alpha: 0.75 });
      }
      // Rib lines for skeletal body
      gfx.rect(cx - 2.5, cy - size * 0.5, 5, 1);
      gfx.fill({ color: 0xAA9955, alpha: 0.5 });
      gfx.rect(cx - 2, cy - size * 0.15, 4, 1);
      gfx.fill({ color: 0xAA9955, alpha: 0.5 });
    },
  },

  [EnemyType.WaterElement]: {
    bodyColor: 0x33AACC,
    strokeColor: 0x1188AA,
    headColor: 0x33AACC,
    headStrokeColor: 0x1188AA,
    size: 14,
    bodyShape: 'round',
    headShape: 'none',
    glowColor: 0x33DDFF,
    isElite: true,
    drawExtras(gfx, cx, cy, size, now) {
      // Translucent highlight for watery look
      gfx.ellipse(cx, cy - size * 0.25, size * 0.4, size * 0.35);
      gfx.fill({ color: 0x77DDFF, alpha: 0.3 });
      // Animated ripple rings at base
      const ripple = (now * 0.003) % (Math.PI * 2);
      const r1 = size * 0.5 + Math.sin(ripple) * 4;
      gfx.ellipse(cx, cy + size * 0.3, r1 + 4, (r1 + 4) * 0.35);
      gfx.stroke({ color: 0x44DDFF, width: 1, alpha: 0.35 + Math.sin(ripple) * 0.15 });
      const r2 = size * 0.5 + Math.sin(ripple + 1.5) * 3;
      gfx.ellipse(cx, cy + size * 0.4, r2 + 7, (r2 + 7) * 0.3);
      gfx.stroke({ color: 0x33CCEE, width: 0.8, alpha: 0.25 + Math.sin(ripple + 1.5) * 0.1 });
      // Water droplets floating upward
      const d1 = cy - size * 0.5 - ((now * 0.02) % 12);
      const d2 = cy - size * 0.3 - ((now * 0.018 + 6) % 10);
      gfx.circle(cx - 3, d1, 1.2);
      gfx.fill({ color: 0x88EEFF, alpha: 0.6 });
      gfx.circle(cx + 4, d2, 1);
      gfx.fill({ color: 0x77DDFF, alpha: 0.5 });
    },
  },

  [EnemyType.ForestWarden]: {
    bodyColor: 0x3A6A2A,
    strokeColor: 0x1A4A0A,
    headColor: 0x3A6A2A,
    headStrokeColor: 0x1A4A0A,
    size: 18,
    bodyShape: 'wide',
    headShape: 'none',
    glowColor: 0x44CC44,
    isElite: true,
    drawExtras(gfx, cx, cy, size, now) {
      // Bark texture (horizontal grooves)
      for (let i = 0; i < 3; i++) {
        const ly = cy - size * 0.25 + i * 5;
        const lw = size * (0.5 - i * 0.08);
        gfx.rect(cx - lw, ly, lw * 2, 1.5);
        gfx.fill({ color: 0x2A4A1A, alpha: 0.4 });
      }
      // Tree canopy crown on top
      const topY = cy - size * 0.6;
      gfx.ellipse(cx, topY - 7, 9, 5.5);
      gfx.fill({ color: 0x2D7A1D, alpha: 0.9 });
      gfx.ellipse(cx - 4, topY - 4, 6, 4);
      gfx.fill({ color: 0x358A25, alpha: 0.85 });
      gfx.ellipse(cx + 4, topY - 4, 6, 4);
      gfx.fill({ color: 0x358A25, alpha: 0.85 });
      // Glowing eyes peering from canopy
      gfx.circle(cx - 3, topY - 6, 1.5);
      gfx.fill({ color: 0x88FF44 });
      gfx.circle(cx + 3, topY - 6, 1.5);
      gfx.fill({ color: 0x88FF44 });
      // Root tendrils at base
      const sway = Math.sin(now * 0.002) * 1.5;
      gfx.poly([
        cx - size * 0.6, cy + size * 0.3,
        cx - size - 3 + sway, cy + size * 0.5,
        cx - size * 0.5, cy + size * 0.4,
      ]);
      gfx.fill({ color: 0x4A5A2A, alpha: 0.7 });
      gfx.poly([
        cx + size * 0.5, cy + size * 0.3,
        cx + size + 2 - sway, cy + size * 0.5,
        cx + size * 0.6, cy + size * 0.4,
      ]);
      gfx.fill({ color: 0x4A5A2A, alpha: 0.7 });
    },
  },

  [EnemyType.LightningTitan]: {
    bodyColor: 0x5577CC,
    strokeColor: 0x3355AA,
    headColor: 0x6688DD,
    headStrokeColor: 0x4466BB,
    size: 20,
    bodyShape: 'tall',
    headShape: 'horns',
    glowColor: 0xFFDD44,
    isElite: true,
    drawExtras(gfx, cx, cy, size, now) {
      // Lightning bolt zigzag (intermittent)
      const strike = Math.sin(now * 0.015);
      if (strike > 0.2) {
        const alpha = Math.min(1, (strike - 0.2) * 1.25);
        const lx = cx + Math.sin(now * 0.02) * 5;
        const topY = cy - size * 1.1 - 5;
        gfx.poly([
          lx - 1, topY - 8,
          lx + 4, topY - 2,
          lx, topY - 1,
          lx + 3, topY + 6,
          lx - 2, topY + 7,
          lx + 1, topY + 14,
          lx - 1, topY + 7,
          lx + 1, topY + 6,
          lx - 3, topY,
          lx + 1, topY - 1,
          lx - 2, topY - 2,
        ]);
        gfx.fill({ color: 0xFFFF44, alpha: alpha * 0.7 });
        gfx.stroke({ color: 0xFFFFAA, width: 1, alpha });
      }
      // Static sparks orbiting the body
      const sparkPhase = (now * 0.01) % (Math.PI * 2);
      for (let i = 0; i < 4; i++) {
        const a = sparkPhase + (i * Math.PI) / 2;
        if (Math.sin(a + now * 0.005) > 0.6) {
          const sx = cx + Math.cos(a) * (size * 0.8);
          const sy = cy + Math.sin(a) * (size * 0.4) - size * 0.3;
          gfx.circle(sx, sy, 1.5);
          gfx.fill({ color: 0xFFFF88, alpha: 0.85 });
        }
      }
    },
  },
};

// ---------------------------------------------------------------------------
// Main draw function — replaces the generic red-diamond drawEnemy
// ---------------------------------------------------------------------------

export function drawEnemyByType(
  gfx: Graphics,
  wx: number,
  wy: number,
  hp: number,
  maxHp: number,
  enemyType: EnemyType,
  now: number,
  worldToScreenFn: (wx: number, wy: number) => { x: number; y: number },
): void {
  gfx.clear();

  const config = ENEMY_VISUALS[enemyType];
  if (!config) return;

  const iso = worldToScreenFn(wx, wy);
  const sway = Math.sin(now * 0.004) * 2;
  const cx = iso.x;
  const cy = iso.y + sway;
  const { size } = config;

  // 1. Shadow
  gfx.ellipse(cx, cy + 8, size + 2, 5);
  gfx.fill({ color: 0x000000, alpha: 0.3 });

  // 2. Elite glow (behind body)
  if (config.isElite && config.glowColor != null) {
    const pulse = Math.sin(now * 0.003) * 0.12 + 0.22;
    gfx.circle(cx, cy - size * 0.2, size + 8);
    gfx.fill({ color: config.glowColor, alpha: pulse });
  }

  // 3. Body
  drawBody(gfx, cx, cy, size, config.bodyShape, config.bodyColor, config.strokeColor);

  // 4. Head
  const bodyTop = getBodyTopY(cy, size, config.bodyShape);
  drawHead(gfx, cx, bodyTop, config.headShape, config.headColor, config.headStrokeColor);

  // 5. Type-specific decorations
  config.drawExtras?.(gfx, cx, cy, size, now);

  // 6. HP bar
  const barWidth = 30;
  const barHeight = 4;
  const headHeight = config.headShape === 'none'
    ? (config.isElite ? 12 : 6)
    : config.headShape === 'crown' ? 22
    : config.headShape === 'horns' ? 18
    : config.headShape === 'helmet' ? 16
    : 14;
  const hpBarY = bodyTop - headHeight - 4;

  gfx.rect(cx - barWidth / 2, hpBarY, barWidth, barHeight);
  gfx.fill({ color: 0x000000, alpha: 0.6 });

  const hpRatio = maxHp > 0 ? Math.max(0, hp / maxHp) : 0;
  if (hpRatio > 0) {
    gfx.rect(cx - barWidth / 2, hpBarY, barWidth * hpRatio, barHeight);
    const hpColor = hpRatio > 0.5 ? 0xcc3333 : hpRatio > 0.25 ? 0xccaa22 : 0xff2222;
    gfx.fill({ color: hpColor });
  }

  // Elite HP bar border
  if (config.isElite) {
    gfx.rect(cx - barWidth / 2, hpBarY, barWidth, barHeight);
    gfx.stroke({ color: config.glowColor ?? 0xFFAA00, width: 1, alpha: 0.8 });
  }

  // Depth sorting
  gfx.zIndex = cy + 100;
}
