// profile-pieces.jsx — Page-specific primitives for the Profile module.
//
// Sprint v1.7 · Profile. All public components carry the `pf-` CSS prefix.
//
// Conventions (locked):
//   • Token-only — no new CSS variables. Every color/spacing/radius comes
//     from design-system/tokens.css or the canonical fallback palette already
//     used by leaderboard-pieces.jsx / shop-pieces.jsx.
//   • Logical properties (margin-inline-*, inset-inline-*, padding-block-*, …)
//     so RTL/LTR flip is automatic. dir="rtl" is always set on the page
//     container, not here.
//   • transform + opacity only for animations (never height/width tweens).
//   • All strings flow through PROF_I18N[locale] (profile-data.jsx).
//   • Numbers via window.toLocaleDigits (card-v2.jsx).
//   • Chrome primitives (AppBar, BottomNav, SectionHead, HHIcon, StatTile,
//     HHEmptyState, TeamCrest, MyCardsDetailModal) are window globals —
//     never re-implemented here.
//
// Public primitives (Object.assign'd to window at the bottom):
//   PfIcon            — HHIcon extended with settings / info / logout glyphs.
//   ProfileHero       — avatar + name + level pill + XP bar.
//                       variant: 'hero' (mobile §S14) | 'sidebar' (desktop).
//   StatCard          — stat tile (label + value) for the 2-column §S14 grid.
//   MenuRow           — icon-button row: icon + label + chevron. danger variant.
//   ProfileEditField  — read-only field row for the §S38 edit screen.
//
// Internal (not exported):
//   PfAvatar          — circular img / initials avatar, consumed by ProfileHero.


// ─── micro-helpers ─────────────────────────────────────────────────────────
// Digit localisation — proxy to card-v2's toLocaleDigits; safe before load.
const _pfT = (n, locale) =>
  (window.toLocaleDigits ? window.toLocaleDigits(n, locale) : String(n));

// Format a large integer with Latin grouping, then map digits to locale.
// e.g. 89320 → "89,320" → "۸۹٬۳۲۰"  in fa.
const _pfFmt = (n, locale) =>
  _pfT((typeof n === 'number' ? n : 0).toLocaleString('en-US'), locale);

// Proxy to the canonical HHIcon (homehub-pieces.jsx).
// Renders nothing when homehub-pieces hasn't loaded yet.
const _pfHHIcon = ({ name, size = 18, strokeWidth = 1.7, style }) => {
  if (typeof window.HHIcon === 'function') {
    return window.HHIcon({ name, size, strokeWidth, style });
  }
  return React.createElement('svg', {
    width: size, height: size, viewBox: '0 0 24 24',
    'aria-hidden': 'true', style,
  });
};


// ─── PfIcon ────────────────────────────────────────────────────────────────
// Extends HHIcon with three profile-specific glyphs not present in the
// canonical set. Falls through to HHIcon for every other name.
//
//   settings  — gear (Feather-style)
//   info      — circle with "i" (Feather-style)
//   logout    — door + exit arrow (Feather-style; visually equivalent across
//               RTL/LTR — the arrow meaning is directionally neutral)
function PfIcon({ name, size = 18, strokeWidth = 1.7, style }) {
  const s = size, sw = strokeWidth;
  const com = {
    width: s, height: s, viewBox: '0 0 24 24', fill: 'none',
    stroke: 'currentColor', strokeWidth: sw,
    strokeLinecap: 'round', strokeLinejoin: 'round',
    style,
  };
  switch (name) {
    case 'settings':
      return (
        <svg {...com}>
          <circle cx="12" cy="12" r="3"/>
          <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
        </svg>
      );
    case 'info':
      return (
        <svg {...com}>
          <circle cx="12" cy="12" r="8.5"/>
          <line x1="12" y1="16" x2="12" y2="12"/>
          <line x1="12" y1="8" x2="12.01" y2="8" strokeWidth={sw + 0.6}/>
        </svg>
      );
    case 'logout':
      return (
        <svg {...com}>
          <path d="M9 21H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5"/>
          <polyline points="16 17 21 12 16 7"/>
          <line x1="21" y1="12" x2="9" y2="12"/>
        </svg>
      );
    default:
      return _pfHHIcon({ name, size, strokeWidth, style });
  }
}


