// One row in the review queue. Self-contained: cover, title, status
// pills, vote tally, action row (vote / admin force). Plays through
// the global NowPlayingBar — the per-card "play" button just calls
// onPlay(sub) which the queue wires into AudioService.
//
// State flow (top to bottom in the rendered card):
//
//   • Cover with click-to-play overlay (becomes a pause icon if this
//     card is the currently-playing track).
//   • Title + status pill + copyright-state pills (pending / flagged).
//   • Artist / duration / submitted-time meta row.
//   • Vote tally chip and ratio bar.
//   • Admin's three-dot menu (AdminMenu component).
//   • Expand toggle.
//
// Below that, two conditional sections:
//
//   • Action bar with vote buttons (or block reason if can't vote /
//     copyright pending / own track).
//   • Expanded vote breakdown — list of who voted which way.

function SubmissionCard({ sub, me, isPlaying, expanded, onToggle, onPlay, onVote, onForceAccept, onForceReject, onBlockUser, onCopyrightSkip, refresh }) {
  const submitter = playerByIdent(sub.identifier);
  const t = tally(sub);
  const myVote = sub.votes.find(v => v.identifier === me.identifier)?.vote;
  const isAdmin = canForceAccept(me);
  const copyrightPending = sub.copyrightStatus === 'pending';
  const copyrightFlagged = sub.copyrightStatus === 'flagged';

  // Admins can also vote on their own submissions (server allows it).
  // For everyone else the self-vote ban + copyright gate stays.
  const eligible = canVote(me)
    && (me.identifier !== sub.identifier || isAdmin)
    && sub.status === 'pending'
    && (!copyrightPending || isAdmin)
    && (!copyrightFlagged || isAdmin);

  // Border accent — flagged tracks get a coral edge so they pop out
  // of the queue even before you've read the title. Pending-cr is
  // gold (warm warning). Otherwise plain.
  const cardBorder = copyrightFlagged ? 'rgba(255,110,138,0.4)'
                   : copyrightPending ? 'rgba(255,194,103,0.4)'
                   : null;
  const cardOrb    = copyrightFlagged ? 'var(--danger)'
                   : copyrightPending ? 'var(--warning)'
                   : 'var(--lila-500)';

  return (
    <Glass radius={20} padding={0} accent={cardBorder} orb={cardOrb}
      style={{ overflow: 'hidden' }}
    >
      {/* Top row: cover (with play overlay) + title block + tally + admin menu + expand */}
      <div style={{ display: 'flex', gap: 18, padding: 18, alignItems: 'center' }}>

        {/* Cover with click-to-play overlay. Hover surfaces a play
            icon. Active (currently playing in this card) keeps the
            pause icon visible without hover. */}
        <div style={{ position: 'relative', flexShrink: 0 }}>
          <Cover colors={sub.cover} src={sub.coverUrl} size={92} radius={16}/>
          <button
            onClick={() => onPlay(sub.id)}
            aria-label={isPlaying ? 'Pausieren' : 'Abspielen'}
            style={{
              position: 'absolute', inset: 0, borderRadius: 16, border: 'none',
              background: 'rgba(17,7,36,0.55)', backdropFilter: 'blur(4px)',
              WebkitBackdropFilter: 'blur(4px)',
              cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: 'var(--foam)', opacity: isPlaying ? 1 : 0,
              transition: 'opacity 150ms var(--ease-out)',
            }}
            onMouseEnter={(e) => { e.currentTarget.style.opacity = 1; }}
            onMouseLeave={(e) => { if (!isPlaying) e.currentTarget.style.opacity = 0; }}
          >
            <ApIcon name={isPlaying ? 'pause' : 'play'} size={26}/>
          </button>
        </div>

        {/* Title + meta. Submitter avatar + name sits below the
            primary meta line so it doesn't compete with the title. */}
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6, flexWrap: 'wrap' }}>
            <div style={{ fontSize: 19, fontWeight: 700, letterSpacing: '-0.01em', color: 'var(--foam)' }}>
              {sub.title}
            </div>
            <StatusPill status={sub.status}/>
            {copyrightPending && (
              <span
                title="Der Hintergrund-Worker prüft den Track auf Übereinstimmungen mit kommerziellen Katalogen (Spotify/Apple Music)."
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 5, padding: '4px 10px',
                  borderRadius: 999, background: 'rgba(255,194,103,0.16)', color: 'var(--warning)',
                  fontSize: 11, fontWeight: 700, letterSpacing: 0.3, textTransform: 'uppercase',
                }}>
                <ApIcon name="clock" size={10}/> Richtlinien-Check
              </span>
            )}
            {copyrightFlagged && (
              <span
                title={sub.copyrightMatch
                  ? `Übereinstimmung: ${sub.copyrightMatch.title} – ${sub.copyrightMatch.artist} (${sub.copyrightMatch.source})`
                  : 'Als kommerzieller Track erkannt.'}
                style={{
                  display: 'inline-flex', alignItems: 'center', gap: 5, padding: '4px 10px',
                  borderRadius: 999, background: 'rgba(255,110,138,0.18)', color: 'var(--danger)',
                  fontSize: 11, fontWeight: 700, letterSpacing: 0.3, textTransform: 'uppercase',
                }}>
                <ApIcon name="shield" size={10}/> Urheberrechtlich geschützt
              </span>
            )}
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: 'var(--fg-2)', marginBottom: 8 }}>
            <ArtistLink identifier={sub.identifier} name={sub.artist} size={13}/>
            <span style={{ color: 'var(--fg-4)' }}>·</span>
            <span style={{ fontVariantNumeric: 'tabular-nums' }}>{fmt(sub.duration)}</span>
            <span style={{ color: 'var(--fg-4)' }}>·</span>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
              <ApIcon name="clock" size={11}/> {timeAgo(sub.submittedAt)}
            </span>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11.5, color: 'var(--fg-3)' }}>
            Hochgeladen von <Avatar player={submitter} size={20}/>
            <PlayerName player={submitter} size={11.5} opacity={1}/>
          </div>
          {copyrightFlagged && sub.copyrightMatch && (
            <div style={{
              marginTop: 10, padding: '8px 12px', borderRadius: 10,
              background: 'rgba(255,110,138,0.08)', border: '1px solid rgba(255,110,138,0.3)',
              fontSize: 12, color: 'var(--fg-2)',
            }}>
              Übereinstimmung: <b style={{ color: 'var(--foam)' }}>{sub.copyrightMatch.title}</b>
              {' – '}{sub.copyrightMatch.artist}
              {' '}<span style={{ color: 'var(--fg-3)' }}>({sub.copyrightMatch.source})</span>
            </div>
          )}
        </div>

        {/* Vote tally + ratio bar */}
        <div style={{
          display: 'flex', flexDirection: 'column', alignItems: 'flex-end',
          gap: 8, minWidth: 140, flexShrink: 0,
        }}>
          <div style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            fontVariantNumeric: 'tabular-nums', fontWeight: 700, fontSize: 14,
          }}>
            <span style={{ color: 'var(--success)' }}>{t.accepts}</span>
            <span style={{ color: 'var(--fg-4)' }}>/</span>
            <span style={{ color: 'var(--danger)' }}>{t.rejects}</span>
            <span style={{ color: 'var(--fg-3)', fontWeight: 500, fontSize: 12 }}>
              · {t.total}/{REQUIRED_VOTES}
            </span>
          </div>
          <div style={{
            width: 120, height: 6, borderRadius: 3,
            background: 'rgba(196,154,255,0.16)', overflow: 'hidden',
          }}>
            <div style={{
              height: '100%', width: `${Math.round(t.ratio * 100)}%`,
              background: t.ratio >= ACCEPT_THRESHOLD ? 'var(--success)' : 'var(--warning)',
              transition: 'width 240ms var(--ease-out)',
            }}/>
          </div>
          <div style={{ fontSize: 11, color: 'var(--fg-3)', fontVariantNumeric: 'tabular-nums' }}>
            {Math.round(t.ratio * 100)}% · {Math.round(ACCEPT_THRESHOLD * 100)}% nötig
          </div>
        </div>

        {/* Admin's overflow menu (edit metadata, regen lyrics/waveform,
            delete, override status). Lives in admin-menu.jsx — moved
            out of this file so it doesn't bloat the card. */}
        {isAdmin && refresh && <AdminMenu sub={sub} refresh={refresh}/>}

        {/* Expand toggle for the vote breakdown */}
        <button onClick={onToggle}
          aria-label={expanded ? 'Stimmen einklappen' : 'Stimmen ausklappen'}
          style={{
            background: 'transparent', border: 'none', cursor: 'pointer',
            color: 'var(--fg-3)', padding: 6, display: 'flex',
            transform: expanded ? 'rotate(180deg)' : 'none',
            transition: 'transform 200ms var(--ease-out)',
          }}>
          <ApIcon name="caret" size={18}/>
        </button>
      </div>

      {/* Action bar — depends on track status + voter eligibility */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 10, padding: '14px 20px',
        background: 'rgba(17,7,36,0.45)',
        borderTop: '1px solid var(--border-hairline)',
        flexWrap: 'wrap',
      }}>
        {sub.status !== 'pending' ? (
          <DecidedRow sub={sub} isAdmin={isAdmin} onCopyrightSkip={onCopyrightSkip}/>
        ) : !canVote(me) ? (
          <div style={{ flex: 1, fontSize: 12.5, color: 'var(--fg-3)' }}>
            Abstimmen ist verifizierten Künstlern und Whitelist-Rollen vorbehalten.
          </div>
        ) : me.identifier === sub.identifier && !isAdmin ? (
          <div style={{ flex: 1, fontSize: 12.5, color: 'var(--fg-3)' }}>
            Du kannst nicht über deinen eigenen Track abstimmen.
          </div>
        ) : copyrightPending && !isAdmin ? (
          <div style={{ flex: 1, fontSize: 12.5, color: 'var(--fg-2)', display: 'flex', alignItems: 'center', gap: 8 }}>
            <ApIcon name="clock" size={14} color="var(--warning)"/>
            Song wird auf Richtlinienverstöße überprüft — Abstimmung ist solange gesperrt.
          </div>
        ) : copyrightFlagged && !isAdmin ? (
          <div style={{ flex: 1, fontSize: 12.5, color: 'var(--fg-2)', display: 'flex', alignItems: 'center', gap: 8 }}>
            <ApIcon name="shield" size={14} color="var(--danger)"/>
            Als kommerzieller Track erkannt — Voting gesperrt.
            {sub.copyrightMatch && (
              <span style={{ color: 'var(--fg-3)' }}>
                ({sub.copyrightMatch.title} – {sub.copyrightMatch.artist}, {sub.copyrightMatch.source})
              </span>
            )}
          </div>
        ) : (
          <ActionRow
            sub={sub} me={me} myVote={myVote} eligible={eligible} isAdmin={isAdmin}
            copyrightPending={copyrightPending} copyrightFlagged={copyrightFlagged}
            onVote={onVote} onForceAccept={onForceAccept} onForceReject={onForceReject}
            onBlockUser={onBlockUser} onCopyrightSkip={onCopyrightSkip}
          />
        )}
      </div>

      {/* Expanded vote breakdown */}
      {expanded && sub.votes.length > 0 && (
        <div style={{
          padding: '14px 20px',
          borderTop: '1px solid var(--border-hairline)',
          background: 'rgba(17,7,36,0.35)',
        }}>
          <Eyebrow style={{ marginBottom: 10 }}>Stimmen ({sub.votes.length})</Eyebrow>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 8 }}>
            {sub.votes.map((v, i) => {
              const voter = v.identifier ? playerByIdent(v.identifier) : null;
              return (
                <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12 }}>
                  {voter && <Avatar player={voter} size={22}/>}
                  <PlayerName player={voter || { name: 'Anonym', identifier: '', group: 'user' }}
                    size={12} opacity={0.85}/>
                  <span style={{
                    marginLeft: 'auto',
                    color: v.vote === 'accept' ? 'var(--success)' : 'var(--danger)',
                    fontWeight: 700,
                  }}>
                    {v.vote === 'accept' ? '✓' : '✕'}
                  </span>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </Glass>
  );
}

