import { useEffect, useState } from "react";
import { X, Lock } from "lucide-react";
import type { QuestNode } from "../types/quest";

// ─── Styles ───────────────────────────────────────────────────────────────────
const STYLES = `
  @import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@600;700;900&family=Sorts+Mill+Goudy:ital@0;1&family=Nunito:wght@700;800;900&family=Nunito+Sans:wght@400;600;700&display=swap');

  /* ══ OVERLAY ══ */
  .qnm-overlay {
    position: fixed; inset: 0; z-index: 40;
    background: rgba(4,8,20,0.72);
    backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
    display: flex; align-items: flex-end; justify-content: center;
    animation: qnmFade 0.22s ease both;
  }
  @keyframes qnmFade { from{opacity:0} to{opacity:1} }

  /* ══ SHEET ══ */
  .qnm-sheet {
    width: 100%; max-width: 520px;
    background: #06101f;
    border-radius: 28px 28px 0 0;
    border-top: 1.5px solid rgba(251,191,36,0.2);
    box-shadow: 0 -12px 60px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.06);
    overflow: hidden;
    display: flex; flex-direction: column;
    max-height: 92vh;
    animation: qnmUp 0.38s cubic-bezier(0.34,1.56,0.64,1) both;
  }
  @keyframes qnmUp { from{transform:translateY(100%);opacity:0} to{transform:translateY(0);opacity:1} }

  /* Handle */
  .qnm-handle-row { display:flex; justify-content:center; padding:0.8rem 0 0.3rem; flex-shrink:0; }
  .qnm-handle { width:38px; height:4px; border-radius:100px; background:rgba(255,255,255,0.12); }

  /* Close btn */
  .qnm-close {
    position:absolute; top:0.9rem; right:1.1rem; z-index:10;
    width:30px; height:30px; border-radius:50%;
    border:1.5px solid rgba(255,255,255,0.12); background:rgba(255,255,255,0.06);
    display:flex; align-items:center; justify-content:center;
    cursor:pointer; transition: all 0.15s ease;
  }
  .qnm-close:hover { border-color:rgba(251,191,36,0.5); background:rgba(251,191,36,0.1); }

  /* ══ 3D ISLAND STAGE ══ */
  .qnm-stage {
    position: relative; flex-shrink: 0;
    height: 200px; overflow: hidden;
    background: linear-gradient(180deg, var(--sky-top) 0%, var(--sky-bot) 55%, var(--sea-col) 100%);
  }

  /* Sea waves */
  .qnm-sea {
    position:absolute; bottom:0; left:0; right:0; height:52px;
    background: var(--sea-col); overflow:hidden;
  }
  .qnm-wave {
    position:absolute; bottom:0; left:-100%; width:300%;
    height:30px; border-radius:50% 50% 0 0;
    background: rgba(255,255,255,0.07);
    animation: qnmWave var(--wdur,5s) ease-in-out infinite;
  }
  .qnm-wave:nth-child(2){ animation-delay:-2s; opacity:0.5; }
  .qnm-wave:nth-child(3){ animation-delay:-4s; opacity:0.3; height:20px; }
  @keyframes qnmWave {
    0%  { transform: translateX(0)   scaleY(1);   }
    50% { transform: translateX(15%) scaleY(1.08);}
    100%{ transform: translateX(0)   scaleY(1);   }
  }

  /* Floating clouds */
  .qnm-cloud {
    position:absolute; border-radius:50px;
    background: rgba(255,255,255,0.18);
    filter: blur(4px);
    animation: qnmDrift var(--cdur,18s) linear infinite;
  }
  @keyframes qnmDrift {
    0%  { transform: translateX(-120px); opacity:0;   }
    10% { opacity:1; }
    90% { opacity:1; }
    100%{ transform: translateX(calc(100vw + 120px)); opacity:0; }
  }

  /* ── The 3D island container ── */
  .qnm-island-3d-wrap {
    position: absolute;
    left: 50%; bottom: 40px;
    transform: translateX(-50%);
    perspective: 420px;
    width: 220px; height: 140px;
  }
  .qnm-island-3d {
    width: 100%; height: 100%;
    transform-style: preserve-3d;
    animation: qnmIslandSpin 18s linear infinite;
    position: relative;
  }
  @keyframes qnmIslandSpin {
    0%   { transform: rotateX(22deg) rotateY(0deg);   }
    100% { transform: rotateX(22deg) rotateY(360deg); }
  }

  /* Island layers — stacked in 3D */
  .qnm-il { /* island layer base class */
    position: absolute; left: 50%; bottom: 0;
    transform-origin: bottom center;
    border-radius: 50%;
    transform-style: preserve-3d;
  }

  /* Water base disc */
  .qnm-il-water {
    width: 200px; height: 44px; margin-left: -100px;
    background: radial-gradient(ellipse 80% 100% at 50% 40%, var(--sea-hi), var(--sea-col));
    border-radius: 50%;
    transform: translateZ(-4px);
    box-shadow: 0 0 40px var(--sea-col);
    animation: qnmWaterShimmer 3s ease-in-out infinite;
  }
  @keyframes qnmWaterShimmer {
    0%,100%{ opacity:1; }
    50%    { opacity:0.82; }
  }

  /* Ripple rings on water */
  .qnm-ripple {
    position:absolute; left:50%; top:50%;
    border-radius:50%; border:1.5px solid rgba(255,255,255,0.25);
    animation: qnmRipple 2.8s ease-out infinite;
  }
  .qnm-ripple:nth-child(2){ animation-delay:-1.4s; }
  @keyframes qnmRipple {
    0%  { width:60px;  height:20px;  margin-left:-30px; margin-top:-10px; opacity:0.7; }
    100%{ width:180px; height:60px;  margin-left:-90px; margin-top:-30px; opacity:0;   }
  }

  /* Island ground */
  .qnm-il-ground {
    width: 160px; height: 36px; margin-left: -80px;
    background: radial-gradient(ellipse at 40% 30%, var(--terr-hi), var(--terr-mid) 55%, var(--terr-lo));
    border-radius: 50%;
    transform: translateZ(14px);
    box-shadow: 0 8px 24px rgba(0,0,0,0.55), inset 0 -4px 8px rgba(0,0,0,0.25);
  }

  /* Island side face — gives the 3D depth illusion */
  .qnm-il-side {
    width: 158px; height: 22px; margin-left: -79px;
    bottom: -12px;
    background: linear-gradient(180deg, var(--terr-lo), rgba(0,0,0,0.6));
    clip-path: ellipse(79px 100% at 50% 0%);
    transform: translateZ(8px) rotateX(-8deg);
  }

  /* Peak */
  .qnm-il-peak {
    width: 80px; height: 60px; margin-left: -40px;
    bottom: 26px;
    background: radial-gradient(ellipse at 42% 25%, var(--peak-hi), var(--peak-mid) 60%, var(--peak-lo));
    clip-path: var(--peak-shape, polygon(50% 0%, 80% 55%, 100% 100%, 0% 100%, 20% 55%));
    transform: translateZ(26px);
    filter: drop-shadow(0 6px 12px rgba(0,0,0,0.5));
    animation: qnmPeakBob 4s ease-in-out infinite;
  }
  @keyframes qnmPeakBob {
    0%,100%{ transform: translateZ(26px) translateY(0);    }
    50%    { transform: translateZ(26px) translateY(-4px); }
  }

  /* Floating decoration layer (trees, cactus, cloud orb, etc.) */
  .qnm-il-deco {
    position: absolute; bottom: 56px; left: 50%;
    transform: translateZ(42px);
    animation: qnmDecoFloat 3s ease-in-out infinite;
  }
  @keyframes qnmDecoFloat {
    0%,100%{ transform: translateZ(42px) translateY(0)    rotate(0deg);   }
    50%    { transform: translateZ(42px) translateY(-7px) rotate(3deg);   }
  }
  .qnm-deco-emoji { font-size:1.4rem; filter:drop-shadow(0 4px 8px rgba(0,0,0,0.5)); }

  /* Flag pole on active */
  .qnm-il-flag {
    position:absolute; bottom:56px; left:50%;
    transform: translateZ(50px) translateX(12px);
  }
  .qnm-flag-pole {
    width:2px; height:26px; background:#7c4a1e;
    border-radius:2px;
  }
  .qnm-flag-cloth {
    position:absolute; top:2px; left:2px;
    width:16px; height:11px;
    background:#ef4444; clip-path:polygon(0%0%,100%25%,0%100%);
    animation: qnmFlagWave 1.2s ease-in-out infinite;
    transform-origin:left center;
  }
  @keyframes qnmFlagWave {
    0%,100%{ transform:skewY(0deg);   }
    50%    { transform:skewY(-10deg); }
  }

  /* Stars / sparkles above completed island */
  .qnm-star {
    position:absolute; font-size:1rem;
    animation: qnmStarPop var(--sdur,2s) ease-in-out infinite;
    animation-delay: var(--sdel,0s);
  }
  @keyframes qnmStarPop {
    0%,100%{ transform:scale(1)   translateY(0);   opacity:0.8; }
    50%    { transform:scale(1.4) translateY(-8px); opacity:1;   }
  }

  /* ══ CONTENT BELOW THE STAGE ══ */
  .qnm-body {
    flex:1; overflow-y:auto; scrollbar-width:none;
    display:flex; flex-direction:column; gap:0.85rem;
    padding:1.1rem 1.25rem 0.5rem;
  }
  .qnm-body::-webkit-scrollbar { display:none; }

  /* Title block */
  .qnm-title-block { position:relative; }
  .qnm-arc-tag {
    display:inline-flex; align-items:center; gap:0.3rem;
    font-size:0.58rem; font-weight:800; letter-spacing:0.14em;
    text-transform:uppercase; color:var(--ac);
    background:rgba(255,255,255,0.05); border:1px solid rgba(255,255,255,0.08);
    border-radius:100px; padding:0.18rem 0.6rem; margin-bottom:0.45rem;
  }
  .qnm-quest-title {
    font-family:'Cinzel',serif;
    font-size:1.22rem; font-weight:700; color:white;
    letter-spacing:0.02em; line-height:1.2; margin-bottom:0.18rem;
  }
  .qnm-island-name {
    font-family:'Nunito Sans',sans-serif;
    font-size:0.72rem; font-weight:700; color:rgba(255,255,255,0.38);
  }

  /* Flavour quote */
  .qnm-flavour {
    background:rgba(255,255,255,0.04); border:1px solid rgba(255,255,255,0.07);
    border-left:3px solid var(--ac);
    border-radius:0 14px 14px 0;
    padding:0.8rem 1rem;
  }
  .qnm-flavour-text {
    font-family:'Sorts Mill Goudy',serif;
    font-size:0.82rem; color:rgba(255,255,255,0.55);
    font-style:italic; line-height:1.6;
  }

  /* Objective card */
  .qnm-obj-card {
    background:rgba(255,255,255,0.04);
    border:1px solid rgba(255,255,255,0.08);
    border-radius:18px; padding:0.9rem 1rem;
  }
  .qnm-obj-header {
    display:flex; align-items:center; justify-content:space-between; margin-bottom:0.65rem;
  }
  .qnm-obj-label {
    font-size:0.58rem; font-weight:800; letter-spacing:0.14em;
    text-transform:uppercase; color:rgba(255,255,255,0.3);
  }
  .qnm-obj-pct {
    font-family:'Nunito',sans-serif;
    font-size:0.78rem; font-weight:900; color:var(--ac);
  }
  .qnm-obj-row {
    display:flex; align-items:center; gap:0.65rem; margin-bottom:0.7rem;
  }
  .qnm-obj-icon {
    width:38px; height:38px; border-radius:12px; flex-shrink:0;
    background:rgba(255,255,255,0.06); border:1px solid rgba(255,255,255,0.08);
    display:flex; align-items:center; justify-content:center; font-size:1.1rem;
  }
  .qnm-obj-text {
    font-family:'Nunito',sans-serif;
    font-size:0.88rem; font-weight:900; color:white;
  }
  .qnm-obj-sub {
    font-family:'Nunito Sans',sans-serif;
    font-size:0.68rem; font-weight:600; color:rgba(255,255,255,0.35); margin-top:0.05rem;
  }

  /* Progress bar */
  .qnm-bar-track {
    height:9px; background:rgba(255,255,255,0.07);
    border-radius:100px; overflow:hidden; margin-bottom:0.3rem;
  }
  .qnm-bar-fill {
    height:100%; border-radius:100px;
    background:linear-gradient(90deg, var(--ac), color-mix(in srgb, var(--ac) 65%, white));
    box-shadow:0 0 10px color-mix(in srgb, var(--ac) 55%, transparent);
    transition:width 0.8s cubic-bezier(0.34,1.56,0.64,1);
  }
  .qnm-bar-nums {
    display:flex; justify-content:space-between;
    font-family:'Nunito',sans-serif;
    font-size:0.65rem; font-weight:800; color:rgba(255,255,255,0.28);
  }
  .qnm-bar-nums span:first-child { color:var(--ac); }

  /* ── HOW TO COMPLETE section ── */
  .qnm-howto-label {
    font-size:0.58rem; font-weight:800; letter-spacing:0.14em;
    text-transform:uppercase; color:rgba(255,255,255,0.3);
    margin-bottom:0.55rem; margin-top:0.3rem;
  }
  .qnm-howto-badges {
    display:flex; flex-wrap:wrap; gap:0.4rem;
  }
  .qnm-howto-badge {
    display:flex; align-items:center; gap:0.3rem;
    padding:0.38rem 0.75rem;
    background:rgba(255,255,255,0.06);
    border:1px solid rgba(255,255,255,0.1);
    border-radius:100px;
    font-family:'Nunito',sans-serif;
    font-size:0.72rem; font-weight:800; color:rgba(255,255,255,0.7);
    transition: all 0.15s ease;
    animation: qnmBadgeIn 0.35s cubic-bezier(0.34,1.56,0.64,1) both;
    animation-delay: var(--bdel, 0s);
  }
  @keyframes qnmBadgeIn {
    from{ opacity:0; transform:scale(0.8) translateY(6px); }
    to  { opacity:1; transform:scale(1)   translateY(0);   }
  }
  .qnm-howto-badge:hover {
    background:rgba(255,255,255,0.1);
    border-color:rgba(255,255,255,0.2);
    color:white;
    transform:translateY(-1px);
  }
  /* Highlight badge = accent coloured */
  .qnm-howto-badge.hi {
    background:color-mix(in srgb, var(--ac) 18%, transparent);
    border-color:color-mix(in srgb, var(--ac) 45%, transparent);
    color:var(--ac);
  }

  /* Locked banner */
  .qnm-locked-banner {
    display:flex; align-items:center; gap:0.7rem;
    background:rgba(255,255,255,0.04); border:1px solid rgba(255,255,255,0.07);
    border-radius:16px; padding:0.9rem 1rem;
  }
  .qnm-locked-icon {
    width:38px; height:38px; border-radius:12px; flex-shrink:0;
    background:rgba(255,255,255,0.05); display:flex; align-items:center; justify-content:center;
  }
  .qnm-locked-text {
    font-family:'Nunito',sans-serif;
    font-size:0.82rem; font-weight:800; color:rgba(255,255,255,0.4);
  }
  .qnm-locked-sub {
    font-family:'Nunito Sans',sans-serif;
    font-size:0.68rem; font-weight:600; color:rgba(255,255,255,0.22); margin-top:0.1rem;
  }

  /* Reward card */
  .qnm-reward-card {
    background:rgba(251,191,36,0.07);
    border:1px solid rgba(251,191,36,0.22);
    border-radius:18px; padding:0.9rem 1rem;
  }
  .qnm-reward-label {
    font-size:0.58rem; font-weight:800; letter-spacing:0.14em;
    text-transform:uppercase; color:rgba(251,191,36,0.6); margin-bottom:0.6rem;
  }
  .qnm-reward-row { display:flex; flex-wrap:wrap; gap:0.4rem; }
  .qnm-reward-pill {
    display:flex; align-items:center; gap:0.28rem;
    padding:0.35rem 0.8rem;
    background:rgba(251,191,36,0.1); border:1.5px solid rgba(251,191,36,0.3);
    border-radius:100px;
    font-family:'Nunito',sans-serif;
    font-size:0.75rem; font-weight:900; color:#fbbf24;
    box-shadow:0 2px 8px rgba(251,191,36,0.1);
  }

  /* ══ FOOTER CTA ══ */
  .qnm-footer {
    padding:1rem 1.25rem calc(1rem + env(safe-area-inset-bottom));
    flex-shrink:0; border-top:1px solid rgba(255,255,255,0.07);
    background:#06101f;
  }
  .qnm-claim-btn {
    width:100%; padding:0.95rem;
    background:linear-gradient(135deg,#fbbf24,#f59e0b);
    border:none; border-radius:16px; cursor:pointer;
    font-family:'Cinzel',serif; font-size:1rem; font-weight:700; color:#1a0800;
    letter-spacing:0.04em;
    box-shadow:0 5px 0 #d97706, 0 8px 24px rgba(251,191,36,0.35);
    transition:all 0.12s ease;
  }
  .qnm-claim-btn:hover  { transform:translateY(-2px); box-shadow:0 7px 0 #d97706; }
  .qnm-claim-btn:active { transform:translateY(2px);  box-shadow:0 3px 0 #d97706; }
  .qnm-note {
    text-align:center;
    font-family:'Nunito Sans',sans-serif;
    font-size:0.72rem; font-weight:700; color:rgba(255,255,255,0.28);
    padding:0.4rem 0;
  }
`;