// ─── PfAvatar (internal) ───────────────────────────────────────────────────
// Circular avatar with src-image or deterministic initials fallback.
// Not exported — consumed only by ProfileHero.
//
// Props
//   src      — string | null. When truthy renders <img>.
//   seed     — string. Drives resolveAvatarPalette for the gradient.
//   initial  — string | { fa, en, ar }. First glyph for initials mode.
//   size     — pixel diameter (number). Default 80.
//   locale   — 'fa' | 'en' | 'ar'. Selects glyph from locale dict.
function PfAvatar({ src, seed = '', initial = '?', size = 80, locale = 'fa' }) {
  const glyph = (initial && typeof initial === 'object')
    ? (initial[locale] || initial.fa || '?')
    : String(initial || '?');

  const pal = (typeof window.resolveAvatarPalette === 'function')
    ? window.resolveAvatarPalette(seed)
    : { from: 'var(--accent-primary)', to: 'var(--accent-primary-2)' };

  if (src) {
    return (
      <span className="pf-avatar" style={{ width: size, height: size }}>
        <img src={src} alt="" className="pf-avatar-img" width={size} height={size}/>
      </span>
    );
  }
  return (
    <span className="pf-avatar pf-avatar--initials"
          style={{
            width: size,
            height: size,
            background: `linear-gradient(150deg, ${pal.from} 0%, ${pal.to} 100%)`,
          }}
          aria-hidden="true">
      <span className="pf-avatar-glyph"
            style={{ fontSize: Math.max(13, Math.round(size * 0.36)) }}>
        {glyph}
      </span>
    </span>
  );
}


// ─── ProfileHero ───────────────────────────────────────────────────────────
// User hero block: circular avatar + display name + level pill + XP bar.
//
// variant="hero"    Mobile §S14 — horizontal layout (avatar start, body end).
//                   Avatar 80px. Full-width content area.
// variant="sidebar" Desktop sidebar — stacked / centered, glass card surface.
//                   Avatar 60px. Narrower text.
//
// Props
//   user     — PROF_USER shape. Defaults to window.PROF_USER.
//   locale   — 'fa' | 'en' | 'ar'
//   onEdit   — optional fn. Wraps the entire hero in a button when provided
//              (used by the AppBar pill instead, so usually left null).
//   variant  — 'hero' (default) | 'sidebar'
function ProfileHero({
  user    = window.PROF_USER,
  locale  = 'fa',
  onEdit,
  variant = 'hero',
}) {
  if (!user) return null;
  const ll = window.PROF_I18N ? window.PROF_I18N[locale] : {};

  const progress = (typeof window.getXPProgress === 'function')
    ? window.getXPProgress(user)
    : Math.min(1, Math.max(0, user.totalXP / (user.nextLevelXP || 1)));

  const avatarSize = variant === 'sidebar' ? 60 : 80;

  const body = (
    <div className={`pf-hero pf-hero--${variant}`}
         style={{ '--pf-xp-progress': `${Math.round(progress * 100)}%` }}>
      <PfAvatar
        src={user.avatarSrc}
        seed={user.avatarSeed || user.username || ''}
        initial={user.avatarInitial}
        size={avatarSize}
        locale={locale}
      />
      <div className="pf-hero-body">
        <div className="pf-hero-name">
          {(user.displayName && (user.displayName[locale] || user.displayName.fa)) || ''}
        </div>
        <div className="pf-hero-pills">
          <span className="pf-hero-level-pill">
            {ll.levelPill
              ? ll.levelPill(_pfFmt(user.level, locale))
              : `سطح ${_pfFmt(user.level, locale)}`}
          </span>
        </div>
        <div className="pf-hero-xp">
          {ll.xpProgress
            ? ll.xpProgress(_pfFmt(user.totalXP, locale), _pfFmt(user.nextLevelXP, locale))
            : `XP ${_pfFmt(user.totalXP, locale)} / ${_pfFmt(user.nextLevelXP, locale)}`}
        </div>
        <div className="pf-hero-bar" aria-hidden="true" role="progressbar"
             aria-valuenow={Math.round(progress * 100)} aria-valuemin={0} aria-valuemax={100}>
          <span className="pf-hero-bar-fill"/>
        </div>
      </div>
    </div>
  );

  return body;
}


