// kova/kraft-briefs.jsx — KRAFT · Studio OS (brief inbox + work board + feedback)
// ----------------------------------------------------------------
// Turns the designer surface into a managed service desk. Inbound briefs from
// HOM (trends), VAULT (remakes), ORBIT (signals) and the CEO (strategic) land
// here as first-class objects; the designer triages → accepts (seeds a chat
// session) → designs → submits a launch pack → and CEO feedback returns home.
//
// Additive + non-breaking: this renders inside a new third KRAFT view
// (Chat | Gallery | Work). Chat/Gallery are untouched. Reuses the atomic
// system (Chip, Btn, Drawer, Seg, Textarea, EmptyState…) and resolves to
// tokens.css. State lives in app.jsx (briefs) and KraftStudioPage (sessions).
//
// Backend contract: api-docs/KRAFT_BRIEFS_API.md · model: docs/KRAFT_STUDIO_OS.md
// ----------------------------------------------------------------

const { Btn, IconBtn, Chip, Icon, Card, Drawer, Seg, Textarea, EmptyState, Avatar } = window.K;
const { useState, useMemo, useCallback } = React;

/* ============================================================
   METADATA MAPS
   ============================================================ */
const BRIEF_STATUS = {
  new:                { label: 'New',            variant: 'info',    col: 'new' },
  accepted:           { label: 'Accepted',       variant: 'accent',  col: 'progress' },
  in_progress:        { label: 'In progress',    variant: 'accent',  col: 'progress' },
  submitted:          { label: 'Submitted',      variant: 'warn',    col: 'submitted' },
  changes_requested:  { label: 'Changes',        variant: 'danger',  col: 'changes' },
  approved:           { label: 'Approved',       variant: 'success', col: 'done' },
  in_production:      { label: 'In production',   variant: 'success', col: 'done' },
  parked:             { label: 'Parked',         variant: 'mute',    col: 'parked' },
};
const PRIORITY = {
  high: { label: 'High', variant: 'danger' },
  mid:  { label: 'Medium', variant: 'warn' },
  low:  { label: 'Low', variant: 'mute' },
};
const SOURCE = {
  orbit: { label: 'Orbit', mod: 'orbit' },
  vault: { label: 'Vault', mod: 'vault' },
  home:  { label: 'Home',  mod: 'home' },
  admin: { label: 'CEO',   mod: 'admin' },
  price: { label: 'Price', mod: 'price' },
};
const COLUMNS = [
  { id: 'new',       label: 'New · inbox' },
  { id: 'progress',  label: 'In progress' },
  { id: 'submitted', label: 'Submitted' },
  { id: 'changes',   label: 'Changes requested' },
  { id: 'done',      label: 'Approved / production' },
  { id: 'parked',    label: 'Parked' },
];

const GOLD_RATE_10G = 78420; // ₹ / 10g (mirrors PRICE seed) — indicative cost model
const money = (n) => {
  if (n == null) return '—';
  if (n >= 100000) return `₹${(n / 100000).toFixed(1)} L`;
  return `₹${n.toLocaleString('en-IN')}`;
};

/* ============================================================
   ATOMS / MOLECULES
   ============================================================ */
const StatusPill = ({ status }) => {
  const s = BRIEF_STATUS[status] || BRIEF_STATUS.new;
  return <Chip variant={s.variant} dot>{s.label}</Chip>;
};
const PriorityTag = ({ priority }) => {
  const p = PRIORITY[priority] || PRIORITY.mid;
  return <Chip variant={p.variant}>{p.label}</Chip>;
};
const DueChip = ({ dueDays }) => {
  if (dueDays == null) return null;
  const overdue = dueDays < 0;
  const soon = dueDays >= 0 && dueDays <= 3;
  const label = overdue ? `${Math.abs(dueDays)} d overdue` : dueDays === 0 ? 'due today' : `due in ${dueDays} d`;
  return (
    <span className={`krw-due${overdue ? ' is-overdue' : soon ? ' is-soon' : ''}`}>
      <Icon name="clock" size={11} /> {label}
    </span>
  );
};
const SourceBadge = ({ source }) => {
  const s = SOURCE[source.module] || { label: source.module, mod: 'home' };
  return (
    <span className="krw-source" style={{ '--m-mod': `var(--m-${s.mod})` }}>
      <span className="krw-source-dot" />
      {s.label}{source.person ? ` · ${source.person}` : ''}
    </span>
  );
};
const ConstraintChips = ({ c, max }) => {
  const items = [c.pieceType, c.metal && `${c.metal}${c.karat ? ' ' + c.karat : ''}`, c.stone, c.motif, c.occasion]
    .filter(Boolean);
  const shown = max ? items.slice(0, max) : items;
  return (
    <div className="krw-cchips">
      {shown.map((t, i) => <Chip key={i} variant="mute">{t}</Chip>)}
      {max && items.length > max && <Chip variant="mute">+{items.length - max}</Chip>}
    </div>
  );
};
const ProvenanceLink = ({ origin, onOpen }) => {
  const typeLabel = { signal: 'Signal', sku: 'SKU', trend: 'Trend', strategic: 'Initiative' }[origin.type] || 'Origin';
  return (
    <button className="krw-prov" onClick={onOpen}>
      <span className="krw-prov-type">{typeLabel}</span>
      <span className="krw-prov-label">{origin.label}</span>
      <span className="t-mono krw-prov-ref">{origin.refId}</span>
      <Icon name="external" size={12} />
    </button>
  );
};

