// PromptOS app — Dashboard screen

// Hero animasi three.js: grid partikel bergelombang, warna mengikuti tema
function ThreeHero({ theme }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el || !window.THREE) return;
    const W = el.clientWidth || 800, H = el.clientHeight || 150;
    const scene = new THREE.Scene();
    const cam = new THREE.PerspectiveCamera(50, W / H, 0.1, 100);
    cam.position.set(0, 3.6, 10);
    cam.lookAt(0, -0.5, 0);
    let renderer;
    try {
      renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    } catch (e) { return; } // WebGL tidak tersedia — banner tampil tanpa animasi
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setSize(W, H);
    el.appendChild(renderer.domElement);

    const COLS = 110, ROWS = 24, SX = 0.32, SZ = 0.55;
    const pos = new Float32Array(COLS * ROWS * 3);
    for (let j = 0; j < ROWS; j++) {
      for (let i = 0; i < COLS; i++) {
        const k = (j * COLS + i) * 3;
        pos[k] = (i - COLS / 2) * SX;
        pos[k + 1] = 0;
        pos[k + 2] = (j - ROWS / 2) * SZ;
      }
    }
    const geo = new THREE.BufferGeometry();
    geo.setAttribute('position', new THREE.BufferAttribute(pos, 3));
    const mat = new THREE.PointsMaterial({
      color: new THREE.Color('#7c5cfa'), size: 0.075,
      transparent: true, opacity: theme === 'light' ? 0.5 : 0.85,
    });
    scene.add(new THREE.Points(geo, mat));

    let t = 0, raf;
    const tick = () => {
      t += 0.025;
      const a = geo.attributes.position.array;
      for (let j = 0; j < ROWS; j++) {
        for (let i = 0; i < COLS; i++) {
          const k = (j * COLS + i) * 3;
          a[k + 1] = Math.sin(i * 0.22 + t) * 0.5 + Math.cos(j * 0.4 + t * 0.7) * 0.35;
        }
      }
      geo.attributes.position.needsUpdate = true;
      renderer.render(scene, cam);
      raf = requestAnimationFrame(tick);
    };
    tick();

    const onResize = () => {
      const w = el.clientWidth, h = el.clientHeight;
      if (!w || !h) return;
      cam.aspect = w / h;
      cam.updateProjectionMatrix();
      renderer.setSize(w, h);
    };
    window.addEventListener('resize', onResize);

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('resize', onResize);
      geo.dispose(); mat.dispose(); renderer.dispose();
      el.removeChild(renderer.domElement);
    };
  }, [theme]);
  return <div ref={ref} style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}></div>;
}