// ─── StatCard ───────────────────────────────────────────────────────────────
// Compact stat tile: label (muted, top) + formatted value (bold, bottom).
// Intended for the 2-column CSS grid on §S14. Deliberately minimal — no icon,
// no progress, no delta — to match the wireframe exactly. The containing grid
// (`pf-stats-grid`) is defined in profile-app.jsx.
//
// Decision note (v1.7): StatTile from homehub-pieces has icon / progress /
// delta complexity that isn't needed here. StatCard is a purposefully simpler
// surface for the profile stat grid; it follows the same glass-surface recipe
// as StatTile's `mode='plain'` variant but in a dedicated, lighter wrapper.
//
// Props
//   label  — string (resolved from PROF_I18N, e.g. ll.statLevel)
//   value  — string (already formatted via _pfFmt / toLocaleDigits)
function StatCard({ label, value }) {
  return (
    <div className="pf-stat">
      <span className="pf-stat-label">{label}</span>
      <span className="pf-stat-value tabular-nums">{value}</span>
    </div>
  );
}


// ─── MenuRow ────────────────────────────────────────────────────────────────
// A single menu list item rendered as a <button> for full keyboard / pointer
// accessibility. Layout: [ icon-circle ] [ label (flex-1) ] [ chevron ]
//
// Separator lines between rows are drawn with border-block-start so they
// flip correctly under RTL without explicit left/right overrides.
//
// Props
//   item    — PROF_MENU_ITEMS entry ({ key, icon, danger? })
//   label   — resolved locale string (e.g. PROF_I18N[locale].menuSettings)
//   locale  — 'fa' | 'en' | 'ar'
//   onClick — fn(item) — called on button click
function MenuRow({ item, label, locale = 'fa', onClick }) {
  if (!item) return null;
  return (
    <button
      type="button"
      className={`pf-menu-row${item.danger ? ' pf-menu-row--danger' : ''}`}
      onClick={() => onClick && onClick(item)}>
      {/* Icon circle */}
      <span className="pf-menu-row-icon" aria-hidden="true">
        <PfIcon name={item.icon} size={17} strokeWidth={1.6}/>
      </span>
      {/* Label */}
      <span className="pf-menu-row-label">{label}</span>
      {/* Chevron — in RTL the path already points "inward-to-outward" */}
      <span className="pf-menu-row-chev" aria-hidden="true">
        {_pfHHIcon({ name: 'chevron', size: 15 })}
      </span>
    </button>
  );
}