// ─── Per-arc terrain themes ───────────────────────────────────────────────────
interface Terrain {
  skyTop: string;
  skyBot: string;
  seaCol: string;
  seaHi: string;
  terrHi: string;
  terrMid: string;
  terrLo: string;
  peakHi: string;
  peakMid: string;
  peakLo: string;
  decos: string[];
}

const TERRAIN: Record<string, Terrain> = {
  east_blue: {
    skyTop: "#0a1628",
    skyBot: "#0d2240",
    seaCol: "#0a3d5c",
    seaHi: "#1a6a8a",
    terrHi: "#5eead4",
    terrMid: "#0d9488",
    terrLo: "#0f5c55",
    peakHi: "#a7f3d0",
    peakMid: "#34d399",
    peakLo: "#065f46",
    decos: ["🌴", "🌿"],
  },
  alabasta: {
    skyTop: "#1c0a00",
    skyBot: "#3d1a00",
    seaCol: "#7c3a00",
    seaHi: "#c26010",
    terrHi: "#fde68a",
    terrMid: "#d97706",
    terrLo: "#78350f",
    peakHi: "#fef3c7",
    peakMid: "#fbbf24",
    peakLo: "#92400e",
    decos: ["🌵", "🏺"],
  },
  skypiea: {
    skyTop: "#1a0033",
    skyBot: "#2e0050",
    seaCol: "#4c1d95",
    seaHi: "#7c3aed",
    terrHi: "#e9d5ff",
    terrMid: "#a855f7",
    terrLo: "#581c87",
    peakHi: "#f5d0fe",
    peakMid: "#d946ef",
    peakLo: "#701a75",
    decos: ["☁️", "✨"],
  },
};
const DEFAULT_TERRAIN = TERRAIN.east_blue;