const BoardCard = ({ brief, onOpen }) => (
  <div className="krw-card" role="button" tabIndex={0}
       onClick={() => onOpen(brief)}
       onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onOpen(brief); } }}>
    <div className="krw-card-top">
      <SourceBadge source={brief.source} />
      <PriorityTag priority={brief.priority} />
    </div>
    <div className="krw-card-title">{brief.title}</div>
    <ConstraintChips c={brief.constraints} max={3} />
    <div className="krw-card-foot">
      <DueChip dueDays={brief.dueDays} />
      {brief.thread?.length > 0 && <span className="krw-card-comments"><Icon name="doc" size={11} /> {brief.thread.length}</span>}
    </div>
  </div>
);

/* ============================================================
   ORGANISM · StudioStrip (analytics + capacity)
   ============================================================ */
const StudioStrip = ({ briefs }) => {
  const by = (fn) => briefs.filter(fn).length;
  const stats = [
    { label: 'New', value: by(b => b.status === 'new'), tone: 'info' },
    { label: 'In progress', value: by(b => b.status === 'accepted' || b.status === 'in_progress'), tone: 'accent' },
    { label: 'Awaiting sign', value: by(b => b.status === 'submitted'), tone: 'warn' },
    { label: 'Changes', value: by(b => b.status === 'changes_requested'), tone: 'danger' },
    { label: 'Approved', value: by(b => b.status === 'approved' || b.status === 'in_production'), tone: 'success' },
  ];
  const active = by(b => ['accepted', 'in_progress', 'changes_requested'].includes(b.status));
  return (
    <div className="krw-strip">
      {stats.map(s => (
        <div key={s.label} className="krw-stat">
          <div className="krw-stat-value" style={{ color: `var(--${s.tone === 'accent' ? 'accent' : s.tone})` }}>{s.value}</div>
          <div className="krw-stat-label">{s.label}</div>
        </div>
      ))}
      <div className="krw-stat krw-stat-cap">
        <div className="krw-stat-value">{active}<span className="krw-stat-cap-of"> / 8</span></div>
        <div className="krw-stat-label">In flight · capacity</div>
      </div>
    </div>
  );
};

/* ============================================================
   ORGANISM · WorkFilterBar
   ============================================================ */
const WorkFilterBar = ({ q, onQ, source, onSource, priority, onPriority, counts }) => (
  <div className="krw-filterbar">
    <div className="krw-search">
      <Icon name="search" size={13} />
      <input value={q} onChange={(e) => onQ(e.target.value)} placeholder="Search briefs, sources, motifs…" />
      {q && <button className="krw-search-x" onClick={() => onQ('')} aria-label="Clear">×</button>}
    </div>
    <Seg value={source} onChange={onSource} items={[
      { id: 'all', label: `All · ${counts.all}` },
      { id: 'orbit', label: 'Orbit' }, { id: 'vault', label: 'Vault' }, { id: 'admin', label: 'CEO' },
    ]} />
    <Seg value={priority} onChange={onPriority} items={[
      { id: 'all', label: 'Any' }, { id: 'high', label: 'High' }, { id: 'mid', label: 'Medium' }, { id: 'low', label: 'Low' },
    ]} />
  </div>
);

/* ============================================================
   ORGANISM · MyWorkBoard (kanban)
   ============================================================ */
const MyWorkBoard = ({ briefs, onOpen }) => {
  const byCol = useMemo(() => {
    const m = Object.fromEntries(COLUMNS.map(c => [c.id, []]));
    briefs.forEach(b => { const col = (BRIEF_STATUS[b.status] || {}).col || 'new'; (m[col] = m[col] || []).push(b); });
    return m;
  }, [briefs]);
  return (
    <div className="krw-board">
      {COLUMNS.map(c => (
        <div key={c.id} className={`krw-col krw-col-${c.id}`}>
          <div className="krw-col-head">
            <span className="krw-col-title">{c.label}</span>
            <span className="krw-col-count">{byCol[c.id].length}</span>
          </div>
          <div className="krw-col-body">
            {byCol[c.id].length === 0
              ? <div className="krw-col-empty">—</div>
              : byCol[c.id].map(b => <BoardCard key={b.id} brief={b} onOpen={onOpen} />)}
          </div>
        </div>
      ))}
    </div>
  );
};