// "Track has been decided" row. Shown for status !== 'pending'.
// Renders who/how decided, plus an admin override that can pull a
// copyright-rejected track back into voting.
function DecidedRow({ sub, isAdmin, onCopyrightSkip }) {
  return (
    <div style={{ flex: 1, fontSize: 12.5, color: 'var(--fg-2)', display: 'flex', alignItems: 'center', gap: 6 }}>
      {sub.status === 'accepted' && (
        <>
          <ApIcon name="check" size={14} color="var(--success)"/>
          {sub.decidedBy === 'auto'
            ? 'Automatisch durch Community-Vote veröffentlicht'
            : <>Veröffentlicht von <PlayerName player={playerByIdent(sub.decidedBy)} size={12.5} opacity={1}/></>}
        </>
      )}
      {sub.status === 'rejected' && (
        <>
          <ApIcon name="x" size={14} color="var(--danger)"/>
          {sub.decidedBy === 'copyright-check'
            ? 'Automatisch abgelehnt: Urheberrecht'
            : 'Abgelehnt'}
        </>
      )}
      {isAdmin && sub.decidedBy === 'copyright-check' && (
        <Button
          variant="warning" size="sm" icon="shield"
          onClick={() => onCopyrightSkip && onCopyrightSkip(sub.id)}
          style={{ marginLeft: 'auto' }}
          title="AudD-Reject überspringen und zurück in die Voting-Queue"
        >
          Rechtlichen Check überspringen
        </Button>
      )}
    </div>
  );
}