// ─── Per-requirement how-to badges ───────────────────────────────────────────
interface Badge {
  emoji: string;
  label: string;
  highlight?: boolean;
}

const HOW_TO: Record<string, { title: string; badges: Badge[] }> = {
  questions: {
    title: "How to complete this",
    badges: [
      { emoji: "📝", label: "Take a Practice Sheet", highlight: true },
      { emoji: "⚡", label: "Try Drills Mode" },
      { emoji: "🎯", label: "Aim for 10+ per session" },
      { emoji: "🔄", label: "Retry completed sheets" },
    ],
  },
  accuracy: {
    title: "How to complete this",
    badges: [
      { emoji: "🐢", label: "Slow down, read carefully", highlight: true },
      { emoji: "📖", label: "Review wrong answers" },
      { emoji: "🎯", label: "Do targeted practice", highlight: true },
      { emoji: "💡", label: "Use process of elimination" },
    ],
  },
  streak: {
    title: "How to complete this",
    badges: [
      { emoji: "📅", label: "Practice every day", highlight: true },
      { emoji: "⏰", label: "Set a daily reminder" },
      { emoji: "🔥", label: "Even 5 mins counts" },
      { emoji: "🛡️", label: "Use a Streak Shield" },
    ],
  },
  sessions: {
    title: "How to complete this",
    badges: [
      { emoji: "📝", label: "Start a Practice Sheet", highlight: true },
      { emoji: "⚡", label: "Complete Drills" },
      { emoji: "🏃", label: "Short sessions count too" },
      { emoji: "📚", label: "Try different modules" },
    ],
  },
  topics: {
    title: "How to complete this",
    badges: [
      { emoji: "🗺️", label: "Explore new modules", highlight: true },
      { emoji: "📊", label: "Check your weak topics" },
      { emoji: "🔍", label: "Use Search to find topics" },
      { emoji: "⚡", label: "Drill each topic once" },
    ],
  },
  xp: {
    title: "How to complete this",
    badges: [
      { emoji: "🎯", label: "High accuracy = bonus XP", highlight: true },
      { emoji: "🔥", label: "Maintain your streak" },
      { emoji: "📝", label: "Complete full sheets", highlight: true },
      { emoji: "⚡", label: "Use XP Boosts" },
    ],
  },
  leaderboard: {
    title: "How to complete this",
    badges: [
      { emoji: "📈", label: "Aim for 80%+ accuracy", highlight: true },
      { emoji: "🔥", label: "Keep your streak alive" },
      { emoji: "📝", label: "Do sessions daily" },
      { emoji: "🏆", label: "Check the leaderboard" },
    ],
  },
};

