/*
  entities.js — Save Pet
  Pet / Bee / Hive: state factories, per-frame physics updates and
  procedural vector-art rendering (pure Canvas 2D — no image
  files, so there is nothing that can fail to load).
*/
window.SP = window.SP || {};

SP.Entities = (function () {
  "use strict";
  const U = SP.Utils;

  /* ============================ PET ============================ */
  function createPet(x, y, radius) {
    return {
      x: x, y: y, radius: radius || 46,
      health: SP.Config.PET_MAX_HEALTH, maxHealth: SP.Config.PET_MAX_HEALTH,
      blinking: false, blinkTimer: 1.5 + Math.random() * 2, blinkDur: 0,
      hurtTimer: 0, happyTimer: 0, tailPhase: Math.random() * 10,
      alert: 0
    };
  }

  function updatePet(pet, dt, alertFactor) {
    pet.tailPhase += dt * (2 + alertFactor * 3.5);
    pet.alert += (alertFactor - pet.alert) * Math.min(1, dt * 5);
    pet.blinkTimer -= dt;
    if (pet.blinkTimer <= 0 && !pet.blinking) {
      pet.blinking = true; pet.blinkDur = 0.12;
      pet.blinkTimer = 2.2 + Math.random() * 2.6;
    }
    if (pet.blinking) {
      pet.blinkDur -= dt;
      if (pet.blinkDur <= 0) pet.blinking = false;
    }
    if (pet.hurtTimer > 0) pet.hurtTimer -= dt;
    if (pet.happyTimer > 0) pet.happyTimer -= dt;
  }

  function hitPet(pet) {
    pet.health = Math.max(0, pet.health - 1);
    pet.hurtTimer = 0.5;
  }

  function drawPet(ctx, pet) {
    const r = pet.radius;
    let shakeX = 0, shakeY = 0;
    if (pet.hurtTimer > 0) {
      const k = pet.hurtTimer * 14;
      shakeX = Math.sin(k) * 5 * pet.hurtTimer * 2;
      shakeY = Math.cos(k * 1.3) * 3 * pet.hurtTimer * 2;
    }
    const bounce = pet.happyTimer > 0 ? Math.abs(Math.sin(pet.happyTimer * 13)) * r * 0.22 : 0;
    const happy = pet.happyTimer > 0;
    const scared = pet.alert > 0.55 && pet.hurtTimer <= 0 && !happy;

    ctx.save();
    ctx.translate(pet.x + shakeX, pet.y + shakeY - bounce);

    ctx.fillStyle = "rgba(20,20,30,0.18)";
    ctx.beginPath();
    ctx.ellipse(0, r * 0.98 + bounce * 0.5, r * 0.82, r * 0.2, 0, 0, Math.PI * 2);
    ctx.fill();

    const tailSwing = Math.sin(pet.tailPhase);
    ctx.strokeStyle = "#E0982A";
    ctx.lineWidth = r * 0.26;
    ctx.lineCap = "round";
    ctx.beginPath();
    ctx.moveTo(r * 0.68, r * 0.15);
    ctx.quadraticCurveTo(r * 1.25, r * 0.05 + tailSwing * r * 0.28, r * 1.42, -r * 0.32 + tailSwing * r * 0.12);
    ctx.stroke();

    ctx.fillStyle = "#FFC363";
    ctx.beginPath();
    ctx.ellipse(0, r * 0.58, r * 0.72, r * 0.55, 0, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = "#E0982A";
    ctx.beginPath();
    ctx.ellipse(-r * 0.9, -r * 0.15, r * 0.34, r * 0.55, -0.15, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(r * 0.9, -r * 0.15, r * 0.34, r * 0.55, 0.15, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = "#FFC363";
    ctx.beginPath();
    ctx.arc(0, 0, r, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = "rgba(255,130,165,0.55)";
    ctx.beginPath(); ctx.ellipse(-r * 0.63, r * 0.2, r * 0.16, r * 0.1, 0, 0, Math.PI * 2); ctx.fill();
    ctx.beginPath(); ctx.ellipse(r * 0.63, r * 0.2, r * 0.16, r * 0.1, 0, 0, Math.PI * 2); ctx.fill();

    [-1, 1].forEach(function (side) {
      const ex = side * r * 0.36, ey = -r * 0.05;
      if (pet.blinking && !happy) {
        ctx.strokeStyle = "#22283A";
        ctx.lineWidth = Math.max(1.5, r * 0.045);
        ctx.beginPath();
        ctx.moveTo(ex - r * 0.16, ey);
        ctx.lineTo(ex + r * 0.16, ey);
        ctx.stroke();
      } else if (happy) {
        ctx.strokeStyle = "#22283A";
        ctx.lineWidth = Math.max(1.5, r * 0.06);
        ctx.beginPath();
        ctx.arc(ex, ey + r * 0.1, r * 0.15, Math.PI, 0, false);
        ctx.stroke();
      } else {
        const eyeR = scared ? r * 0.21 : r * 0.165;
        ctx.fillStyle = "#FFFFFF";
        ctx.beginPath(); ctx.ellipse(ex, ey, eyeR * 0.85, eyeR, 0, 0, Math.PI * 2); ctx.fill();
        ctx.fillStyle = "#22283A";
        ctx.beginPath(); ctx.arc(ex, ey + eyeR * 0.1, eyeR * 0.52, 0, Math.PI * 2); ctx.fill();
        ctx.fillStyle = "#FFFFFF";
        ctx.beginPath(); ctx.arc(ex - eyeR * 0.18, ey - eyeR * 0.25, eyeR * 0.18, 0, Math.PI * 2); ctx.fill();
      }
    });

    ctx.fillStyle = "#FFF3DE";
    ctx.beginPath();
    ctx.ellipse(0, r * 0.34, r * 0.42, r * 0.32, 0, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = "#22283A";
    ctx.beginPath();
    ctx.ellipse(0, r * 0.26, r * 0.1, r * 0.075, 0, 0, Math.PI * 2);
    ctx.fill();

    ctx.strokeStyle = "#22283A";
    ctx.lineWidth = Math.max(1.5, r * 0.04);
    ctx.beginPath();
    if (pet.hurtTimer > 0) {
      ctx.ellipse(0, r * 0.5, r * 0.09, r * 0.11, 0, 0, Math.PI * 2);
      ctx.stroke();
    } else {
      const smileR = happy ? r * 0.24 : r * 0.16;
      ctx.arc(0, r * 0.34, smileR, 0.15 * Math.PI, 0.85 * Math.PI);
      ctx.stroke();
    }

    if (pet.hurtTimer > 0) {
      ctx.fillStyle = "rgba(130,205,255,0.9)";
      ctx.beginPath();
      ctx.ellipse(r * 0.36, r * 0.05, r * 0.05, r * 0.09, 0, 0, Math.PI * 2);
      ctx.fill();
    }

    ctx.restore();
  }

  /* ============================ BEE ============================ */
  function createBee(x, y, opts) {
    opts = opts || {};
    const type = opts.type || "normal";
    const baseR = type === "tank" ? 21 : (type === "fast" ? 12.5 : 16);
    return {
      x: x, y: y, vx: 0, vy: 0,
      type: type,
      radius: baseR * (opts.scale || 1),
      speed: opts.speed || 80,
      hp: type === "tank" ? 2 : 1,
      wobblePhase: Math.random() * Math.PI * 2,
      wobbleFreq: 1.6 + Math.random() * 1.4,
      flapPhase: Math.random() * Math.PI * 2,
      hitFlash: 0,
      angle: 0,
      dead: false
    };
  }

  function updateBee(bee, dt, tx, ty, windMag, elapsed) {
    const dx = tx - bee.x, dy = ty - bee.y;
    const d = Math.hypot(dx, dy) || 1;
    const desiredVx = (dx / d) * bee.speed, desiredVy = (dy / d) * bee.speed;
    const steer = Math.min(1, 4.2 * dt);
    bee.vx += (desiredVx - bee.vx) * steer;
    bee.vy += (desiredVy - bee.vy) * steer;
    const perpX = -dy / d, perpY = dx / d;
    const wobble = Math.sin(elapsed * bee.wobbleFreq + bee.wobblePhase) * (windMag || 12);
    bee.x += bee.vx * dt + perpX * wobble * dt;
    bee.y += bee.vy * dt + perpY * wobble * dt;
    bee.angle = Math.atan2(bee.vy, bee.vx);
    bee.flapPhase += dt * 42;
    if (bee.hitFlash > 0) bee.hitFlash -= dt;
  }

  function drawBeeBody(ctx, r, type, flash) {
    const bodyColor = flash ? "#FFFFFF" : (type === "tank" ? "#E0A100" : "#FFC93C");
    ctx.save();
    ctx.beginPath();
    ctx.ellipse(0, 0, r, r * 0.72, 0, 0, Math.PI * 2);
    ctx.closePath();
    ctx.clip();
    ctx.fillStyle = bodyColor;
    ctx.fillRect(-r, -r, r * 2, r * 2);
    ctx.fillStyle = flash ? "#EDEDED" : "#22283A";
    [-0.5, 0, 0.5].forEach(function (sx) {
      ctx.fillRect(sx * r - r * 0.14, -r, r * 0.28, r * 2);
    });
    ctx.restore();
    if (type === "tank") {
      ctx.strokeStyle = "rgba(255,255,255,0.55)";
      ctx.lineWidth = Math.max(1, r * 0.08);
      ctx.beginPath();
      ctx.ellipse(0, 0, r * 1.05, r * 0.78, 0, 0, Math.PI * 2);
      ctx.stroke();
    }
  }

  function drawBee(ctx, bee) {
    const r = bee.radius;
    ctx.save();
    ctx.translate(bee.x, bee.y);
    ctx.rotate(bee.angle);

    if (bee.type === "fast") {
      ctx.globalAlpha = 0.22;
      for (let i = 1; i <= 2; i++) {
        ctx.save();
        ctx.translate(-i * r * 1.1, 0);
        drawBeeBody(ctx, r * 0.75, bee.type, false);
        ctx.restore();
      }
      ctx.globalAlpha = 1;
    }

    const flap = Math.sin(bee.flapPhase) * 0.5 + 0.5;
    ctx.fillStyle = "rgba(255,255,255,0.85)";
    ctx.beginPath();
    ctx.ellipse(-r * 0.05, -r * 0.55 - flap * r * 0.35, r * 0.5, r * 0.3, -0.3, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(r * 0.4, -r * 0.55 - flap * r * 0.35, r * 0.46, r * 0.28, 0.3, 0, Math.PI * 2);
    ctx.fill();

    drawBeeBody(ctx, r, bee.type, bee.hitFlash > 0);

    ctx.fillStyle = "#22283A";
    ctx.beginPath(); ctx.arc(r * 0.62, -r * 0.1, r * 0.11, 0, Math.PI * 2); ctx.fill();

    ctx.strokeStyle = "#22283A";
    ctx.lineWidth = Math.max(1, r * 0.06);
    ctx.beginPath();
    ctx.moveTo(r * 0.65, -r * 0.35); ctx.quadraticCurveTo(r * 0.95, -r * 0.65, r * 0.85, -r * 0.8);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(r * 0.75, -r * 0.25); ctx.quadraticCurveTo(r * 1.1, -r * 0.45, r * 1.1, -r * 0.65);
    ctx.stroke();

    ctx.fillStyle = "#22283A";
    ctx.beginPath();
    ctx.moveTo(-r * 1.0, 0); ctx.lineTo(-r * 1.35, -r * 0.1); ctx.lineTo(-r * 1.35, r * 0.1);
    ctx.closePath(); ctx.fill();

    ctx.restore();
  }

  /* ============================ HIVE ============================ */
  function createHive(x, y, radius) {
    return { x: x, y: y, radius: radius || 36, phase: Math.random() * Math.PI * 2, pulse: 0 };
  }

  function drawHive(ctx, hive, elapsed) {
    const bob = Math.sin(elapsed * 1.4 + hive.phase) * 4;
    const r = hive.radius;
    ctx.save();
    ctx.translate(hive.x, hive.y + bob);

    ctx.fillStyle = "rgba(20,15,10,0.22)";
    ctx.beginPath();
    ctx.ellipse(0, r * 0.92, r * 0.78, r * 0.2, 0, 0, Math.PI * 2);
    ctx.fill();

    const grad = ctx.createLinearGradient(0, -r, 0, r);
    grad.addColorStop(0, "#E3A85C");
    grad.addColorStop(1, "#A9702D");
    ctx.fillStyle = grad;
    ctx.beginPath();
    ctx.moveTo(-r * 0.85, r * 0.7);
    ctx.quadraticCurveTo(-r * 1.05, -r * 0.2, 0, -r * 1.02);
    ctx.quadraticCurveTo(r * 1.05, -r * 0.2, r * 0.85, r * 0.7);
    ctx.quadraticCurveTo(0, r * 0.92, -r * 0.85, r * 0.7);
    ctx.closePath();
    ctx.fill();

    ctx.strokeStyle = "rgba(0,0,0,0.16)";
    ctx.lineWidth = 2;
    for (let i = 1; i <= 3; i++) {
      const ry = -r * 0.55 + i * r * 0.48;
      const rx = Math.max(4, r * 0.85 * (1 - Math.abs(ry) / (r * 1.05)));
      ctx.beginPath();
      ctx.ellipse(0, ry, rx, 5, 0, 0, Math.PI * 2);
      ctx.stroke();
    }

    ctx.fillStyle = "#3B2413";
    ctx.beginPath();
    ctx.ellipse(0, r * 0.42, r * 0.28, r * 0.2, 0, 0, Math.PI * 2);
    ctx.fill();

    ctx.restore();
  }

  return {
    createPet: createPet, updatePet: updatePet, hitPet: hitPet, drawPet: drawPet,
    createBee: createBee, updateBee: updateBee, drawBee: drawBee,
    createHive: createHive, drawHive: drawHive
  };
})();