// Vote + admin action cluster. Three buttons (Dafür / Dagegen + your
// vote indicator) on the left; admin override cluster on the right.
function ActionRow({ sub, me, myVote, eligible, isAdmin, copyrightPending, copyrightFlagged, onVote, onForceAccept, onForceReject, onBlockUser, onCopyrightSkip }) {
  return (
    <>
      <Button
        variant={myVote === 'accept' ? 'success' : 'secondary'} size="sm" icon="thumb-up"
        disabled={!eligible}
        onClick={() => onVote(sub.id, 'accept')}
      >
        Dafür
      </Button>
      <Button
        variant={myVote === 'reject' ? 'danger' : 'secondary'} size="sm" icon="thumb-down"
        disabled={!eligible}
        onClick={() => onVote(sub.id, 'reject')}
      >
        Dagegen
      </Button>
      {myVote && (
        <span style={{ fontSize: 11.5, color: 'var(--fg-3)' }}>
          Deine Stimme: <b style={{ color: myVote === 'accept' ? 'var(--success)' : 'var(--danger)' }}>
            {myVote === 'accept' ? 'dafür' : 'dagegen'}
          </b>
        </span>
      )}
      <div style={{ flex: 1 }}/>
      {isAdmin && (
        <>
          {(copyrightPending || copyrightFlagged) && (
            <Button variant="warning" size="sm" icon="shield"
              onClick={() => onCopyrightSkip && onCopyrightSkip(sub.id)}
              title="AudD-Prüfung überspringen — Voting wird freigegeben">
              Check überspringen
            </Button>
          )}
          <Button variant="danger" size="sm" icon="ban"
            onClick={() => onBlockUser(sub.id)}
            title="Creator sperren + Track ablehnen">
            User sperren
          </Button>
          <Button variant="danger" size="sm" icon="x"
            onClick={() => onForceReject(sub.id)}>
            Ablehnen
          </Button>
          <Button variant="reward" size="sm" icon="bolt"
            onClick={() => onForceAccept(sub.id)}
            title={(copyrightPending || copyrightFlagged) ? 'Veröffentlicht den Track sofort — Copyright-Check wird automatisch übersprungen' : ''}>
            Veröffentlichen
          </Button>
        </>
      )}
    </>
  );
}

window.SubmissionCard = SubmissionCard;
