/* NINA — design-system components (client web). Exposed on window. */

// ---- Button ----
function Button({ variant = 'primary', size, block, icon, iconRight, children, ...rest }) {
  const cls = ['btn', `btn--${variant}`, size === 'lg' ? 'btn--lg' : '', block ? 'btn--block' : '', !children ? 'btn--icon' : ''].join(' ');
  return (
    <button className={cls} {...rest}>
      {icon && <Icon name={icon} />}
      {children}
      {iconRight && <Icon name={iconRight} />}
    </button>
  );
}

// ---- Pill ----
function Pill({ tone = 'neutral', dot, children }) {
  return <span className={`pill pill--${tone}`}>{dot && <span className="dot" style={{ background: 'currentColor' }} />}{children}</span>;
}

// status → pill tone
const STATUS_PILL = {
  trialing: ['amber', 'Em teste'], active: ['mint', 'Ativo'], expired: ['red', 'Expirado'], none: ['neutral', 'Sem plano'],
  pago: ['mint', 'Pago'], pendente: ['amber', 'Pendente'], paga: ['mint', 'Paga'], aberta: ['neutral', 'Em aberto'],
  atrasada: ['red', 'Atrasada'], recebida: ['mint', 'Recebida'],
  novo: ['coral', 'Novo'], triado: ['amber', 'Triado'], resolvido: ['mint', 'Resolvido'],
};
function StatusPill({ status }) { const [tone, label] = STATUS_PILL[status] || ['neutral', status]; return <Pill tone={tone} dot>{label}</Pill>; }

// ---- StatCard (count-up + delta) ----
function StatCard({ label, dotColor, cents, deltaPct, deltaGoodWhenDown, hint }) {
  const value = useCountUpBRL(cents);
  const showDelta = deltaPct != null && deltaPct !== 0;
  const isUp = deltaPct > 0;
  // for expense: up is bad (red), down is good (mint). for income: up is good.
  const good = deltaGoodWhenDown ? !isUp : isUp;
  return (
    <div className="card card-hover stat">
      <div className="stat__label"><span className="stat__dot" style={{ background: dotColor }} />{label}</div>
      <div className="stat__value tnum">{value}</div>
      {showDelta ? (
        <span className={`stat__delta ${good ? 'down' : 'up'}`}>
          <Icon name={isUp ? 'arrowUp' : 'arrowDown'} size={14} />
          {Math.abs(deltaPct)}% vs mês passado
        </span>
      ) : <span className="stat__delta delta-muted">{hint || 'estável vs mês passado'}</span>}
    </div>
  );
}

// ---- TxRow ----
const SOURCE_LABEL = { whatsapp: 'WhatsApp', app: 'App', web: 'Web' };
function TxRow({ tx, onClick }) {
  return (
    <button className="txrow" onClick={onClick} style={{ border: 'none', background: 'none', width: '100%', textAlign: 'left' }}>
      <span className="txrow__emoji">{tx.emoji}</span>
      <span className="txrow__main">
        <span className="txrow__desc">{tx.description}</span>
        <span className="txrow__meta">
          <span>{tx.category}</span><span className="src-dot" />
          <span>{tx.methodLabel}</span><span className="src-dot" />
          <span>{tx.dateFmt}</span>
          <span className="src-dot" /><span>via {SOURCE_LABEL[tx.source] || tx.source}</span>
        </span>
      </span>
      <span className={`txrow__amount tnum ${tx.positive ? 'amt-income' : 'amt-expense'}`}>
        {tx.positive ? '+ ' : ''}{tx.amountFmt.replace('– ', '– ')}
      </span>
    </button>
  );
}

// ---- Progress (budget) ----
function budgetColor(pct) {
  if (pct > 100) return 'var(--expense)';
  if (pct >= 80) return 'var(--amber)';
  return 'var(--mint)';
}
function Progress({ pct, color }) {
  const [ref, seen] = useInView();
  const reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  return (
    <div ref={ref} className="progress">
      <div className="progress__fill" style={{ width: ((seen || reduced) ? Math.min(100, pct) : 0) + '%', background: color || budgetColor(pct) }} />
    </div>
  );
}

// ---- Period selector ----
const PERIODS = [['today', 'Hoje'], ['7d', '7 dias'], ['mes', 'Mês'], ['90d', '90 dias'], ['12m', '12 meses']];
function PeriodSelector({ value, onChange }) {
  return (
    <div className="period" role="tablist">
      {PERIODS.map(([k, label]) => (
        <button key={k} className={value === k ? 'is-active' : ''} onClick={() => onChange(k)} role="tab" aria-selected={value === k}>
          {value === k && <span className="period__pill" />}{label}
        </button>
      ))}
    </div>
  );
}