// ─── Island shape configs (mirrors the 6 clip-path shapes in QuestMap) ────────
// groundClip  = clip-path for the flat top disc of the island
// peakClip    = clip-path for the hill/feature rising above it
// groundW/H   = pixel size of the ground layer
// peakW/H     = pixel size of the peak layer
// sideClip    = clip-path for the side-face depth layer
interface ShapeConfig {
  groundClip: string;
  peakClip: string;
  sideClip: string;
  groundW: number;
  groundH: number;
  peakW: number;
  peakH: number;
  peakBottom: number; // translateZ bottom offset in px
}

// These correspond 1-to-1 with SHAPES[0..5] in QuestMap.tsx
const ISLAND_SHAPES: ShapeConfig[] = [
  // 0: fat round atoll
  {
    groundClip: "ellipse(50% 50% at 50% 50%)",
    peakClip: "ellipse(50% 50% at 50% 55%)",
    sideClip: "ellipse(50% 100% at 50% 0%)",
    groundW: 160,
    groundH: 38,
    peakW: 88,
    peakH: 38,
    peakBottom: 26,
  },
  // 1: tall mountain — narrow diamond ground, sharp triangular peak
  {
    groundClip: "polygon(50% 5%, 92% 50%, 50% 95%, 8% 50%)",
    peakClip: "polygon(50% 0%, 82% 52%, 100% 100%, 0% 100%, 18% 52%)",
    sideClip: "polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)",
    groundW: 148,
    groundH: 36,
    peakW: 72,
    peakH: 72,
    peakBottom: 24,
  },
  // 2: wide flat shoal — extra-wide squashed ellipse, low dome
  {
    groundClip: "ellipse(50% 40% at 50% 58%)",
    peakClip: "ellipse(50% 38% at 50% 60%)",
    sideClip: "ellipse(50% 100% at 50% 0%)",
    groundW: 178,
    groundH: 30,
    peakW: 114,
    peakH: 28,
    peakBottom: 22,
  },
  // 3: jagged rocky reef — star-burst polygon
  {
    groundClip:
      "polygon(50% 2%, 63% 35%, 98% 35%, 71% 56%, 80% 92%, 50% 72%, 20% 92%, 29% 56%, 2% 35%, 37% 35%)",
    peakClip:
      "polygon(50% 0%, 63% 32%, 98% 32%, 71% 54%, 80% 90%, 50% 70%, 20% 90%, 29% 54%, 2% 32%, 37% 32%)",
    sideClip: "ellipse(50% 100% at 50% 0%)",
    groundW: 152,
    groundH: 38,
    peakW: 80,
    peakH: 66,
    peakBottom: 24,
  },
  // 4: crescent — lopsided asymmetric bean
  {
    groundClip:
      "path('M 80 10 C 120 5, 150 30, 145 55 C 140 78, 110 88, 80 85 C 55 82, 38 70, 42 55 C 46 42, 62 40, 68 50 C 74 60, 65 70, 55 68 C 38 62, 30 42, 42 28 C 55 12, 70 12, 80 10 Z')",
    peakClip: "ellipse(38% 55% at 38% 50%)",
    sideClip: "ellipse(50% 100% at 50% 0%)",
    groundW: 160,
    groundH: 36,
    peakW: 80,
    peakH: 58,
    peakBottom: 22,
  },
  // 5: teardrop/pear — narrow top, wide rounded base
  {
    groundClip:
      "path('M 50 4 C 72 4, 95 28, 95 55 C 95 78, 76 94, 50 94 C 24 94, 5 78, 5 55 C 5 28, 28 4, 50 4 Z')",
    peakClip:
      "polygon(50% 0%, 73% 27%, 88% 62%, 68% 98%, 32% 98%, 12% 62%, 27% 27%)",
    sideClip: "ellipse(50% 100% at 50% 0%)",
    groundW: 144,
    groundH: 38,
    peakW: 76,
    peakH: 66,
    peakBottom: 24,
  },
];

