// Reusable character-sheet renderer for the char.profile shape returned by
// /public/shard/char/:serial. Presentational only — the parent handles loading
// and errors. Styled with the shared theme vocabulary (panel/grid/stat tiles).
//
// `moderation` opts in the in-game kick/ban controls for the character's account;
// they self-gate to staff (ShardAccountActions), so passing it from a page a
// player can reach is safe.

import ShardAccountActions from './ShardAccountActions.jsx'

const RESIST_LABELS = { phys: 'Physical', fire: 'Fire', cold: 'Cold', pois: 'Poison', energy: 'Energy' }

// The char.profile `titles` block (Protocol 2.0). fameKarma/skill are already
// computed display strings; reward entries may be a cliloc NUMBER-as-string or a
// literal string. Without a cliloc table on the site we can only show literals, so
// numeric reward entries are skipped rather than shown as a raw number. Returns a
// de-duped list of human-readable title chips.
function displayTitles(titles) {
  if (!titles) return []
  const out = []
  if (titles.fameKarma) out.push(titles.fameKarma)
  if (titles.skill) out.push(titles.skill)
  const reward = Array.isArray(titles.reward) ? titles.reward : []
  const sel = typeof titles.selected === 'number' ? titles.selected : -1
  // Prefer the selected reward title; fall back to the first literal one.
  const candidate = sel >= 0 && sel < reward.length ? reward[sel] : reward.find((r) => r && !/^\d+$/.test(String(r)))
  if (candidate && !/^\d+$/.test(String(candidate))) out.push(String(candidate))
  return [...new Set(out.filter(Boolean))]
}

function TitleChip({ children, tone = 'var(--muted)' }) {
  return (
    <span
      className="sans"
      style={{
        fontSize: '0.72rem', padding: '3px 9px', borderRadius: 999,
        border: `1px solid ${tone}55`, color: tone, whiteSpace: 'nowrap',
      }}
    >
      {children}
    </span>
  )
}

function StatTile({ value, label }) {
  return (
    <div className="panel" style={{ padding: '14px 12px', textAlign: 'center' }}>
      <div className="display" style={{ fontSize: '1.35rem', color: 'var(--head)' }}>{value}</div>
      <div className="sans" style={{ color: 'var(--accent)', fontSize: '0.64rem', letterSpacing: '0.12em', textTransform: 'uppercase', marginTop: 4 }}>{label}</div>
    </div>
  )
}