function StatCard({ icon, value, label, delta, color }) {
  return (
    <Card hover style={{ flex: 1, padding: '16px 18px', display: 'flex', flexDirection: 'column', gap: 8 }}>
      <span style={{
        width: 30, height: 30, borderRadius: 8, background: color + '22', border: `1px solid ${color}44`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <span style={{ width: 11, height: 11, borderRadius: 3.5, background: color }}></span>
      </span>
      <span style={{ fontSize: 26, fontWeight: 800, letterSpacing: '-0.02em', color: T.text }}>{value}</span>
      <span style={{ fontSize: 12.5, color: T.mut }}>{label}</span>
      <span style={{ fontSize: 11.5, fontWeight: 700, color: T.green }}>{delta}</span>
    </Card>
  );
}

function TrendCard({ p, fav, toggleFav, onDelete, onEdit, onOpen }) {
  return (
    <Card hover onClick={onOpen} style={{ padding: 10, display: 'flex', flexDirection: 'column', gap: 10, position: 'relative' }}>
      <Cover hue={p.hue} img={p.img} />
      <span style={{
        position: 'absolute', top: 18, left: 18, display: 'inline-flex', alignItems: 'center', gap: 6,
        background: 'rgba(8,8,14,0.75)', borderRadius: 7, padding: '4px 8px',
        fontSize: 10.5, fontWeight: 700, color: '#f1f1f8',
      }}>{(() => {
        const ms = (p.models && p.models.length ? p.models : [p.m]).filter(Boolean);
        return <>
          <span style={{ display: 'inline-flex' }}>{ms.slice(0, 3).map((n, i) => (
            <span key={n} style={{ marginLeft: i ? -5 : 0 }}><MChip name={n} size={13} /></span>
          ))}</span>
          {ms.length > 1 ? `${ms.length} model` : ms[0]}
        </>;
      })()}</span>
      <button onClick={(e) => { e.stopPropagation(); toggleFav(p.id); }} title="Favorite" style={{
        position: 'absolute', top: 18, right: 18, width: 26, height: 26, borderRadius: 7,
        background: 'rgba(8,8,14,0.75)', border: 'none', cursor: 'pointer',
        color: fav ? T.amber : 'rgba(255,255,255,0.55)', fontSize: 13, lineHeight: 1,
      }}>{fav ? '★' : '☆'}</button>
      {onEdit && (
        <button onClick={(e) => { e.stopPropagation(); onEdit(); }} title="Edit prompt" style={{
          position: 'absolute', top: 18, right: 50, width: 26, height: 26, borderRadius: 7,
          background: 'rgba(8,8,14,0.75)', border: 'none', cursor: 'pointer',
          color: 'rgba(255,255,255,0.55)', display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor"
            strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <path d="M11.3 2.2 L13.8 4.7 L5.5 13 L2.5 13.5 L3 10.5 Z" />
            <path d="M9.5 4 L12 6.5" />
          </svg>
        </button>
      )}
      {onDelete && (
        <button onClick={(e) => { e.stopPropagation(); onDelete(); }} title="Move to trash" style={{
          position: 'absolute', top: 18, right: onEdit ? 82 : 50, width: 26, height: 26, borderRadius: 7,
          background: 'rgba(8,8,14,0.75)', border: 'none', cursor: 'pointer',
          color: 'rgba(255,255,255,0.55)', fontSize: 14, lineHeight: 1,
        }}>×</button>
      )}
      <div style={{ padding: '0 6px 6px', display: 'flex', flexDirection: 'column', gap: 5 }}>
        <span style={{ fontSize: 14, fontWeight: 700, color: T.text }}>{p.t}</span>
        <span style={{ fontSize: 11.5, color: T.mut, lineHeight: 1.45 }}>{p.d}</span>
        <span style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 4 }}>
          <Stars r={p.r} />
          <span style={{ fontSize: 11, color: T.dim }}>{p.u} uses</span>
        </span>
      </div>
    </Card>
  );
}

function QuickAction({ glyph, title, sub, onClick }) {
  return (
    <Card hover onClick={onClick} style={{
      flex: 1, padding: '20px 14px', display: 'flex', flexDirection: 'column',
      alignItems: 'center', gap: 9, textAlign: 'center',
    }}>
      <span style={{
        width: 38, height: 38, borderRadius: 10, background: T.vioSoft, border: `1px solid ${T.vio}44`,
        display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#b9a3ff',
        fontSize: 17, fontWeight: 700,
      }}>{glyph}</span>
      <span style={{ fontSize: 13, fontWeight: 700, color: T.text }}>{title}</span>
      <span style={{ fontSize: 11, color: T.dim }}>{sub}</span>
    </Card>
  );
}

// contribution graph ala GitHub — heatmap prompt dibuat per hari (data nyata dari created_at)
function ActivityChart({ lib = [] }) {
  const WEEKS = 16, CELL = 11, GAP = 3, STEP = CELL + GAP, TOP = 14;
  const moLbl = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'];
  const today = new Date(); today.setHours(0, 0, 0, 0);
  const endSat = new Date(today); endSat.setDate(today.getDate() + (6 - today.getDay())); // Sabtu minggu ini
  const start = new Date(endSat); start.setDate(endSat.getDate() - (WEEKS * 7 - 1)); // mundur 16 minggu → jatuh di Minggu
  const key = (d) => d.getFullYear() + '-' + d.getMonth() + '-' + d.getDate();
  const counts = {};
  lib.forEach((p) => { if (p.created) { const d = new Date(p.created); if (!isNaN(d)) counts[key(d)] = (counts[key(d)] || 0) + 1; } });
  const colors = [T.line2, 'rgba(124,92,250,0.30)', 'rgba(124,92,250,0.55)', 'rgba(124,92,250,0.80)', '#8f63f9'];
  const lvl = (c) => (c === 0 ? 0 : c === 1 ? 1 : c <= 2 ? 2 : c <= 4 ? 3 : 4);
  let total = 0;
  const cells = [], months = [];
  let lastMo = -1;
  for (let w = 0; w < WEEKS; w++) {
    for (let dow = 0; dow < 7; dow++) {
      const d = new Date(start); d.setDate(start.getDate() + w * 7 + dow);
      const future = d > today;
      const c = future ? 0 : (counts[key(d)] || 0);
      if (!future) total += c;
      cells.push({ x: w * STEP, y: TOP + dow * STEP, c, future, d });
    }
    const topMonth = new Date(start); topMonth.setDate(start.getDate() + w * 7);
    if (topMonth.getMonth() !== lastMo) { months.push({ x: w * STEP, m: topMonth.getMonth() }); lastMo = topMonth.getMonth(); }
  }
  const W = WEEKS * STEP, H = TOP + 7 * STEP;
  return (
    <div>
      <div style={{ fontSize: 11.5, color: T.mut, marginBottom: 8 }}><b style={{ color: T.text }}>{total}</b> prompt dibuat dalam {WEEKS} minggu terakhir</div>
      <svg width={W} height={H} style={{ display: 'block' }}>
        {months.map((mo, i) => (
          <text key={i} x={mo.x} y={9} fill={T.dim} style={{ fontFamily: T.font, fontSize: 9 }}>{moLbl[mo.m]}</text>
        ))}
        {cells.map((c, i) => (
          <rect key={i} x={c.x} y={c.y} width={CELL} height={CELL} rx={2.5}
            fill={c.future ? 'transparent' : colors[lvl(c.c)]}
            opacity={c.future ? 0 : 1}>
            <title>{c.d.toLocaleDateString('id-ID')}: {c.c} prompt</title>
          </rect>
        ))}
      </svg>
      <div style={{ display: 'flex', alignItems: 'center', gap: 5, marginTop: 8, fontSize: 9.5, color: T.dim }}>
        <span>Sedikit</span>
        {colors.map((c, i) => <span key={i} style={{ width: 10, height: 10, borderRadius: 2.5, background: c }}></span>)}
        <span>Banyak</span>
      </div>
    </div>
  );
}

function RightRail({ lib = [], categories = [] }) {
  // top kategori nyata dari Library
  const catMeta = {}; categories.forEach((c) => { catMeta[c.name] = c; });
  const counts = {};
  lib.forEach((p) => { if (p.cat) counts[p.cat] = (counts[p.cat] || 0) + 1; });
  const total = lib.length || 1;
  const topCats = Object.entries(counts).sort((a, b) => b[1] - a[1]).slice(0, 6)
    .map(([name, n]) => ({ name, pct: Math.round((n / total) * 100) }));
  return (
    <div style={{ width: 264, flex: '0 0 auto', display: 'flex', flexDirection: 'column', gap: 16 }}>
      <Card style={{ padding: 16 }}>
        <SectionTitle>AI Compatibility</SectionTitle>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
          {posModelList.map((m) => (
            <div key={m.n} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '5px 2px' }}>
              <MChip name={m.n} size={18} />
              <span style={{ fontSize: 12.5, color: T.text }}>{m.n}</span>
              <span style={{ marginLeft: 'auto', color: T.green, fontSize: 12, fontWeight: 700 }}>✓</span>
            </div>
          ))}
        </div>
      </Card>
      <Card style={{ padding: 16 }}>
        <SectionTitle>Your Activity</SectionTitle>
        <ActivityChart lib={lib} />
      </Card>
      <Card style={{ padding: 16 }}>
        <SectionTitle>Top Categories</SectionTitle>
        {topCats.length ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 11 }}>
            {topCats.map(({ name, pct }) => {
              const meta = catMeta[name];
              return (
                <div key={name} style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
                  <span style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 11.5 }}>
                    {meta && meta.icon && <span style={{ color: meta.color || T.vio, display: 'flex' }}><IconGlyph name={meta.icon} size={13} color="currentColor" /></span>}
                    <span style={{ color: T.mut, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{name}</span>
                    <span style={{ marginLeft: 'auto', color: T.text, fontWeight: 700, flex: '0 0 auto' }}>{pct}%</span>
                  </span>
                  <span style={{ height: 5, borderRadius: 3, background: T.line, overflow: 'hidden' }}>
                    <span style={{ display: 'block', height: '100%', width: `${pct}%`, borderRadius: 3, background: (meta && meta.color) ? meta.color : T.grad }}></span>
                  </span>
                </div>
              );
            })}
          </div>
        ) : (
          <div style={{ fontSize: 12, color: T.dim, padding: '12px 0' }}>Belum ada prompt untuk dihitung.</div>
        )}
      </Card>
    </div>
  );
}