// ─── Helpers ──────────────────────────────────────────────────────────────────
const reqIcon = (type: string): string =>
  ({
    questions: "❓",
    accuracy: "🎯",
    streak: "🔥",
    sessions: "📚",
    topics: "🗺️",
    xp: "⚡",
    leaderboard: "🏆",
  })[type] ?? "⭐";

// ─── 3D Island Stage ──────────────────────────────────────────────────────────
const IslandStage = ({
  arcId,
  status,
  nodeIndex,
}: {
  arcId: string;
  status: QuestNode["status"];
  nodeIndex: number;
}) => {
  const t = TERRAIN[arcId] ?? DEFAULT_TERRAIN;
  const shp = ISLAND_SHAPES[nodeIndex % ISLAND_SHAPES.length];

  const isCompleted = status === "completed";
  const isClaimable = status === "claimable";
  const isActive = status === "active";
  const isLocked = status === "locked";

  const vars = {
    "--sky-top": t.skyTop,
    "--sky-bot": t.skyBot,
    "--sea-col": t.seaCol,
    "--sea-hi": t.seaHi,
    "--terr-hi": t.terrHi,
    "--terr-mid": t.terrMid,
    "--terr-lo": t.terrLo,
    "--peak-hi": t.peakHi,
    "--peak-mid": t.peakMid,
    "--peak-lo": t.peakLo,
  } as React.CSSProperties;

  return (
    <div className="qnm-stage" style={vars}>
      {/* Clouds */}
      {[
        { w: 70, h: 22, top: 14, delay: 0, dur: 16 },
        { w: 50, h: 16, top: 28, delay: -7, dur: 22 },
        { w: 40, h: 14, top: 10, delay: -3, dur: 28 },
      ].map((c, i) => (
        <div
          key={i}
          className="qnm-cloud"
          style={
            {
              width: c.w,
              height: c.h,
              top: c.top,
              "--cdur": `${c.dur}s`,
              animationDelay: `${c.delay}s`,
              opacity: isLocked ? 0.08 : 0.18,
            } as React.CSSProperties
          }
        />
      ))}

      {/* Sea + waves */}
      <div className="qnm-sea">
        <div
          className="qnm-wave"
          style={{ "--wdur": "5s" } as React.CSSProperties}
        />
        <div
          className="qnm-wave"
          style={{ "--wdur": "7s" } as React.CSSProperties}
        />
        <div
          className="qnm-wave"
          style={{ "--wdur": "9s" } as React.CSSProperties}
        />
      </div>

      {/* Ripple rings on water surface */}
      <div
        style={{
          position: "absolute",
          left: "50%",
          bottom: 32,
          transform: "translateX(-50%)",
          width: 0,
          height: 0,
        }}
      >
        <div className="qnm-ripple" />
        <div className="qnm-ripple" />
      </div>

      {/* 3D island */}
      <div
        className="qnm-island-3d-wrap"
        style={{ opacity: isLocked ? 0.3 : 1 }}
      >
        <div
          className="qnm-island-3d"
          style={{
            // Pause rotation when locked
            animationPlayState: isLocked ? "paused" : "running",
          }}
        >
          {/* Water base */}
          <div className="qnm-il qnm-il-water" />

          {/* Island side face */}
          <div
            className="qnm-il qnm-il-side"
            style={{
              width: shp.groundW,
              marginLeft: -(shp.groundW / 2),
              clipPath: shp.sideClip,
            }}
          />

          {/* Island ground — shaped to match QuestMap */}
          <div
            className="qnm-il qnm-il-ground"
            style={{
              width: shp.groundW,
              height: shp.groundH,
              marginLeft: -(shp.groundW / 2),
              clipPath: shp.groundClip,
              borderRadius: 0,
            }}
          />

          {/* Peak / hill — shaped to match QuestMap */}
          {!isLocked && (
            <div
              className="qnm-il qnm-il-peak"
              style={{
                width: shp.peakW,
                height: shp.peakH,
                marginLeft: -(shp.peakW / 2),
                bottom: shp.peakBottom,
                clipPath: shp.peakClip,
              }}
            />
          )}

          {/* Decorations */}
          {!isLocked &&
            t.decos.map((deco, di) => (
              <div
                key={di}
                className="qnm-il-deco"
                style={{
                  marginLeft: di === 0 ? "-30px" : "8px",
                  animationDelay: `${di * 0.6}s`,
                }}
              >
                <span className="qnm-deco-emoji">{deco}</span>
              </div>
            ))}

          {/* Pirate flag on active */}
          {isActive && (
            <div className="qnm-il-flag">
              <div className="qnm-flag-pole" />
              <div className="qnm-flag-cloth" />
            </div>
          )}

          {/* Chest bouncing on claimable */}
          {isClaimable && (
            <div className="qnm-il-deco" style={{ marginLeft: "-12px" }}>
              <span
                className="qnm-deco-emoji"
                style={{
                  animation: "qnmPeakBob 1s ease-in-out infinite",
                  fontSize: "1.6rem",
                }}
              >
                📦
              </span>
            </div>
          )}

          {/* Lock icon on locked */}
          {isLocked && (
            <div
              style={{
                position: "absolute",
                left: "50%",
                bottom: 50,
                transform: "translateX(-50%) translateZ(30px)",
                fontSize: "2rem",
                opacity: 0.5,
              }}
            >
              🔒
            </div>
          )}
        </div>
      </div>

      {/* Sparkles for completed */}
      {isCompleted && (
        <>
          {[
            { left: "30%", top: "18%", sdur: "2s", sdel: "0s" },
            { left: "62%", top: "12%", sdur: "2.4s", sdel: "0.6s" },
            { left: "20%", top: "38%", sdur: "1.8s", sdel: "1.1s" },
            { left: "74%", top: "32%", sdur: "2.2s", sdel: "0.3s" },
          ].map((s, i) => (
            <span
              key={i}
              className="qnm-star"
              style={
                {
                  left: s.left,
                  top: s.top,
                  "--sdur": s.sdur,
                  "--sdel": s.sdel,
                } as React.CSSProperties
              }
            >
              ✨
            </span>
          ))}
        </>
      )}

      {/* Lock overlay tint */}
      {isLocked && (
        <div
          style={{
            position: "absolute",
            inset: 0,
            background: "rgba(0,0,0,0.45)",
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
          }}
        >
          <span style={{ fontSize: "2.5rem", opacity: 0.6 }}>🔒</span>
        </div>
      )}
    </div>
  );
};