/* ============================================================
   MOLECULE · Feasibility (cost / manufacturability pre-check)
   ============================================================ */
const Feasibility = ({ c }) => {
  if (!c) return null;
  const goldCost = c.weightCeilingG ? Math.round((c.weightCeilingG / 10) * GOLD_RATE_10G) : null;
  const overBudget = goldCost != null && c.budget != null && goldCost > c.budget;
  return (
    <div className="krw-feas">
      <div className="krw-feas-row"><span>Budget / piece</span><b>{money(c.budget)}</b></div>
      <div className="krw-feas-row"><span>Weight ceiling</span><b>{c.weightCeilingG ? `${c.weightCeilingG} g` : '—'}</b></div>
      <div className="krw-feas-row">
        <span>Est. gold value <span className="t-meta">@ ₹78,420/10g</span></span>
        <b className={overBudget ? 'is-over' : ''}>{goldCost != null ? money(goldCost) : '—'}</b>
      </div>
      <div className={`krw-feas-verdict${overBudget ? ' is-over' : ' is-ok'}`}>
        {goldCost == null ? 'Add a weight ceiling to estimate feasibility.'
          : overBudget ? '⚠ Gold value alone exceeds the budget — tighten weight or raise budget.'
            : '✓ Indicative gold value sits within budget.'}
      </div>
    </div>
  );
};

/* ============================================================
   ORGANISM · BriefDetailDrawer body
   ============================================================ */
const DSection = ({ eyebrow, children, right }) => (
  <div className="krw-dsec">
    <div className="krw-dsec-head"><span className="krw-dsec-eyebrow">{eyebrow}</span>{right}</div>
    {children}
  </div>
);
const BriefDetailBody = ({ brief, onProvenance, comment, setComment, onAddComment }) => (
  <>
    <DSection eyebrow="The ask">
      <p className="t-body-sm" style={{ margin: 0, lineHeight: 1.6 }}>{brief.intent}</p>
    </DSection>
    <DSection eyebrow="Provenance">
      <ProvenanceLink origin={brief.origin} onOpen={onProvenance} />
    </DSection>
    <DSection eyebrow="Constraints">
      <div className="krw-cgrid">
        {[['Piece', brief.constraints.pieceType], ['Metal', brief.constraints.metal && `${brief.constraints.metal} ${brief.constraints.karat || ''}`.trim()],
          ['Stone', brief.constraints.stone], ['Motif', brief.constraints.motif],
          ['Occasion', brief.constraints.occasion], ['Weight ≤', brief.constraints.weightCeilingG ? `${brief.constraints.weightCeilingG} g` : '']
        ].map(([k, v]) => (
          <div key={k} className="krw-cgrid-cell"><div className="krw-cgrid-k">{k}</div><div className="krw-cgrid-v">{v || '—'}</div></div>
        ))}
      </div>
    </DSection>
    <DSection eyebrow="Feasibility · indicative"><Feasibility c={brief.constraints} /></DSection>
    {brief.references?.length > 0 && (
      <DSection eyebrow="References">
        {brief.references.map((r, i) => <div key={i} className="krw-ref">{r.label}</div>)}
      </DSection>
    )}
    <DSection eyebrow={`Conversation · ${brief.thread?.length || 0}`}>
      <div className="krw-thread">
        {(brief.thread || []).map((m, i) => (
          <div key={i} className={`krw-msg${m.role === 'designer' ? ' is-me' : ''}`}>
            <Avatar initials={(m.who || '?').split(' ').map(s => s[0]).slice(0, 2).join('')} size={22} />
            <div className="krw-msg-body">
              <div className="krw-msg-who">{m.who} <span className="t-meta">· {m.at}</span></div>
              <div className="krw-msg-text">{m.text}</div>
            </div>
          </div>
        ))}
      </div>
      <div className="krw-reply">
        <Textarea value={comment} onChange={setComment} rows={2} placeholder="Ask the requester a question, or note progress…" />
        <Btn size="sm" variant="primary" disabled={!comment.trim()} onClick={onAddComment}>Send</Btn>
      </div>
    </DSection>
    <DSection eyebrow="History">
      <div className="krw-hist">
        {(brief.history || []).map((h, i) => (
          <div key={i} className="krw-hist-row">
            <StatusPill status={h.state} /><span className="t-meta">{h.at}</span>
          </div>
        ))}
      </div>
    </DSection>
  </>
);

/* ============================================================
   PAGE-SECTION · KraftBriefsView
   ============================================================ */
