// Per-submission admin power-tools dropdown. Sits behind a kebab button on
// every card the admin sees, both in the queue and in the decided list.
//
// All actions go through the same shared handlers — when refreshing the
// list, the parent passes a `refresh` callback that reloads /api/submissions.

function AdminMenu({ sub, refresh, dark }) {
  const [open, setOpen] = React.useState(false);
  // Anchor rect — recomputed every time the menu opens (and on scroll/resize
  // while open) so the dropdown stays glued to the kebab button even if the
  // page below it shifts.
  const [rect, setRect] = React.useState(null);
  const buttonRef = React.useRef(null);
  const menuRef = React.useRef(null);

  const reposition = React.useCallback(() => {
    if (!buttonRef.current) return;
    setRect(buttonRef.current.getBoundingClientRect());
  }, []);

  // Click-outside to close. Both refs count as "inside" — the button to allow
  // toggling, the menu so a click inside it doesn't auto-close before the
  // action handler fires.
  React.useEffect(() => {
    if (!open) return;
    reposition();
    const onClick = (e) => {
      if (buttonRef.current?.contains(e.target)) return;
      if (menuRef.current?.contains(e.target)) return;
      setOpen(false);
    };
    const onScroll = () => reposition();
    setTimeout(() => document.addEventListener('click', onClick), 0);
    window.addEventListener('scroll', onScroll, true);
    window.addEventListener('resize', onScroll);
    return () => {
      document.removeEventListener('click', onClick);
      window.removeEventListener('scroll', onScroll, true);
      window.removeEventListener('resize', onScroll);
    };
  }, [open, reposition]);

  const guarded = (label, fn) => async () => {
    setOpen(false);
    if (!confirm(label)) return;
    try { await fn(); await refresh(); }
    catch (e) { toast.error(e.message); }
  };

  const onDelete = guarded(
    'Diesen Track KOMPLETT löschen?\n\nDB-Eintrag, CDN-Dateien und (falls veröffentlicht) der Eintrag im FiveM-Katalog werden entfernt. Nicht rückgängig.',
    async () => {
      await Api.deleteSubmission(sub.id);
      AudioService.stop();
      toast.success('Track gelöscht.');
    },
  );

  const overrideTo = (target, label) => guarded(
    `Status auf „${label}" ändern?` + (target === 'pending' ? '\n\nDer Track geht zurück in die Prüfung.' : ''),
    async () => {
      // Status flips can move the card out of the visible filter (e.g.
      // pending → accepted leaves the review queue). Kill any audition
      // first so playback doesn't continue without a play/pause surface.
      if (AudioService.get().currentId === sub.id) AudioService.stop();
      await Api.overrideStatus(sub.id, target);
      toast.success(`Status: ${label}.`);
    },
  );

  // Re-trigger lyrics transcription. Fire-and-forget — the worker picks
  // it up on its next 15s poll. Toast tells the admin it's queued.
  const onRegenLyrics = guarded(
    'Lyrics neu generieren?\n\nDer alte Songtext wird verworfen, der Track wandert in die Transkriptions-Warteschlange. Die neue Version erscheint in 15-60 Sekunden ingame.',
    async () => {
      await Api.regenerateLyrics(sub.id);
      toast.success('Lyrics werden neu generiert.');
    },
  );

  // Re-extract waveform peaks. Synchronous on the server side — the
  // webpanel downloads the audio fresh from CDN, runs ffmpeg, posts back.
  // Confirm dialog flags the ~1-3 s wait so the admin doesn't think the
  // page hung.
  const onRegenWaveform = guarded(
    'Waveform neu generieren?\n\nDer Track wird vom CDN nachgeladen und neu vermessen. Dauert 1-3 Sekunden.',
    async () => {
      await Api.regenerateWaveform(sub.id);
      toast.success('Waveform aktualisiert.');
    },
  );

  const onEdit = async () => {
    setOpen(false);
    const newTitle  = prompt('Neuer Titel:', sub.title);
    if (newTitle === null) return;
    const newArtist = prompt('Neuer Artist-Name:', sub.artist);
    if (newArtist === null) return;
    const fields = {};
    if (newTitle.trim()  && newTitle.trim()  !== sub.title)  fields.title  = newTitle.trim();
    if (newArtist.trim() && newArtist.trim() !== sub.artist) fields.artist = newArtist.trim();
    if (Object.keys(fields).length === 0) return;
    try {
      await Api.editSubmission(sub.id, fields);
      await refresh();
      toast.success('Metadaten aktualisiert.');
    } catch (e) {
      toast.error(e.message);
    }
  };

  // The dropdown is rendered into <body> via a portal so it escapes any
  // ancestor `overflow: hidden` (the submission card uses overflow:hidden to
  // clip the cover; we don't want it clipping our menu too).
  const MENU_WIDTH = 240;
  const menu = open && rect ? (
    <div
      ref={menuRef}
      style={{
        position: 'fixed',
        // Right-align with the kebab button. Clamp to viewport so the menu
        // never spills off the left edge on narrow screens.
        left:  Math.max(8, rect.right - MENU_WIDTH),
        top:   rect.bottom + 6,
        width: MENU_WIDTH,
        zIndex: 1000,
        background: dark ? 'rgba(20,15,32,0.94)' : 'rgba(255,255,255,0.95)',
        backdropFilter: 'blur(20px) saturate(140%)',
        WebkitBackdropFilter: 'blur(20px) saturate(140%)',
        border: dark ? '1px solid rgba(255,255,255,0.12)' : '1px solid rgba(0,0,0,0.08)',
        borderRadius: 12, padding: 6,
        boxShadow: '0 12px 40px rgba(0,0,0,0.45)',
        display: 'flex', flexDirection: 'column', gap: 2,
      }}
    >
      <MenuLabel>Status ändern</MenuLabel>
      {sub.status !== 'pending'  && <MenuItem icon="clock"  color="#fbbf24" onClick={overrideTo('pending',  'In Prüfung')}>Zurück zur Prüfung</MenuItem>}
      {sub.status !== 'accepted' && <MenuItem icon="check"  color="#34d399" onClick={overrideTo('accepted', 'Veröffentlicht')}>Veröffentlichen</MenuItem>}
      {sub.status !== 'rejected' && <MenuItem icon="x"      color="#f87171" onClick={overrideTo('rejected', 'Abgelehnt')}>Ablehnen</MenuItem>}
      <MenuDivider/>
      <MenuLabel>Metadaten</MenuLabel>
      <MenuItem icon="image" color="#a78bfa" onClick={onEdit}>Titel / Artist bearbeiten</MenuItem>
      <MenuDivider/>
      <MenuLabel>Neu generieren</MenuLabel>
      <MenuItem icon="music" color="#3eb8ff" onClick={onRegenLyrics}>Lyrics neu machen</MenuItem>
      <MenuItem icon="wave"  color="#a78bfa" onClick={onRegenWaveform}>Waveform neu machen</MenuItem>
      <MenuDivider/>
      <MenuItem icon="x" color="#f87171" danger onClick={onDelete}>Komplett löschen</MenuItem>
    </div>
  ) : null;

  return (
    <div style={{ position: 'relative', display: 'inline-flex' }}>
      <button
        ref={buttonRef}
        onClick={(e) => { e.stopPropagation(); setOpen(o => !o); }}
        title="Admin-Aktionen"
        style={{
          width: 32, height: 32, borderRadius: 8,
          background: open
            ? 'rgba(251,191,36,0.18)'
            : (dark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.04)'),
          border: open
            ? '1px solid rgba(251,191,36,0.5)'
            : (dark ? '1px solid rgba(255,255,255,0.1)' : '1px solid rgba(0,0,0,0.08)'),
          color: open ? '#fbbf24' : 'inherit',
          cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
          padding: 0,
        }}
      >
        <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
          <circle cx="5"  cy="12" r="1.7"/>
          <circle cx="12" cy="12" r="1.7"/>
          <circle cx="19" cy="12" r="1.7"/>
        </svg>
      </button>
      {menu && ReactDOM.createPortal(menu, document.body)}
    </div>
  );
}

function MenuLabel({ children }) {
  return (
    <div style={{
      fontSize: 10, fontWeight: 700, letterSpacing: 0.6, textTransform: 'uppercase',
      opacity: 0.45, padding: '8px 10px 2px',
    }}>{children}</div>
  );
}

function MenuDivider() {
  return <div style={{ height: 1, background: 'rgba(255,255,255,0.08)', margin: '4px 0' }}/>;
}

function MenuItem({ icon, color, danger, onClick, children }) {
  const [hover, setHover] = React.useState(false);
  return (
    <button
      onClick={onClick}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        display: 'flex', alignItems: 'center', gap: 10,
        padding: '8px 10px', borderRadius: 8,
        background: hover
          ? (danger ? 'rgba(239,68,68,0.15)' : 'rgba(255,255,255,0.06)')
          : 'transparent',
        border: 'none', cursor: 'pointer',
        color: 'inherit', fontSize: 13, fontWeight: 500, textAlign: 'left',
      }}
    >
      <ApIcon name={icon} size={14} color={color}/>
      <span style={{ color: danger ? '#f87171' : 'inherit', flex: 1 }}>{children}</span>
    </button>
  );
}

window.AdminMenu = AdminMenu;