// ─── Main component ───────────────────────────────────────────────────────────
interface Props {
  node: QuestNode;
  arcAccent: string;
  arcDark: string;
  arcId?: string;
  nodeIndex?: number;
  onClose: () => void;
  onClaim: () => void;
}

export const QuestNodeModal = ({
  node,
  arcAccent,
  arcDark,
  arcId = "east_blue",
  nodeIndex = 0,
  onClose,
  onClaim,
}: Props) => {
  const [mounted, setMounted] = useState(false);
  useEffect(() => {
    setMounted(true);
  }, []);

  const progress = Math.min(
    100,
    Math.round((node.progress / node.requirement.target) * 100),
  );
  const isClaimable = node.status === "claimable";
  const isLocked = node.status === "locked";
  const isCompleted = node.status === "completed";
  const isActive = node.status === "active";
  const howTo = HOW_TO[node.requirement.type];

  return (
    <div
      className="qnm-overlay"
      onClick={onClose}
      style={{ "--ac": arcAccent } as React.CSSProperties}
    >
      <style>{STYLES}</style>
      <div className="qnm-sheet" onClick={(e) => e.stopPropagation()}>
        {/* Handle + close */}
        <div className="qnm-handle-row">
          <div className="qnm-handle" />
        </div>
        <button className="qnm-close" onClick={onClose}>
          <X size={13} color="rgba(255,255,255,0.5)" />
        </button>

        {/* 3D island stage */}
        <IslandStage arcId={arcId} status={node.status} nodeIndex={nodeIndex} />

        {/* Scrollable content */}
        <div className="qnm-body">
          {/* Title */}
          <div className="qnm-title-block">
            <div className="qnm-arc-tag">
              {reqIcon(node.requirement.type)} Quest
            </div>
            <h2 className="qnm-quest-title">{node.title}</h2>
            <p className="qnm-island-name">📍 {node.islandName}</p>
          </div>

          {/* Flavour */}
          <div className="qnm-flavour">
            <p className="qnm-flavour-text">{node.flavourText}</p>
          </div>

          {/* Objective */}
          <div className="qnm-obj-card">
            <div className="qnm-obj-header">
              <span className="qnm-obj-label">⚓ Objective</span>
              {!isLocked && (
                <span className="qnm-obj-pct">
                  {isCompleted ? "✅ Done" : `${progress}%`}
                </span>
              )}
            </div>
            <div className="qnm-obj-row">
              <div className="qnm-obj-icon">
                {reqIcon(node.requirement.type)}
              </div>
              <div>
                <p className="qnm-obj-text">
                  {node.requirement.target} {node.requirement.label}
                </p>
                <p className="qnm-obj-sub">
                  {isCompleted
                    ? "✅ Completed — treasure claimed!"
                    : isLocked
                      ? "🔒 Complete previous quests first"
                      : `${node.progress} / ${node.requirement.target} done`}
                </p>
              </div>
            </div>

            {/* Progress bar */}
            {!isLocked && (
              <>
                <div className="qnm-bar-track">
                  <div
                    className="qnm-bar-fill"
                    style={{ width: mounted ? `${progress}%` : "0%" }}
                  />
                </div>
                <div className="qnm-bar-nums">
                  <span>{node.progress}</span>
                  <span>{node.requirement.target}</span>
                </div>
              </>
            )}

            {/* How-to badges — show when active or claimable */}
            {(isActive || isClaimable) && howTo && (
              <>
                <p className="qnm-howto-label" style={{ marginTop: "0.75rem" }}>
                  🧭 {howTo.title}
                </p>
                <div className="qnm-howto-badges">
                  {howTo.badges.map((b, bi) => (
                    <div
                      key={bi}
                      className={`qnm-howto-badge${b.highlight ? " hi" : ""}`}
                      style={
                        { "--bdel": `${bi * 0.06}s` } as React.CSSProperties
                      }
                    >
                      <span>{b.emoji}</span>
                      <span>{b.label}</span>
                    </div>
                  ))}
                </div>
              </>
            )}
          </div>

          {/* Locked banner */}
          {isLocked && (
            <div className="qnm-locked-banner">
              <div className="qnm-locked-icon">
                <Lock size={18} color="rgba(255,255,255,0.3)" />
              </div>
              <div>
                <p className="qnm-locked-text">Quest Locked</p>
                <p className="qnm-locked-sub">
                  Complete the previous island to sail here
                </p>
              </div>
            </div>
          )}

          {/* Reward */}
          <div className="qnm-reward-card">
            <p className="qnm-reward-label">📦 Treasure Chest</p>
            <div className="qnm-reward-row">
              <div className="qnm-reward-pill">⚡ +{node.reward.xp} XP</div>
              {node.reward.title && (
                <div className="qnm-reward-pill">🏴‍☠️ {node.reward.title}</div>
              )}
              {node.reward.itemLabel && (
                <div className="qnm-reward-pill">
                  🎁 {node.reward.itemLabel}
                </div>
              )}
            </div>
          </div>
        </div>

        {/* Footer CTA */}
        <div className="qnm-footer">
          {isClaimable ? (
            <button className="qnm-claim-btn" onClick={onClaim}>
              ⚓ Open Your Treasure Chest
            </button>
          ) : isCompleted ? (
            <p className="qnm-note">✅ Completed — treasure claimed!</p>
          ) : isLocked ? (
            <p className="qnm-note">🔒 Locked — keep sailing</p>
          ) : (
            <p className="qnm-note">
              {progress}% complete · {node.requirement.target - node.progress}{" "}
              {node.requirement.label} remaining
            </p>
          )}
        </div>
      </div>
    </div>
  );
};