// ---- Field / Input / Select ----
function Field({ label, error, children }) {
  return <label className="field"><span className="field__label">{label}</span>{children}{error && <span className="field__error">{error}</span>}</label>;
}
function Input(props) { return <input className="input" {...props} />; }
function Select({ children, ...rest }) { return <select className="select" {...rest}>{children}</select>; }

// ---- MoneyInput (live BRL mask) ----
function MoneyInput({ cents, onChange, autoFocus }) {
  const display = 'R$ ' + (cents / 100).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  return (
    <input className="money-input" inputMode="numeric" value={display} autoFocus={autoFocus}
      onChange={(e) => { const digits = e.target.value.replace(/\D/g, ''); onChange(parseInt(digits || '0', 10)); }} />
  );
}

// ---- catálogo padrão (sempre disponível, mesmo sem histórico) ----
const DEFAULT_CATS = [
  { key: 'default:moradia', name: 'Moradia', emoji: '🏠' },
  { key: 'default:mercado', name: 'Mercado', emoji: '🛒' },
  { key: 'default:restaurantes', name: 'Restaurantes', emoji: '🍔' },
  { key: 'default:transporte', name: 'Transporte', emoji: '🚗' },
  { key: 'default:contas', name: 'Contas da casa', emoji: '💡' },
  { key: 'default:saude', name: 'Saúde', emoji: '💊' },
  { key: 'default:lazer', name: 'Lazer', emoji: '🎬' },
  { key: 'default:compras', name: 'Compras', emoji: '🛍️' },
  { key: 'default:assinaturas', name: 'Assinaturas', emoji: '💻' },
  { key: 'default:pet', name: 'Pet', emoji: '🐾' },
  { key: 'default:educacao', name: 'Educação', emoji: '📚' },
];

// ---- categorias custom (persistidas) ----
function ninaGetCats() {
  const real = Object.entries(window.NinaData.CATS).filter(([k, c]) => !c.income).map(([k, c]) => ({ key: k, name: c.name, emoji: c.emoji }));
  const usedNames = new Set(real.map((c) => c.name.trim().toLowerCase()));
  const defaults = DEFAULT_CATS.filter((c) => !usedNames.has(c.name.trim().toLowerCase()));
  const base = real.concat(defaults);
  try { const ex = JSON.parse(localStorage.getItem('nina-cats') || '[]'); return base.concat(ex); } catch (e) { return base; }
}
function ninaAddCat(emoji, name) {
  const key = 'cat' + Date.now();
  try { const ex = JSON.parse(localStorage.getItem('nina-cats') || '[]'); ex.push({ key, name, emoji }); localStorage.setItem('nina-cats', JSON.stringify(ex)); } catch (e) {}
  return key;
}
const NINA_EMOJIS = ['🛒', '🍔', '🚗', '🏠', '💡', '💊', '🎬', '🛍️', '📺', '🐾', '📚', '✈️', '🎁', '💅', '⚽', '☕', '🎸', '👶', '🌱', '💰'];

// ---- Nova categoria (modal) ----
function NovaCategoria({ onClose, onCreated }) {
  const [emoji, setEmoji] = useState('🛒');
  const [name, setName] = useState('');
  return (
    <Modal title="Nova categoria" onClose={onClose}
      footer={<>
        <Button variant="ghost" onClick={onClose}>Cancelar</Button>
        <Button block icon="check" disabled={!name.trim()} style={!name.trim() ? { opacity: .5, pointerEvents: 'none' } : {}}
          onClick={() => { const k = ninaAddCat(emoji, name.trim()); window.ninaToast('Categoria criada 🧡'); onCreated && onCreated(k); onClose(); }}>Criar categoria</Button>
      </>}>
      <div style={{ textAlign: 'center' }}>
        <div style={{ width: 72, height: 72, borderRadius: 'var(--radius-full)', background: 'var(--coral-tint)', display: 'grid', placeItems: 'center', fontSize: 34, margin: '0 auto' }}>{emoji}</div>
      </div>
      <Field label="Nome"><Input placeholder="Ex: Viagem, Filhos, Hobby…" value={name} onChange={(e) => setName(e.target.value)} autoFocus /></Field>
      <Field label="Ícone">
        <div className="chips">
          {NINA_EMOJIS.map((e) => (
            <button key={e} type="button" className={`chip ${emoji === e ? 'is-active' : ''}`} style={{ fontSize: 18, padding: '8px 12px' }} onClick={() => setEmoji(e)}>{e}</button>
          ))}
        </div>
      </Field>
    </Modal>
  );
}