// ─── ProfileEditField ───────────────────────────────────────────────────────
// Read-only form field used on the Edit Profile screen (§S38). The field
// shows a muted label above a glass-surface row containing the value, an
// optional leading element (e.g. TeamCrest for the team field), and an
// optional action link (e.g. "تغییر" for email / phone).
//
// Props
//   label    — string — field label (e.g. "نام کاربری")
//   value    — string — displayed value (e.g. "@keyvan")
//   leading  — ReactElement | null — rendered before the value (flag/crest)
//   action   — { label: string, onClick: fn } | null — accent link after value
//   verified — boolean — when true shows a "✓ تأیید شده" badge (phone field)
//   verifiedLabel — string — the verified badge text (from PROF_I18N)
function ProfileEditField({ label, value, leading = null, action = null,
                            verified = false, verifiedLabel = '' }) {
  return (
    <div className="pf-edit-field">
      <div className="pf-edit-field-label">{label}</div>
      <div className="pf-edit-field-body">
        {leading && (
          <span className="pf-edit-field-leading" aria-hidden="true">{leading}</span>
        )}
        <span className="pf-edit-field-value">
          {value}
        </span>
        {verified && (
          <span className="pf-edit-field-verified">{verifiedLabel}</span>
        )}
        {action && !verified && (
          <button type="button" className="pf-edit-field-action" onClick={action.onClick}>
            {action.label}
          </button>
        )}
      </div>
    </div>
  );
}


// ─── Exports ────────────────────────────────────────────────────────────────
Object.assign(window, {
  PfIcon,
  ProfileHero,
  StatCard,
  MenuRow,
  ProfileEditField,
  // PfAvatar intentionally not exported — internal to this file.
});