function Vital({ label, cur, max }) {
  const pct = max ? Math.min(100, Math.round((cur / max) * 100)) : 0
  return (
    <div className="panel" style={{ padding: '12px 14px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 8 }}>
        <span className="sans" style={{ color: 'var(--accent)', fontSize: '0.64rem', letterSpacing: '0.12em', textTransform: 'uppercase' }}>{label}</span>
        <span className="display" style={{ color: 'var(--head)', fontSize: '0.95rem' }}>{cur ?? '—'}<span className="dim" style={{ fontSize: '0.8rem' }}> / {max ?? '—'}</span></span>
      </div>
      <div style={{ height: 6, borderRadius: 999, background: 'var(--line)', overflow: 'hidden' }}>
        <div style={{ width: `${pct}%`, height: '100%', background: 'var(--accent)' }} />
      </div>
    </div>
  )
}

export default function CharacterSheet({ char, moderation = false }) {
  if (!char) return null
  const stats = char.stats || {}
  const resist = stats.resist || {}
  // Skills the character actually has, best first.
  const skills = (char.skills || [])
    .filter((s) => (s.value || s.base || 0) > 0)
    .sort((a, b) => (b.value || 0) - (a.value || 0))
  const equipment = char.equipment || []

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
      {/* Identity */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap' }}>
        <h2 className="display" style={{ margin: 0, fontSize: '1.6rem', color: 'var(--head)' }}>{char.name || 'Unknown'}</h2>
        {char.title && <span className="sans" style={{ color: 'var(--muted)', fontSize: '0.9rem' }}>{char.title}</span>}
        <span
          className="sans"
          style={{
            display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 10px', borderRadius: 999,
            border: '1px solid var(--line)', fontSize: '0.74rem',
            color: char.online ? '#7fd0a4' : 'var(--muted)',
          }}
        >
          <span style={{ width: 8, height: 8, borderRadius: '50%', background: char.online ? '#7fd0a4' : 'var(--dim)' }} />
          {char.online ? 'Online' : 'Offline'}
        </span>
        <span className="sans dim" style={{ fontSize: '0.76rem', marginLeft: 'auto' }}>{char.serial}</span>
      </div>

      {/* Titles + standing (guild led / governorship) — all optional */}
      {(displayTitles(char.titles).length > 0 || char.guild || (char.governorOf && char.governorOf.length > 0)) && (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: -8 }}>
          {char.governorOf && char.governorOf.map((city) => (
            <TitleChip key={`gov-${city}`} tone="#c9a24b">Governor of {city}</TitleChip>
          ))}
          {char.guild && (
            <TitleChip tone="var(--accent)">
              Guildmaster{char.guild.abbr ? `, [${char.guild.abbr}]` : ''} {char.guild.name}
            </TitleChip>
          )}
          {displayTitles(char.titles).map((t) => <TitleChip key={t}>{t}</TitleChip>)}
        </div>
      )}

      {/* Staff moderation for this character's account (self-gates to staff). */}
      {moderation && char.acct && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, padding: '12px 14px', border: '1px solid var(--line-soft)', borderRadius: 10, background: 'rgba(255,255,255,0.02)' }}>
          <span className="sans dim" style={{ fontSize: '0.76rem' }}>Account <strong style={{ color: 'var(--ink)' }}>{char.acct}</strong></span>
          <ShardAccountActions account={char.acct} />
        </div>
      )}

      {/* Core stats */}
      <section>
        <div className="field-label" style={{ marginBottom: 8 }}>Attributes</div>
        <div className="grid-3" style={{ gap: 12 }}>
          <StatTile value={stats.str ?? '—'} label="Strength" />
          <StatTile value={stats.dex ?? '—'} label="Dexterity" />
          <StatTile value={stats.int ?? '—'} label="Intelligence" />
        </div>
        <div className="grid-3" style={{ gap: 12, marginTop: 12 }}>
          <Vital label="Hits" cur={stats.hits} max={stats.hitsMax} />
          <Vital label="Mana" cur={stats.mana} max={stats.manaMax} />
          <Vital label="Stamina" cur={stats.stam} max={stats.stamMax} />
        </div>
      </section>

      {/* Resistances */}
      {Object.keys(resist).length > 0 && (
        <section>
          <div className="field-label" style={{ marginBottom: 8 }}>Resistances</div>
          <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
            {['phys', 'fire', 'cold', 'pois', 'energy'].map((k) => (
              <div key={k} className="panel" style={{ padding: '10px 16px', textAlign: 'center', minWidth: 84 }}>
                <div className="display" style={{ color: 'var(--head)', fontSize: '1.1rem' }}>{resist[k] ?? 0}</div>
                <div className="sans" style={{ color: 'var(--muted)', fontSize: '0.66rem', textTransform: 'uppercase', letterSpacing: '0.08em', marginTop: 2 }}>{RESIST_LABELS[k]}</div>
              </div>
            ))}
          </div>
        </section>
      )}

      {/* Skills */}
      {skills.length > 0 && (
        <section>
          <div className="field-label" style={{ marginBottom: 8 }}>Skills <span className="dim">({skills.length})</span></div>
          <div className="grid-2" style={{ gap: '8px 18px' }}>
            {skills.map((s) => {
              const cap = s.cap || 100
              const pct = Math.min(100, Math.round(((s.value || 0) / cap) * 100))
              return (
                <div key={s.n}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 3 }}>
                    <span className="sans" style={{ color: 'var(--ink)', fontSize: '0.86rem' }}>{s.n}</span>
                    <span className="sans" style={{ color: 'var(--head)', fontSize: '0.82rem' }}>{s.value}</span>
                  </div>
                  <div style={{ height: 4, borderRadius: 999, background: 'var(--line)', overflow: 'hidden' }}>
                    <div style={{ width: `${pct}%`, height: '100%', background: 'var(--accent)' }} />
                  </div>
                </div>
              )
            })}
          </div>
        </section>
      )}

      {/* Equipment */}
      {equipment.length > 0 && (
        <section>
          <div className="field-label" style={{ marginBottom: 8 }}>Equipment</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {equipment.map((it) => (
              <div key={it.serial} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '10px 14px', border: '1px solid var(--line)', borderRadius: 8 }}>
                <span style={{ flex: 'none', width: 22, height: 22, borderRadius: 5, border: '1px solid var(--line)', background: 'rgba(255,255,255,0.05)' }} />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div className="sans" style={{ color: 'var(--head)', fontSize: '0.88rem' }}>{it.layer || 'Item'}</div>
                  <div className="sans dim" style={{ fontSize: '0.74rem' }}>id {it.itemId}{it.hue ? ` · hue ${it.hue}` : ''}</div>
                </div>
                {it.mods && Object.keys(it.mods).length > 0 && (
                  <div className="sans" style={{ display: 'flex', gap: 6, flexWrap: 'wrap', justifyContent: 'flex-end', maxWidth: '55%' }}>
                    {Object.entries(it.mods).map(([k, v]) => (
                      <span key={k} className="pill" style={{ fontSize: '0.7rem', padding: '2px 8px' }}>{k} {v}</span>
                    ))}
                  </div>
                )}
              </div>
            ))}
          </div>
        </section>
      )}
    </div>
  )
}