const KraftBriefsView = ({ briefs = [], onAccept, onUpdateBrief, onComment, onOpenSession, onProvenance, pushToast }) => {
  const [q, setQ] = useState('');
  const [source, setSource] = useState('all');
  const [priority, setPriority] = useState('all');
  const [openId, setOpenId] = useState(null);
  const [comment, setComment] = useState('');

  const filtered = useMemo(() => briefs.filter(b => {
    if (source !== 'all' && b.source.module !== source) return false;
    if (priority !== 'all' && b.priority !== priority) return false;
    if (q) {
      const hay = `${b.title} ${b.intent} ${b.source.person} ${b.origin.label} ${b.constraints.motif} ${b.constraints.metal}`.toLowerCase();
      if (!hay.includes(q.toLowerCase())) return false;
    }
    return true;
  }), [briefs, source, priority, q]);

  const brief = briefs.find(b => b.id === openId) || null;
  const close = useCallback(() => { setOpenId(null); setComment(''); }, []);

  const newCount = briefs.filter(b => b.status === 'new').length;

  // drawer actions by status
  const act = (fn) => { fn(); close(); };
  const footer = brief && (() => {
    const s = brief.status;
    if (s === 'new') return (
      <>
        <Btn variant="ghost" onClick={() => act(() => { onUpdateBrief(brief.id, b => ({ status: 'parked', history: [...(b.history || []), { state: 'parked', at: 'just now' }] })); pushToast?.({ kind: 'info', title: 'Brief parked', body: brief.title }); })}>Park</Btn>
        <span style={{ flex: 1 }} />
        <Btn variant="primary" onClick={() => act(() => onAccept(brief))}>Accept &amp; start</Btn>
      </>
    );
    if (s === 'accepted' || s === 'in_progress' || s === 'changes_requested') return (
      <>
        <Btn variant="ghost" onClick={() => act(() => { onUpdateBrief(brief.id, b => ({ status: 'parked', history: [...(b.history || []), { state: 'parked', at: 'just now' }] })); })}>Park</Btn>
        <span style={{ flex: 1 }} />
        <Btn variant="primary" onClick={() => act(() => onOpenSession(brief))}>Open in chat →</Btn>
      </>
    );
    if (s === 'submitted') return (
      <>
        <span className="t-meta" style={{ flex: 1 }}>Awaiting CEO sign-off on the launch pack.</span>
        <Btn variant="ghost" onClick={() => act(() => onOpenSession(brief))}>Open session</Btn>
      </>
    );
    if (s === 'parked') return (
      <>
        <span style={{ flex: 1 }} />
        <Btn variant="primary" onClick={() => act(() => onUpdateBrief(brief.id, b => ({ status: 'new', history: [...(b.history || []), { state: 'new', at: 'just now' }] })))}>Reactivate</Btn>
      </>
    );
    return <><span style={{ flex: 1 }} /><Btn variant="ghost" onClick={close}>Close</Btn></>;
  })();

  return (
    <div className="krw">
      {newCount > 0 && (
        <div className="krw-banner">
          <Icon name="inbox" size={14} />
          <span><b>{newCount} new brief{newCount === 1 ? '' : 's'}</b> need triage — accept to start a grounded session, or park.</span>
        </div>
      )}
      <StudioStrip briefs={briefs} />
      <WorkFilterBar q={q} onQ={setQ} source={source} onSource={setSource} priority={priority} onPriority={setPriority}
                     counts={{ all: briefs.length }} />
      {filtered.length === 0
        ? <Card><EmptyState mark="K" title="No briefs match these filters." body="Clear filters, or briefs arrive here from Orbit, Vault and the CEO." /></Card>
        : <MyWorkBoard briefs={filtered} onOpen={(b) => { setOpenId(b.id); setComment(''); }} />}

      <Drawer
        open={!!brief}
        onClose={close}
        eyebrow={brief ? <span className="krw-deye"><SourceBadge source={brief.source} /><StatusPill status={brief.status} /><PriorityTag priority={brief.priority} /><DueChip dueDays={brief.dueDays} /></span> : ''}
        title={brief?.title}
        footer={footer}
      >
        {brief && (
          <BriefDetailBody
            brief={brief}
            onProvenance={() => onProvenance?.(brief)}
            comment={comment} setComment={setComment}
            onAddComment={() => { onComment(brief.id, comment); setComment(''); }}
          />
        )}
      </Drawer>
    </div>
  );
};

Object.assign(window.K, {
  KraftBriefsView, MyWorkBoard, BoardCard, StudioStrip, WorkFilterBar,
  StatusPill, PriorityTag, DueChip, SourceBadge, ConstraintChips, ProvenanceLink, Feasibility,
  BRIEF_STATUS,
});