// ─── CSS (pf- prefix · token-only) ─────────────────────────────────────────
const PROFILE_PIECES_CSS = `
/* =========================================================================
   PfAvatar — circular img / initials fallback
   ========================================================================= */
.pf-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  flex: 0 0 auto;
  overflow: hidden;
  position: relative;
  user-select: none;
  border: 2.5px solid var(--border-soft, rgba(255,255,255,0.09));
}
.pf-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}
.pf-avatar--initials {
  font-family: var(--font-current);
  font-weight: 800;
  text-transform: uppercase;
  color: rgba(255,255,255,0.92);
}
.pf-avatar-glyph { line-height: 1; letter-spacing: -0.01em; }


/* =========================================================================
   ProfileHero
   ========================================================================= */
.pf-hero {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px;
  font-family: var(--font-current);
}

/* Desktop sidebar — stacked, glass surface */
.pf-hero--sidebar {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  padding: 20px 16px 18px;
  background: linear-gradient(
    180deg,
    rgba(255,255,255,0.035) 0%,
    rgba(255,255,255,0.015) 100%
  );
  border: 1px solid var(--border-soft, rgba(255,255,255,0.08));
  border-radius: 16px;
}

.pf-hero-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.pf-hero--sidebar .pf-hero-body {
  align-items: center;
  width: 100%;
}

.pf-hero-name {
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pf-hero--sidebar .pf-hero-name { font-size: 15px; }

.pf-hero-pills {
  margin-block-start: 7px;
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Level pill — accent gradient chip */
.pf-hero-level-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 11px;
  border-radius: 999px;
  background: linear-gradient(
    135deg,
    var(--accent-primary, #7163D9) 0%,
    var(--accent-primary-2, #534AB7) 100%
  );
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.45;
  letter-spacing: 0.025em;
  font-variant-numeric: tabular-nums;
}

/* XP label */
.pf-hero-xp {
  margin-block-start: 10px;
  font-size: 11.5px;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* XP progress bar */
.pf-hero-bar {
  margin-block-start: 6px;
  height: 5px;
  border-radius: 999px;
  background: var(--bg-surface, rgba(255,255,255,0.06));
  overflow: hidden;
  width: 100%;
}
.pf-hero-bar-fill {
  display: block;
  height: 100%;
  width: var(--pf-xp-progress, 0%);
  border-radius: 999px;
  background: linear-gradient(
    90deg,
    var(--accent-primary, #7163D9) 0%,
    var(--tier-platinum, #93C5FD) 100%
  );
  transition: width 600ms cubic-bezier(0.16, 1, 0.28, 1);
}


/* =========================================================================
   StatCard — 2-column profile stat grid cell
   ========================================================================= */
.pf-stat {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 12px 14px;
  border-radius: 12px;
  background: linear-gradient(
    180deg,
    rgba(255,255,255,0.04) 0%,
    rgba(255,255,255,0.02) 100%
  );
  border: 1px solid var(--border-soft, rgba(255,255,255,0.08));
  font-family: var(--font-current);
}
.pf-stat-label {
  font-size: 11px;
  color: var(--text-tertiary);
  font-weight: 600;
  line-height: 1.3;
}
.pf-stat-value {
  font-size: 20px;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}


/* =========================================================================
   MenuRow — icon + label + chevron list button
   ========================================================================= */
.pf-menu-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  width: 100%;
  appearance: none;
  border: none;
  border-block-start: 1px solid var(--border-soft, rgba(255,255,255,0.06));
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-current);
  font-size: 14px;
  text-align: start;
  cursor: pointer;
  transition: background 140ms ease, opacity 140ms ease;
}
/* First row in a group has no top separator */
.pf-menu-group > .pf-menu-row:first-child { border-block-start: none; }
.pf-menu-row:hover  { background: rgba(255,255,255,0.03); }
.pf-menu-row:active { background: rgba(255,255,255,0.055); }
.pf-menu-row:focus-visible {
  outline: 2px solid var(--accent-primary, #7163D9);
  outline-offset: -2px;
  border-radius: 2px;
}

/* Icon circle */
.pf-menu-row-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: var(--bg-elevated, rgba(255,255,255,0.04));
  border: 1px solid var(--border-soft, rgba(255,255,255,0.07));
  color: var(--text-secondary);
  flex: 0 0 auto;
  transition: color 140ms ease;
}

.pf-menu-row-label {
  flex: 1;
  font-weight: 500;
  color: var(--text-primary);
  text-align: start;
}

/* Chevron */
.pf-menu-row-chev {
  display: inline-flex;
  align-items: center;
  color: var(--text-tertiary);
  flex: 0 0 auto;
  /* The chevron SVG path faces right. In a dir="rtl" container the browser
     mirrors inline layout but not the SVG path itself. We keep it as-is:
     pointing outward (toward the inline-end) is the correct affordance for
     a "navigate forward" row in both RTL and LTR. */
}

/* Danger variant */
.pf-menu-row--danger .pf-menu-row-icon  { color: var(--danger, #FB7185); }
.pf-menu-row--danger .pf-menu-row-label { color: var(--danger, #FB7185); font-weight: 600; }


/* =========================================================================
   ProfileEditField — §S38 read-only form row
   ========================================================================= */
.pf-edit-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-family: var(--font-current);
}

.pf-edit-field-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
  padding-inline-start: 1px;
}

.pf-edit-field-body {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-radius: 10px;
  background: linear-gradient(
    180deg,
    rgba(255,255,255,0.04) 0%,
    rgba(255,255,255,0.02) 100%
  );
  border: 1px solid var(--border-soft, rgba(255,255,255,0.08));
}

.pf-edit-field-leading { flex: 0 0 auto; }

.pf-edit-field-value {
  flex: 1;
  font-size: 13px;
  color: var(--text-primary);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* Verified badge — accent-colored tick + text */
.pf-edit-field-verified {
  flex: 0 0 auto;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--success, #34D399);
  letter-spacing: 0.01em;
}

/* Action link (e.g. "تغییر") */
.pf-edit-field-action {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 600;
  color: var(--accent-primary, #7163D9);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font-family: var(--font-current);
  transition: opacity 140ms ease;
}
.pf-edit-field-action:hover { opacity: 0.75; }


/* =========================================================================
   Reduced motion — suppress the only tween in this file
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .pf-hero-bar-fill { transition: none !important; }
  .pf-menu-row      { transition: none !important; }
}
`;

const __profilePiecesStyle = document.createElement('style');
__profilePiecesStyle.textContent = PROFILE_PIECES_CSS;
document.head.appendChild(__profilePiecesStyle);