// ---- Category picker (chips) — com "+ Nova" ----
function CategoryPicker({ value, onChange }) {
  const [addOpen, setAddOpen] = useState(false);
  const cats = ninaGetCats();
  return (
    <>
      <div className="chips">
        {cats.map((c) => (
          <button key={c.key} className={`chip ${value === c.key ? 'is-active' : ''}`} onClick={() => onChange(c.key)} type="button">
            <span>{c.emoji}</span>{c.name}
          </button>
        ))}
        <button className="chip" style={{ borderStyle: 'dashed', color: 'var(--coral-strong)' }} onClick={() => setAddOpen(true)} type="button">+ Nova categoria</button>
      </div>
      {addOpen && <NovaCategoria onClose={() => setAddOpen(false)} onCreated={(k) => onChange(k)} />}
    </>
  );
}

// ---- Modal ----
function Modal({ title, onClose, children, footer, wide }) {
  useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', h); return () => window.removeEventListener('keydown', h);
  }, []);
  return (
    <div className="backdrop" onClick={onClose}>
      <div className={`modal ${wide ? 'modal--wide' : ''}`} onClick={(e) => e.stopPropagation()} role="dialog" aria-modal="true">
        <div className="modal__head">
          <h3 className="modal__title">{title}</h3>
          <button className="x-btn" onClick={onClose} aria-label="Fechar"><Icon name="x" size={18} /></button>
        </div>
        <div className="modal__body">{children}</div>
        {footer && <div className="modal__foot">{footer}</div>}
      </div>
    </div>
  );
}

// ---- Toast host ----
let _toastSeq = 0;
function ToastHost() {
  const [items, setItems] = useState([]);
  useEffect(() => {
    window.ninaToast = (msg, kind = 'ok') => {
      const id = ++_toastSeq;
      setItems((x) => [...x, { id, msg, kind }]);
      setTimeout(() => setItems((x) => x.filter((i) => i.id !== id)), 3200);
    };
  }, []);
  return (
    <div className="toast-wrap">
      {items.map((t) => (
        <div key={t.id} className={`toast toast--${t.kind}`}>
          <Icon name={t.kind === 'ok' ? 'checkCircle' : 'alert'} />{t.msg}
        </div>
      ))}
    </div>
  );
}

// ---- Skeleton helpers ----
function Sk({ w, h, r, style }) { return <div className="sk" style={{ width: w, height: h || 14, borderRadius: r || 8, ...style }} />; }
function SkCard({ lines = 3 }) {
  return (
    <div className="card card--pad">
      <Sk w="40%" h={18} style={{ marginBottom: 16 }} />
      {Array.from({ length: lines }).map((_, i) => <Sk key={i} w={`${90 - i * 12}%`} style={{ marginBottom: 10 }} />)}
    </div>
  );
}

// ---- Empty state (warm, illustrated) ----
function EmptyArt({ emoji = '🌱' }) {
  return (
    <div className="state-box__art float-anim" style={{ position: 'relative' }}>
      <svg width="120" height="120" viewBox="0 0 120 120">
        <circle cx="60" cy="60" r="52" fill="var(--coral-tint)" />
        <circle cx="60" cy="60" r="36" fill="var(--surface)" />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', fontSize: 40 }}>{emoji}</div>
    </div>
  );
}
function EmptyState({ emoji, title, sub, action }) {
  return (
    <div className="state-box">
      <EmptyArt emoji={emoji} />
      <div className="state-box__title">{title}</div>
      <div className="state-box__sub">{sub}</div>
      {action}
    </div>
  );
}
function ErrorState({ onRetry, sub }) {
  return (
    <div className="state-box">
      <div className="state-box__art float-anim" style={{ position: 'relative' }}>
        <svg width="120" height="120" viewBox="0 0 120 120"><circle cx="60" cy="60" r="52" fill="var(--expense-tint)" /></svg>
        <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', color: 'var(--expense)' }}><Icon name="alert" size={44} /></div>
      </div>
      <div className="state-box__title">Algo não carregou</div>
      <div className="state-box__sub">{sub || 'Tive um probleminha pra buscar seus dados. Pode tentar de novo?'}</div>
      <Button variant="secondary" icon="refresh" onClick={onRetry}>Tentar de novo</Button>
    </div>
  );
}