function Dashboard({ lib, favs, toggleFav, setRoute, theme, openPrompt, categories = [], onImport, cap = { edit: true } }) {
  return (
    <div style={{ display: 'flex', gap: 20, padding: 22, alignItems: 'flex-start' }}>
      <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 22 }}>
        <div style={{
          position: 'relative', overflow: 'hidden', borderRadius: 16,
          border: `1px solid ${T.line}`, background: T.card, padding: '26px 24px',
        }}>
          <ThreeHero theme={theme} />
          <div style={{ position: 'relative' }}>
            <div style={{ fontSize: 22, fontWeight: 800, color: T.text, letterSpacing: '-0.01em' }}>👋 Welcome back, Jade!</div>
            <div style={{ fontSize: 13, color: T.mut, marginTop: 4 }}>Ready to supercharge your AI workflow today?</div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 14 }}>
          <StatCard color={T.vio} value={String(lib.length)} label="Total Prompts" delta="+124 this week" />
          <StatCard color="#60a5fa" value={String(new Set(lib.map((p) => p.cat)).size)} label="Categories" delta="+3 new" />
          <StatCard color="#f472b6" value={String(favs.size)} label="Favorites" delta="+18 this week" />
          <StatCard color="#34d399" value={String(posAgents.length)} label="AI Agents" delta="+7 new" />
        </div>
        <div>
          <SectionTitle right={
            <a href="#" onClick={(e) => { e.preventDefault(); setRoute('library'); }}
              style={{ fontSize: 12.5, fontWeight: 600, color: T.vio, textDecoration: 'none' }}>View all</a>
          }>🔥 Trending Prompts</SectionTitle>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14 }}>
            {lib.slice(0, 3).map((p) => (
              <TrendCard key={p.id} p={p} fav={favs.has(p.id)} toggleFav={toggleFav}
                onOpen={openPrompt && (() => openPrompt(p))} />
            ))}
          </div>
        </div>
        <div>
          <SectionTitle>Quick Actions</SectionTitle>
          <div style={{ display: 'flex', gap: 14 }}>
            <QuickAction glyph="+" title="Create Prompt" sub="Buat prompt dari nol" onClick={() => setRoute('library')} />
            <QuickAction glyph="✦" title="Generate Prompt" sub="Buat prompt dengan AI" onClick={() => setRoute('generator')} />
            <QuickAction glyph="▦" title="Prompt Builder" sub="Drag & drop builder" onClick={() => setRoute('builder')} />
            <QuickAction glyph="↥" title="Import Prompt" sub="Import dari file JSON" onClick={() => (cap.edit && onImport ? onImport() : setRoute('library'))} />
          </div>
        </div>
      </div>
      <RightRail lib={lib} categories={categories} />
    </div>
  );
}

Object.assign(window, { Dashboard, StatCard, TrendCard, ActivityChart });