// ---- Nina insight card ----
function NinaInsight({ loading, text, mark }) {
  return (
    <div className="insight">
      <img className="insight__avatar" src={mark} alt="Nina" />
      <div>
        <div className="insight__name"><Icon name="sparkle" size={14} /> Recado da Nina</div>
        {loading
          ? <div className="typing" style={{ marginTop: 6 }}><span></span><span></span><span></span></div>
          : <div className="insight__text">{text}</div>}
      </div>
    </div>
  );
}

// ---- Switch (toggle) ----
function Switch({ checked, onChange, label, hint }) {
  return (
    <label className="row between" style={{ cursor: 'pointer', gap: 16 }}>
      <span style={{ minWidth: 0 }}>
        <span style={{ display: 'block', fontWeight: 600, fontSize: 14 }}>{label}</span>
        {hint && <span style={{ display: 'block', fontSize: 12, color: 'var(--subtle)', marginTop: 1 }}>{hint}</span>}
      </span>
      <span className={`switch ${checked ? 'on' : ''}`} onClick={() => onChange(!checked)} role="switch" aria-checked={checked}>
        <span className="switch__dot" />
      </span>
    </label>
  );
}

// ---- Card section wrapper ----
function SectionCard({ title, hint, action, children, pad = true, className = '' }) {
  return (
    <div className={`card ${pad ? 'card--pad' : ''} ${className}`}>
      {(title || action) && (
        <div className="card__head" style={pad ? {} : { padding: 'var(--space-6) var(--space-6) 0' }}>
          <div style={{ minWidth: 0 }}><h3 className="card__title">{title}</h3>{hint && <div className="card__hint" style={{ marginTop: 2 }}>{hint}</div>}</div>
          {action}
        </div>
      )}
      {children}
    </div>
  );
}

// ---- Comunidade no WhatsApp (chamada reutilizável) ----
function CommunityCard({ compact }) {
  const cfg = window.NinaData.config;
  if (compact) {
    return (
      <a href={cfg.contact.communityUrl} target="_blank" rel="noopener" className="card card-hover" style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '14px 18px', textDecoration: 'none', color: 'inherit', background: 'linear-gradient(135deg, #E9F9EF, #F3FBF4)', border: '1px solid #CBEDD6' }}>
        <span className="txrow__emoji" style={{ background: '#25D366', color: '#fff', flex: 'none' }}><Icon name="whatsapp" size={20} /></span>
        <span style={{ flex: 1, minWidth: 0 }}>
          <span style={{ display: 'block', fontWeight: 700, fontSize: 14 }}>Comunidade da {cfg.projectName} no WhatsApp</span>
          <span style={{ display: 'block', fontSize: 12.5, color: 'var(--muted)', marginTop: 1 }}>Novidades em primeira mão e suporte mais próximo.</span>
        </span>
        <span className="pill pill--mint" style={{ flex: 'none' }}>Entrar →</span>
      </a>
    );
  }
  return (
    <div className="card card--pad" style={{ background: 'linear-gradient(135deg, #E9F9EF, #F3FBF4)', border: '1px solid #CBEDD6' }}>
      <div className="row between wrap" style={{ gap: 16 }}>
        <div className="row" style={{ gap: 14, minWidth: 0 }}>
          <span className="txrow__emoji" style={{ width: 52, height: 52, background: '#25D366', color: '#fff', flex: 'none' }}><Icon name="whatsapp" size={24} /></span>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 16, fontFamily: 'var(--font-display)' }}>Entre na comunidade da {cfg.projectName}</div>
            <div className="muted" style={{ fontSize: 13.5, marginTop: 2, lineHeight: 1.5 }}>Atualizações em primeira mão, dicas de quem usa todo dia e um canal de suporte mais personalizado — direto no seu WhatsApp.</div>
          </div>
        </div>
        <a href={cfg.contact.communityUrl} target="_blank" rel="noopener" className="btn btn--whats" style={{ textDecoration: 'none', flex: 'none' }}><Icon name="whatsapp" /> Entrar na comunidade</a>
      </div>
    </div>
  );
}

Object.assign(window, {
  Button, Pill, StatusPill, StatCard, TxRow, Progress, budgetColor, PeriodSelector,
  Field, Input, Select, MoneyInput, CategoryPicker, NovaCategoria, ninaGetCats, ninaAddCat, DEFAULT_CATS, Modal, ToastHost, Switch,
  Sk, SkCard, EmptyState, EmptyArt, ErrorState, NinaInsight, SectionCard, PERIODS, SOURCE_LABEL, CommunityCard,
});
