// Approvals — inbox + approval detail page

// Check if a workflow stage condition is met for an order
const checkCondition = (condition, order) => {
  if (!condition || condition === 'always') return true;
  const mrr    = order.monthly || 0;
  const months = order.contractMonths || 12;

  // Dynamic evaluation from CONDITIONS_DATA (DB-driven conditions)
  const condData = (window.CONDITIONS_DATA || []).find(c => c.id === condition);
  if (condData) {
    const { type, operator, value, value2 } = condData;
    if (type === 'customer') {
      const all = window.ORDERS || [];
      return !all.some(o => o.id !== order.id && o.company?.id === order.company?.id &&
        ['active','provisioning','approved'].includes(o.status?.id));
    }
    const subject = type === 'mrr' ? mrr : type === 'contract' || type === 'contract_months' ? months : null;
    if (subject === null) return true;
    if (operator === '>'  || operator === 'gt')  return subject > value;
    if (operator === '>=' || operator === 'gte') return subject >= value;
    if (operator === '<'  || operator === 'lt')  return subject < value;
    if (operator === '<=' || operator === 'lte') return subject <= value;
    if (operator === '='  || operator === 'eq')  return subject === value;
    if (operator === 'between') return subject >= value && subject <= (value2 ?? value);
    return true;
  }

  // Fallback: hardcoded system condition IDs
  if (condition === 'mrr_gt_50k')       return mrr > 50000;
  if (condition === 'mrr_gt_200k')      return mrr > 200000;
  if (condition === 'mrr_gt_500k')      return mrr > 500000;
  if (condition === 'contract_gt_24mo') return months >= 24;
  if (condition === 'new_customer') {
    const all = window.ORDERS || [];
    return !all.some(o => o.id !== order.id && o.company?.id === order.company?.id &&
      ['active','provisioning','approved'].includes(o.status?.id));
  }
  return true;
};

// Build approval items filtered to the given user's pending approvals
const buildPendingItems = (allOrders) => {
  const workflows = window.DEFAULT_WORKFLOWS || DEFAULT_WORKFLOWS || {};
  const pending = allOrders.filter(o =>
    o.status?.id === 'pending_apv' || o.status?.id === 'submitted'
  );
  return pending.map(o => {
    // Merge stages across ALL products (same logic as SLATimeline & submit)
    const seenApprovers = new Map();
    (o.items || []).forEach(it => {
      (workflows[it.productId] || []).forEach((s, i) => {
        const key = s.approver;
        if (!seenApprovers.has(key) || s.slaH > seenApprovers.get(key).slaH) {
          seenApprovers.set(key, { ...s, stageOrder: i });
        }
      });
    });
    const wf = [...seenApprovers.values()]
      .sort((a, b) => a.stageOrder - b.stageOrder)
      .filter(s => checkCondition(s.condition, o));

    const stageIdx = Math.min(o.approvalStage || 0, wf.length - 1);
    const currentStage = wf[stageIdx] || wf[0];
    const createdAt = o.createdAt instanceof Date ? o.createdAt : new Date(o.createdAt);
    return {
      orderId: o.id,
      order: o,
      currentStageIdx: stageIdx,
      workflow: wf,
      currentStage,
      receivedAt: new Date(createdAt.getTime() + 1000 * 60 * 60 * 4),
      slaDeadlineH: currentStage?.slaH || 48,
      requester: o.owner,
    };
  });
};

// Inbox: always filter to only stages where I am the assigned approver
const buildApprovalItems = (currentUserId) => {
  const allOrders = window.ORDERS || ORDERS || [];
  const items = buildPendingItems(allOrders);
  if (!currentUserId) return items;
  return items.filter(it => it.currentStage?.approver === currentUserId);
};

// All approvals: admin view — every pending order regardless of stage assignment
const buildAllApprovalItems = () => {
  const allOrders = window.ORDERS || ORDERS || [];
  return buildPendingItems(allOrders);
};

// Approval history (mock)
const APPROVAL_HISTORY = [
  { orderId: 'SOL-2026-0186', decision: 'approved', stage: 'Sales Lead',       at: new Date('2026-05-26T10:14:00'), remark: 'OK ตามที่หารือ — ปิด deal ใน Q2' },
  { orderId: 'SOL-2026-0185', decision: 'approved', stage: 'Solution Manager', at: new Date('2026-05-10T15:32:00'), remark: 'ลูกค้าเดิม signed 24 mo — approve' },
  { orderId: 'SOL-2026-0181', decision: 'rejected', stage: 'Solution Manager', at: new Date('2026-05-22T09:45:00'), reason: 'เอกสารไม่ครบ', remark: 'ขาดใบ ภพ.20 — ขอเอกสารเพิ่ม' },
  { orderId: 'SOL-2026-0184', decision: 'approved', stage: 'Solution Manager', at: new Date('2026-05-06T11:20:00'), remark: '—' },
];

const ApprovalsView = ({ onOpen, currentApprovalId, setCurrentApprovalId }) => {
  const [tab, setTab] = useState('inbox');
  const [refreshKey, setRefreshKey] = useState(0);

  // Permission + identity
  const { perms = {}, currentUser = {} } = React.useContext(window.PermCtx);
  const canApprove = perms['Approve orders'] === true;
  const isAdmin    = perms['Admin Setting']  === true;

  // My inbox: only orders where I am the assigned approver for the current stage
  const items = useMemo(
    () => canApprove ? buildApprovalItems(currentUser.id) : [],
    [canApprove, currentUser.id, refreshKey] // eslint-disable-line
  );

  // All approvals tab (admin only): every pending order
  const allItems = useMemo(
    () => isAdmin ? buildAllApprovalItems() : [],
    [isAdmin, refreshKey] // eslint-disable-line
  );

  // Return to inbox + force re-build items from latest window.ORDERS
  const handleBack = React.useCallback(() => {
    setCurrentApprovalId(null);
    setRefreshKey(k => k + 1);
  }, [setCurrentApprovalId]);

  if (currentApprovalId) {
    const item = items.find(x => x.orderId === currentApprovalId);
    if (item) return <ApprovalDetailView item={item} onBack={handleBack}/>;
  }

  return (
    <>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 18, gap: 16 }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: 6 }}>Solutions · Approvals</div>
          <h1 style={{ fontSize: 22, fontWeight: 500, letterSpacing: '-0.01em', margin: 0 }}>กล่องอนุมัติ</h1>
          <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 4 }}>
            คำสั่งซื้อที่รออนุมัติจากคุณ ตาม approval workflow ของแต่ละ product
          </div>
        </div>
        <Segmented options={[
          { value: 'inbox',   label: `Pending (${items.length})`, icon: 'bell' },
          { value: 'history', label: 'My decisions', icon: 'check' },
          { value: 'all',     label: 'All approvals', icon: 'list' },
        ]} value={tab} onChange={setTab}/>
      </div>

      {/* KPI strip */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, marginBottom: 18 }}>
        <SummaryStat label="AWAITING ME"     value={items.length}              sublabel="รอการอนุมัติของคุณ"           accent={items.length > 0 ? "#d97b2e" : undefined}/>
        <SummaryStat label="DUE TODAY"       value={Math.min(2, items.length)} sublabel="ครบ SLA วันนี้"             accent={items.length > 0 ? "#b8492f" : undefined}/>
        <SummaryStat label="APPROVED · 7D"   value={APPROVAL_HISTORY.filter(h => h.decision === 'approved').length} sublabel="อนุมัติใน 7 วัน"/>
        <SummaryStat label="AVG. RESPONSE"   value="6.2h"                       sublabel="เวลาตอบโดยเฉลี่ย"/>
      </div>

      {/* Permission indicator */}
      {!canApprove && (
        <div style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '5px 10px', marginBottom: 14,
          background: 'var(--negative-bg)', border: '1px solid var(--negative)',
          borderRadius: 3, fontSize: 11.5, color: 'var(--negative)',
        }}>
          <Icon name="lock" size={12}/>
          <span>Role ของคุณไม่มีอำนาจอนุมัติ — ติดต่อ System Admin</span>
        </div>
      )}

      {tab === 'inbox'   && <ApprovalInbox  items={items} onOpen={setCurrentApprovalId}/>}
      {tab === 'history' && <ApprovalHistory/>}
      {tab === 'all'     && <ApprovalAll items={allItems} onOpen={setCurrentApprovalId}/>}
    </>
  );
};

const ApprovalInbox = ({ items, onOpen }) => {
  if (items.length === 0) {
    return (
      <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4 }}>
        <Empty icon="check" title="ไม่มีคำสั่งซื้อรออนุมัติ" hint="กลับมาดูใหม่ภายหลัง"/>
      </div>
    );
  }
  return (
    <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4, overflow: 'hidden' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5 }}>
        <thead>
          <tr style={{ background: 'var(--bg-2)' }}>
            {[
              ['Order ID',    'left', 140],
              ['Company',     'left', null],
              ['Products',    'left', null],
              ['Requester',   'left', 120],
              ['Stage',       'left', 140],
              ['Monthly',     'right', 100],
              ['SLA',         'right', 100],
              ['', 'right', 110],
            ].map(([lbl, align, w], i) => (
              <th key={i} className="eyebrow" style={{ padding: '10px', textAlign: align, fontWeight: 500, borderBottom: '1px solid var(--line)', width: w || undefined }}>{lbl}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {items.map((it, i) => {
            const prods = window.PRODUCTS || PRODUCTS || [];
            const users = window.USERS || USERS || [];
            const products = it.order.items
              .map(x => prods.find(p => p.id === x.productId))
              .filter(Boolean);
            const stage = it.currentStage;
            const stageUser = stage ? users.find(u => u.id === stage.approver) : null;
            const requesterUser = users.find(u => u.id === it.requester);
            const requesterName = requesterUser?.name || it.order?.contact?.name || '—';
            const hoursLeft = Math.max(0, it.slaDeadlineH - Math.floor((Date.now() - it.receivedAt.getTime()) / 3600000));
            const urgent = hoursLeft < 12;
            return (
              <tr key={it.orderId} style={{ borderBottom: i === items.length - 1 ? 'none' : '1px solid var(--line-2)', cursor: 'pointer' }}
                onClick={() => onOpen(it.orderId)}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-hover)'}
                onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                <td className="num" style={{ padding: '12px 10px', fontWeight: 500 }}>{it.orderId}</td>
                <td style={{ padding: '12px 10px' }}>
                  <div style={{ fontWeight: 500 }}>{it.order.company?.name || '—'}</div>
                  <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{it.order.company?.sector || ''}</div>
                </td>
                <td style={{ padding: '12px 10px' }}>
                  <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
                    {products.map((p, j) => (
                      <span key={j} style={{
                        padding: '2px 7px', background: p.color + '12', color: p.color,
                        borderRadius: 2, fontSize: 11, fontWeight: 500,
                      }}>{p.name}</span>
                    ))}
                  </div>
                </td>
                <td style={{ padding: '12px 10px' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                    <Avatar name={requesterName} size={20}/>
                    <span style={{ fontSize: 11.5 }}>{requesterName}</span>
                  </div>
                </td>
                <td style={{ padding: '12px 10px' }}>
                  {stageUser ? (
                    <div>
                      <div style={{ fontSize: 11.5, fontWeight: 500 }}>{stageUser.name}</div>
                      <div style={{ fontSize: 10.5, color: 'var(--ink-3)' }}>Stage {it.currentStageIdx + 1} · {stageUser.role}</div>
                    </div>
                  ) : <span style={{ color: 'var(--ink-4)', fontSize: 12 }}>—</span>}
                </td>
                <td className="num" style={{ padding: '12px 10px', textAlign: 'right', fontWeight: 500 }}>{fmtBaht(it.order.monthly)}</td>
                <td className="num" style={{ padding: '12px 10px', textAlign: 'right' }}>
                  <span style={{
                    fontSize: 11, fontWeight: 500,
                    color: urgent ? 'var(--negative)' : hoursLeft < 24 ? '#d97b2e' : 'var(--ink-2)',
                  }}>{hoursLeft}h left</span>
                </td>
                <td style={{ padding: '12px 10px', textAlign: 'right' }}>
                  <Button variant="primary" size="sm" iconRight="arrowRight" onClick={(e) => { e.stopPropagation(); onOpen(it.orderId); }}>
                    Review
                  </Button>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

const ApprovalHistory = () => (
  <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4 }}>
    <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5 }}>
      <thead>
        <tr style={{ background: 'var(--bg-2)' }}>
          {[['Order','left'],['Decision','left'],['Stage','left'],['Reason','left'],['Remark','left'],['Decided at','right']].map(([l,a],i) => (
            <th key={i} className="eyebrow" style={{ padding: '10px', textAlign: a, fontWeight: 500, borderBottom: '1px solid var(--line)' }}>{l}</th>
          ))}
        </tr>
      </thead>
      <tbody>
        {APPROVAL_HISTORY.map((h, i) => {
          const o = ORDERS.find(x => x.id === h.orderId);
          return (
            <tr key={i} style={{ borderBottom: i === APPROVAL_HISTORY.length - 1 ? 'none' : '1px solid var(--line-2)' }}>
              <td className="num" style={{ padding: '12px 10px', fontWeight: 500 }}>
                {h.orderId}
                {o && <div style={{ fontSize: 10.5, color: 'var(--ink-3)', fontFamily: 'Kanit, sans-serif', fontWeight: 400 }}>{o.company.name}</div>}
              </td>
              <td style={{ padding: '12px 10px' }}>
                <DecisionBadge decision={h.decision}/>
              </td>
              <td style={{ padding: '12px 10px', color: 'var(--ink-2)' }}>{h.stage}</td>
              <td style={{ padding: '12px 10px', color: 'var(--ink-2)' }}>
                {h.reason || <span style={{ color: 'var(--ink-4)' }}>—</span>}
              </td>
              <td style={{ padding: '12px 10px', color: 'var(--ink-2)', fontSize: 12 }}>{h.remark}</td>
              <td className="num" style={{ padding: '12px 10px', textAlign: 'right', fontSize: 11, color: 'var(--ink-2)' }}>
                {h.at.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', hour: '2-digit', minute: '2-digit' })}
              </td>
            </tr>
          );
        })}
      </tbody>
    </table>
  </div>
);

const ApprovalAll = ({ items, onOpen }) => {
  if (items.length === 0) {
    return (
      <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4 }}>
        <Empty icon="check" title="ไม่มีคำสั่งซื้อรออนุมัติในระบบ" hint="ทุก Order ได้รับการอนุมัติแล้ว"/>
      </div>
    );
  }
  const prods = window.PRODUCTS || PRODUCTS || [];
  const users = window.USERS || USERS || [];
  return (
    <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4, overflow: 'hidden' }}>
      <div style={{ padding: '10px 16px', borderBottom: '1px solid var(--line)', fontSize: 12, color: 'var(--ink-3)' }}>
        Order รออนุมัติทั้งหมดในระบบ · <span className="num" style={{ color: 'var(--ink-2)', fontWeight: 500 }}>{items.length}</span> รายการ
      </div>
      <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5 }}>
        <thead>
          <tr style={{ background: 'var(--bg-2)' }}>
            {[['Order ID','left',140],['Company','left',null],['Products','left',null],['Requester','left',120],['Approver (Stage)','left',160],['Monthly','right',100],['SLA','right',100],['','right',110]].map(([lbl,align,w],i) => (
              <th key={i} className="eyebrow" style={{ padding:'10px', textAlign:align, fontWeight:500, borderBottom:'1px solid var(--line)', width:w||undefined }}>{lbl}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {items.map((it, i) => {
            const products = it.order.items.map(x => prods.find(p => p.id === x.productId)).filter(Boolean);
            const stage = it.currentStage;
            const stageUser = stage ? users.find(u => u.id === stage.approver) : null;
            const requesterUser = users.find(u => u.id === it.requester);
            const requesterName = requesterUser?.name || it.order?.contact?.name || '—';
            const hoursLeft = Math.max(0, it.slaDeadlineH - Math.floor((Date.now() - it.receivedAt.getTime()) / 3600000));
            const urgent = hoursLeft < 12;
            return (
              <tr key={it.orderId} style={{ borderBottom: i === items.length-1 ? 'none' : '1px solid var(--line-2)', cursor:'pointer' }}
                onClick={() => onOpen && onOpen(it.orderId)}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-hover)'}
                onMouseLeave={e => e.currentTarget.style.background = ''}>
                <td className="num" style={{ padding:'12px 10px', fontWeight:500 }}>{it.orderId}</td>
                <td style={{ padding:'12px 10px' }}>
                  <div style={{ fontWeight:500 }}>{it.order.company?.name}</div>
                  <div style={{ fontSize:11, color:'var(--ink-3)' }}>{it.order.company?.sector}</div>
                </td>
                <td style={{ padding:'12px 10px' }}>
                  <div style={{ display:'flex', flexWrap:'wrap', gap:4 }}>
                    {products.map(p => (
                      <span key={p.id} style={{ padding:'2px 6px', background:p.color+'22', color:p.color, borderRadius:2, fontSize:11, fontWeight:500 }}>{p.name}</span>
                    ))}
                  </div>
                </td>
                <td style={{ padding:'12px 10px', color:'var(--ink-2)' }}>{requesterName}</td>
                <td style={{ padding:'12px 10px', color:'var(--ink-2)' }}>
                  {stageUser?.name || '—'}
                  <div style={{ fontSize:10.5, color:'var(--ink-4)' }}>Stage {it.currentStageIdx+1} · {stageUser?.role || ''}</div>
                </td>
                <td className="num" style={{ padding:'12px 10px', textAlign:'right' }}>฿{(it.order.monthly||0).toLocaleString()}</td>
                <td style={{ padding:'12px 10px', textAlign:'right' }}>
                  <span className="num" style={{ color: urgent ? 'var(--negative)' : 'var(--ink-2)', fontWeight: urgent ? 600 : 400 }}>{hoursLeft}h</span>
                  <div style={{ fontSize:10, color:'var(--ink-4)' }}>left</div>
                </td>
                <td style={{ padding:'12px 10px', textAlign:'right' }}>
                  <button onClick={e => { e.stopPropagation(); onOpen && onOpen(it.orderId); }} style={{
                    padding:'5px 14px', background:'var(--ink)', color:'#fff',
                    border:'none', borderRadius:3, cursor:'pointer', fontSize:12, fontWeight:500,
                    display:'inline-flex', alignItems:'center', gap:5,
                  }}>Review <Icon name="arrowRight" size={11}/></button>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
};

// ---------- Approval detail / decision page ----------
const ApprovalDetailView = ({ item, onBack }) => {
  const { order } = item;
  const allProds = window.PRODUCTS || PRODUCTS || [];
  const products = order.items.map(it => {
    const product = allProds.find(p => p.id === it.productId);
    const pkg     = product?.packages?.find(p => p.id === it.packageId);
    return { item: it, product, pkg };
  }).filter(x => x.product);
  const totalUnits = order.items.reduce((s, x) => s + x.qty, 0);
  const allUsers = window.USERS || USERS || [];
  const requesterUser = allUsers.find(u => u.id === item.requester);
  const requesterName = requesterUser?.name || order?.contact?.name || '—';

  // Permission to approve orders
  const { perms = {}, currentUser = {} } = React.useContext(window.PermCtx);
  const canApproveThisOrder = perms['Approve orders'] === true;
  const isAdmin = perms['Admin Setting'] === true;
  // User must be the designated approver for this stage (or System Admin as fallback)
  const isDesignatedApprover = isAdmin || item.currentStage?.approver === currentUser.id;
  const canAct = canApproveThisOrder && isDesignatedApprover;

  const [decision, setDecision] = useState('');  // 'approve' | 'reject' | 'request_info'
  const [reason, setReason] = useState('');
  const [remark, setRemark] = useState('');
  const [submitted, setSubmitted] = useState(false);
  const [viewingDoc, setViewingDoc] = useState(null); // { id, filename, orderId }
  const [viewingDocBlobUrl, setViewingDocBlobUrl] = useState(null);

  React.useEffect(() => {
    if (!viewingDoc) { setViewingDocBlobUrl(null); return; }
    let url = null;
    window.apiFetch(`/api/orders/${viewingDoc.orderId}/documents/${viewingDoc.id}/file`)
      .then(r => r.blob()).then(b => { url = URL.createObjectURL(b); setViewingDocBlobUrl(url); })
      .catch(() => setViewingDocBlobUrl(null));
    return () => { if (url) URL.revokeObjectURL(url); };
  }, [viewingDoc]);

  // Dynamic reasons from Settings (window.APPROVAL_CONFIGS), with static fallback
  const AC = window.APPROVAL_CONFIGS || {};
  const REJECT_REASONS = (AC.reject?.reasons || []).length > 0
    ? (AC.reject.reasons).map(r => r.text)
    : ['เอกสารไม่ครบถ้วน','ราคา / package ไม่ตรงกับข้อตกลง','เครดิตลูกค้าไม่ผ่าน','เกินเพดานอำนาจการอนุมัติ','ลูกค้ามี outstanding balance','อื่นๆ (โปรดระบุใน remark)'];
  const REQ_INFO_REASONS = (AC.request_info?.reasons || []).length > 0
    ? (AC.request_info.reasons).map(r => r.text)
    : ['ขอเอกสารเพิ่มเติม','ขอใบเสนอราคาฉบับล่าสุด','ขอข้อมูลผู้ติดต่อทางเทคนิค','ขอ Letter of Intent / PO','ขอข้อมูลผู้มีอำนาจลงนาม','อื่นๆ'];
  const APPROVE_REASONS = (AC.approve?.reasons || []).length > 0
    ? (AC.approve.reasons).map(r => r.text)
    : ['ลูกค้าเดิม (renew)','ส่วนลดพิเศษตามที่ได้รับอนุมัติ','ราคาตามใบเสนอราคาที่ผู้บริหารอนุมัติ'];

  const REJECT_QUICKFILL = (AC.reject?.quickfill || []).length > 0
    ? (AC.reject.quickfill).map(r => r.text)
    : ['ขาดเอกสารสำคัญ','ราคาเกินอำนาจ','รอ confirm จากลูกค้า'];
  const REQ_INFO_QUICKFILL = (AC.request_info?.quickfill || []).length > 0
    ? (AC.request_info.quickfill).map(r => r.text)
    : ['รบกวนส่งเอกสารเพิ่ม','ขอ confirm ผู้มีอำนาจลงนาม'];
  const APPROVE_QUICKFILL = (AC.approve?.quickfill || []).length > 0
    ? (AC.approve.quickfill).map(r => r.text)
    : ['ตรวจสอบครบถ้วน อนุมัติ','ส่งต่อให้ Solution Manager พิจารณา','OK ตามที่หารือทีม'];

  const reasonOptions = decision === 'reject' ? REJECT_REASONS
                       : decision === 'request_info' ? REQ_INFO_REASONS
                       : APPROVE_REASONS;

  const canSubmit = canAct && decision && (decision === 'approve' || reason.length > 0);

  const submit = async () => {
    setSubmitted(true);

    // Multi-stage approval logic
    // Build merged stages across ALL products (same logic as SLATimeline in order-detail)
    // so multi-product orders use the complete, deduplicated stage list
    const wf = window.DEFAULT_WORKFLOWS || {};
    const seenApprovers = new Map();
    (order.items || []).forEach(it => {
      (wf[it.productId] || []).forEach((s, i) => {
        const key = s.approver;
        if (!seenApprovers.has(key) || s.slaH > seenApprovers.get(key).slaH) {
          seenApprovers.set(key, { ...s, stageOrder: i });
        }
      });
    });
    const allStages = [...seenApprovers.values()]
      .sort((a, b) => a.stageOrder - b.stageOrder)
      .filter(s => checkCondition(s.condition, order));
    const currentStage = order.approvalStage || 0;
    const hasMoreStages = decision === 'approve' && (currentStage + 1) < allStages.length;

    // If approving and more stages remain → stay pending_apv, advance stage
    // Otherwise use normal status transition
    const newStatus = decision === 'approve'
      ? (hasMoreStages ? 'pending_apv' : 'approved')
      : decision === 'reject' ? 'rejected'
      : 'sent_back';
    const newApprovalStage = decision === 'approve' ? currentStage + 1 : 0;

    try {
      const r = await window.apiFetch(`/api/orders/${order.id}/status`, {
        method: 'PATCH',
        body: JSON.stringify({
          status: newStatus,
          approvalStage: newApprovalStage,
        }),
      });
      if (!r.ok) {
        const d = await r.json();
        showToast(d.error || 'เกิดข้อผิดพลาด', { variant: 'error' });
        setSubmitted(false);
        return;
      }
      // Log activity
      const actionMap = { approve: 'approved', reject: 'rejected', request_info: 'sent_back' };
      await window.apiFetch(`/api/orders/${order.id}/activities`, {
        method: 'POST',
        body: JSON.stringify({ action: actionMap[decision], note: remark || reason || null }),
      }).catch(() => {});

      // Refresh global orders — await so inbox re-renders with up-to-date data
      try {
        const initData = await window.apiFetch('/api/init').then(r => r.ok ? r.json() : null);
        if (initData?.orders) window.ORDERS = initData.orders;
      } catch {}

      const labels = { approve: 'อนุมัติ', reject: 'ปฏิเสธ', request_info: 'ขอข้อมูลเพิ่มเติม' };
      const detail = decision === 'reject'       ? 'Rejected'
                   : decision === 'request_info' ? 'Sent back to requester'
                   : hasMoreStages               ? `ส่งต่อ Stage ${currentStage + 2} — รออนุมัติจาก approver ถัดไป`
                   :                              'Approved — ทุก stage ผ่านแล้ว';
      showToast(`${labels[decision]}คำสั่งซื้อแล้ว`, {
        variant: decision === 'reject' ? 'error' : 'success',
        detail: `${order.id} → ${detail}`,
      });
      setTimeout(onBack, 1200);
    } catch {
      showToast('เกิดข้อผิดพลาด กรุณาลองใหม่', { variant: 'error' });
      setSubmitted(false);
    }
  };

  // SLA countdown
  const hoursLeft = Math.max(0, item.slaDeadlineH - Math.floor((Date.now() - item.receivedAt.getTime()) / 3600000));
  const urgent = hoursLeft < 12;

  return (
    <>
      {/* Breadcrumb */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11.5, color: 'var(--ink-3)', marginBottom: 10 }}>
        <button onClick={onBack} style={{
          background: 'none', border: 'none', cursor: 'pointer', color: 'var(--ink-3)',
          fontFamily: 'Kanit, sans-serif', fontSize: 11.5, padding: 0,
          display: 'inline-flex', alignItems: 'center', gap: 4,
        }}>
          <Icon name="chevronLeft" size={11}/> Approvals
        </button>
        <Icon name="chevron" size={9}/>
        <span className="num" style={{ color: 'var(--ink-2)' }}>{order.id}</span>
      </div>

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16, marginBottom: 16 }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 4 }}>
            <h1 className="num" style={{ fontSize: 22, fontWeight: 500, letterSpacing: '-0.01em', margin: 0 }}>{order.id}</h1>
            <span style={{
              display: 'inline-flex', alignItems: 'center', gap: 5,
              padding: '3px 8px', background: '#fef3e8', color: '#d97b2e',
              borderRadius: 2, fontSize: 11, fontWeight: 500,
            }}>
              <span style={{ width: 5, height: 5, borderRadius: '50%', background: '#d97b2e' }}/>
              รออนุมัติจากคุณ
            </span>
          </div>
          <div style={{ fontSize: 14, color: 'var(--ink-2)' }}>
            {order.company.name}
            <span style={{ color: 'var(--ink-4)', margin: '0 8px' }}>·</span>
            <span style={{ fontSize: 12 }}>คำสั่งซื้อโดย <span style={{ color: 'var(--ink)' }}>{requesterName}</span> · {fmtDate(order.createdAt)}</span>
          </div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div className="eyebrow" style={{ fontSize: 9.5 }}>SLA REMAINING</div>
          <div className="num" style={{
            fontSize: 22, fontWeight: 500, letterSpacing: '-0.01em',
            color: urgent ? 'var(--negative)' : 'var(--ink)',
          }}>
            {hoursLeft}<span style={{ fontSize: 12, color: 'var(--ink-3)', marginLeft: 3, fontWeight: 400 }}>hours left</span>
          </div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr', gap: 16, minWidth: 0 }}>
        {/* LEFT — workflow + summary + decision */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16, minWidth: 0 }}>
          {/* Approval workflow */}
          <ApprovalWorkflowPanel item={item} requesterName={requesterName}/>

          {/* Order summary */}
          <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4 }}>
            <div style={{ padding: '14px 18px 10px', borderBottom: '1px solid var(--line)' }}>
              <h3 style={{ fontSize: 14, fontWeight: 600, margin: 0 }}>Order summary</h3>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 3 }}>
                {products.length} product · {fmtInt(totalUnits)} units · {order.contractMonths} mo contract
              </div>
            </div>
            <div>
              {products.map(({ item: it, product, pkg }, i) => (
                <div key={i} style={{
                  padding: '12px 18px',
                  borderBottom: i === products.length - 1 ? 'none' : '1px solid var(--line-2)',
                  display: 'grid', gridTemplateColumns: '32px 1fr auto', gap: 12, alignItems: 'center',
                }}>
                  <ProductGlyph productId={it.productId} size={30}/>
                  <div>
                    <div style={{ fontWeight: 500, fontSize: 13 }}>{product.name} <span style={{ color: 'var(--ink-3)', fontWeight: 400 }}>· {pkg.name}</span></div>
                    <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>
                      <span className="num">{it.qty}</span> {product.unit}{it.qty > 1 ? 's' : ''} ·
                      <span className="num"> ฿{pkg.price.toLocaleString()}</span> / {product.unit} / mo
                    </div>
                  </div>
                  <div className="num" style={{ fontSize: 13.5, fontWeight: 500 }}>{fmtBaht(pkg.price * it.qty)}</div>
                </div>
              ))}
              <div style={{ padding: '12px 18px', background: 'var(--bg-2)', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                <div>
                  <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>Monthly Recurring Revenue · 12 mo contract</div>
                  <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>Total contract value: <span className="num" style={{ color: 'var(--ink)' }}>{fmtBaht(order.monthly * order.contractMonths)}</span></div>
                </div>
                <div className="num" style={{ fontSize: 20, fontWeight: 500, letterSpacing: '-0.02em' }}>{fmtBaht(order.monthly)}<span style={{ fontSize: 11, color: 'var(--ink-3)', marginLeft: 4 }}>/mo</span></div>
              </div>
            </div>
          </div>

          {/* Decision form */}
          <div style={{ background: 'var(--panel)', border: '1px solid var(--ink)', borderRadius: 4, position: 'relative' }}>
            <div style={{ padding: '14px 18px 10px', borderBottom: '1px solid var(--line)' }}>
              <h3 style={{ fontSize: 14, fontWeight: 600, margin: 0 }}>การตัดสิน</h3>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 3 }}>เลือกการดำเนินการสำหรับ Stage นี้ — ส่งต่อไปยังขั้นถัดไปหรือคืนกลับให้ผู้สมัคร</div>
            </div>

            <div style={{ padding: '16px 18px', display: 'flex', flexDirection: 'column', gap: 14 }}>
              {/* Not designated approver — show info banner */}
              {!canAct && (
                <div style={{
                  display: 'flex', alignItems: 'center', gap: 8,
                  padding: '10px 14px', background: 'var(--bg-2)',
                  border: '1px solid var(--line)', borderRadius: 3,
                  fontSize: 12, color: 'var(--ink-3)',
                }}>
                  <Icon name="lock" size={13}/>
                  {!canApproveThisOrder
                    ? 'Role ของคุณไม่มีสิทธิ์อนุมัติ — ติดต่อ System Admin'
                    : 'คุณไม่ใช่ผู้อนุมัติที่กำหนดไว้สำหรับ Stage นี้'}
                </div>
              )}
              {/* Decision picker */}
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>
                <DecisionTile
                  selected={decision === 'approve'} onClick={canAct ? () => setDecision('approve') : null}
                  icon={canAct ? 'check' : 'lock'}
                  color={canAct ? 'var(--positive)' : 'var(--ink-4)'}
                  label="Approve"
                  sub={canAct ? 'ส่งต่อขั้นถัดไป' : 'ไม่มีสิทธิ์'}
                  disabled={!canAct}/>
                <DecisionTile
                  selected={decision === 'request_info'} onClick={canAct ? () => setDecision('request_info') : null}
                  icon="alert" color={canAct ? '#d97b2e' : 'var(--ink-4)'}
                  label="Request more info" sub={canAct ? 'คืนหา requester' : 'ไม่มีสิทธิ์'}
                  disabled={!canAct}/>
                <DecisionTile
                  selected={decision === 'reject'} onClick={canAct ? () => setDecision('reject') : null}
                  icon="close" color={canAct ? 'var(--negative)' : 'var(--ink-4)'}
                  label="Reject" sub={canAct ? 'ปฏิเสธคำสั่งซื้อ' : 'ไม่มีสิทธิ์'}
                  disabled={!canAct}/>
              </div>

              {/* Reason — required if not approve */}
              {decision && decision !== 'approve' && (
                <Field label="Reason" required hint="เลือกเหตุผลที่ตรงที่สุด">
                  <Select value={reason} onChange={e => setReason(e.target.value)}>
                    <option value="">— เลือกเหตุผล —</option>
                    {reasonOptions.map(r => <option key={r} value={r}>{r}</option>)}
                  </Select>
                </Field>
              )}
              {decision === 'approve' && (
                <Field label="Reason" hint="ระบุได้หากต้องการอ้างอิงเงื่อนไขพิเศษ (ไม่บังคับ)">
                  <Select value={reason} onChange={e => setReason(e.target.value)}>
                    <option value="">— ไม่ระบุ —</option>
                    {APPROVE_REASONS.map(r => <option key={r} value={r}>{r}</option>)}
                  </Select>
                </Field>
              )}

              {/* Remark — always optional, longer text */}
              <Field label="Remark" hint="หมายเหตุเพิ่มเติมที่จะส่งให้ requester และบันทึกใน audit log">
                <Textarea value={remark} onChange={e => setRemark(e.target.value)} rows={3}
                  placeholder={decision === 'reject'
                    ? 'เช่น ขอแนบหนังสือมอบอำนาจที่ลงนามภายในไตรมาสนี้'
                    : decision === 'request_info'
                    ? 'ระบุข้อมูลที่ต้องการให้ผู้สมัครเพิ่มเติม'
                    : 'หมายเหตุประกอบการอนุมัติ (ถ้ามี)'}/>
              </Field>

              {/* Quick-fill remark templates */}
              {decision && (
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', fontSize: 11 }}>
                  <span style={{ color: 'var(--ink-3)' }}>Quick fill:</span>
                  {(decision === 'approve' ? APPROVE_QUICKFILL
                    : decision === 'reject' ? REJECT_QUICKFILL
                    : REQ_INFO_QUICKFILL
                  ).map(t => (
                    <button key={t} onClick={() => setRemark(remark ? remark + ' · ' + t : t)} style={{
                      padding: '3px 8px', background: 'var(--bg-2)', border: '1px solid var(--line)',
                      borderRadius: 2, cursor: 'pointer', fontFamily: 'Kanit, sans-serif', fontSize: 11,
                      color: 'var(--ink-2)',
                    }}>+ {t}</button>
                  ))}
                </div>
              )}

              {/* Footer */}
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderTop: '1px solid var(--line-2)', paddingTop: 12 }}>
                <div style={{ fontSize: 11, color: 'var(--ink-3)', display: 'flex', alignItems: 'center', gap: 6 }}>
                  <Icon name="shield" size={12}/>
                  การตัดสินใจของคุณจะถูกบันทึกใน audit log และส่งแจ้งไปยัง requester
                </div>
                <div style={{ display: 'flex', gap: 8 }}>
                  <Button variant="ghost" onClick={onBack}>Cancel</Button>
                  <Button
                    variant={decision === 'reject' ? 'danger' : 'accent'}
                    icon={decision === 'reject' ? 'close' : 'check'}
                    disabled={!canSubmit || submitted}
                    onClick={submit}>
                    {decision === 'reject' ? 'Reject order'
                     : decision === 'request_info' ? 'Return to requester'
                     : 'Approve order'}
                  </Button>
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* RIGHT — context */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4 }}>
            <div style={{ padding: '14px 18px 10px', borderBottom: '1px solid var(--line)' }}>
              <h3 style={{ fontSize: 14, fontWeight: 600, margin: 0 }}>Customer</h3>
            </div>
            <div style={{ padding: 16 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
                <Avatar name={order.company.name} size={36} square/>
                <div>
                  <div style={{ fontWeight: 500, fontSize: 13.5 }}>{order.company.name}</div>
                  <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{order.company.sector}</div>
                </div>
              </div>
              <DefRow label="Tax ID"   value={<span className="num">{order.company.taxId}</span>}/>
              <DefRow label="Size"     value={`${order.company.size} employees`}/>
              <DefRow label="Province" value={order.company.province}/>
            </div>
          </div>

          <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4 }}>
            <div style={{ padding: '14px 18px 10px', borderBottom: '1px solid var(--line)' }}>
              <h3 style={{ fontSize: 14, fontWeight: 600, margin: 0 }}>Documents</h3>
              <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 3 }}>{order.documents.length} ไฟล์แนบ</div>
            </div>
            <div>
              {(order.documents || []).length === 0 && (
                <div style={{ padding: '12px 16px', fontSize: 12, color: 'var(--ink-4)', textAlign: 'center' }}>
                  ยังไม่มีเอกสารแนบ
                </div>
              )}
              {(order.documents || []).map((d, i) => {
                const rawName = typeof d === 'string' ? d : (d.filename || '');
                // Fix Latin-1 mis-encoded UTF-8 filenames from legacy uploads
                let filename = rawName;
                try {
                  const decoded = decodeURIComponent(escape(rawName));
                  if (decoded !== rawName) filename = decoded;
                } catch {}
                const size = typeof d === 'object' ? d.size : null;
                const docId = typeof d === 'object' ? d.id : null;
                const handleDownload = async () => {
                  if (!docId) return;
                  try {
                    const r = await window.apiFetch(`/api/orders/${order.id}/documents/${docId}/file`);
                    if (!r.ok) return;
                    const blob = await r.blob();
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url; a.download = filename; a.click();
                    setTimeout(() => URL.revokeObjectURL(url), 10000);
                  } catch {}
                };
                return (
                  <div key={i} style={{
                    padding: '10px 16px',
                    borderBottom: i === (order.documents.length - 1) ? 'none' : '1px solid var(--line-2)',
                    display: 'flex', alignItems: 'center', gap: 10,
                  }}>
                    <Icon name="fileCheck" size={14} color="var(--positive)"/>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 12, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{filename}</div>
                      {size && <div style={{ fontSize: 10.5, color: 'var(--ink-3)' }}>{size}</div>}
                    </div>
                    {docId && (
                      <div style={{ display: 'flex', gap: 4, flexShrink: 0 }}>
                        <button onClick={() => setViewingDoc({ id: docId, filename, orderId: order.id })} title="ดูเอกสาร"
                          style={{ background: 'none', border: '1px solid var(--line)', borderRadius: 3, cursor: 'pointer', color: 'var(--ink-2)', padding: '3px 8px', fontSize: 11, display: 'flex', alignItems: 'center', gap: 4 }}>
                          <Icon name="eye" size={11}/> View
                        </button>
                        <button onClick={handleDownload} title="ดาวน์โหลด"
                          style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--ink-3)', padding: 3 }}>
                          <Icon name="download" size={12}/>
                        </button>
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          </div>

          <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4 }}>
            <div style={{ padding: '14px 18px 10px', borderBottom: '1px solid var(--line)' }}>
              <h3 style={{ fontSize: 14, fontWeight: 600, margin: 0 }}>Requester message</h3>
            </div>
            <div style={{ padding: 14, display: 'flex', gap: 10 }}>
              <Avatar name={requesterName} size={28}/>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 12, fontWeight: 500 }}>{requesterName}</div>
                <div style={{ fontSize: 10.5, color: 'var(--ink-3)' }}>{item.receivedAt.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', hour: '2-digit', minute: '2-digit' })}</div>
                {order.notes ? (
                  <div style={{ fontSize: 12, color: 'var(--ink-2)', marginTop: 8, lineHeight: 1.6, background: 'var(--bg-2)', padding: 10, borderRadius: 3 }}>
                    {order.notes}
                  </div>
                ) : (
                  <div style={{ fontSize: 12, color: 'var(--ink-4)', marginTop: 8, fontStyle: 'italic' }}>
                    ไม่มีข้อความแนบ
                  </div>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>

      {viewingDoc && (
        <div style={{
          position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.7)', zIndex: 1200,
          display: 'flex', flexDirection: 'column', padding: 24,
        }} onClick={e => { if (e.target === e.currentTarget) setViewingDoc(null); }}>
          <div style={{
            background: 'var(--panel)', borderRadius: 6, flex: 1,
            display: 'flex', flexDirection: 'column', overflow: 'hidden',
            border: '1px solid var(--line)', boxShadow: '0 8px 40px rgba(0,0,0,0.3)',
          }}>
            <div style={{
              padding: '12px 18px', borderBottom: '1px solid var(--line)',
              display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12,
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <Icon name="file" size={14} color="var(--ink-3)"/>
                <span style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink)' }}>{viewingDoc.filename}</span>
              </div>
              <button onClick={() => setViewingDoc(null)} style={{
                background: 'none', border: 'none', cursor: 'pointer', color: 'var(--ink-3)',
                padding: 4, display: 'flex', alignItems: 'center', gap: 5, fontSize: 12,
              }}>
                <Icon name="close" size={14}/> ปิด
              </button>
            </div>
            {viewingDocBlobUrl ? (
              <iframe src={viewingDocBlobUrl} style={{ flex: 1, border: 'none', width: '100%' }} title={viewingDoc.filename}/>
            ) : (
              <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--ink-4)', fontSize: 13 }}>
                กำลังโหลด...
              </div>
            )}
          </div>
        </div>
      )}
    </>
  );
};

// ---------- Approval workflow panel ----------
const ApprovalWorkflowPanel = ({ item, requesterName }) => {
  const { workflow, currentStageIdx } = item;
  const allUsers = window.USERS || USERS || [];
  const allProds = window.PRODUCTS || PRODUCTS || [];
  const productName = allProds.find(p => p.id === item.order.items[0]?.productId)?.name
                   || item.order.items[0]?.productId || '—';
  return (
    <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 4 }}>
      <div style={{ padding: '14px 18px 10px', borderBottom: '1px solid var(--line)' }}>
        <h3 style={{ fontSize: 14, fontWeight: 600, margin: 0 }}>Approval workflow</h3>
        <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginTop: 3 }}>
          ลำดับการอนุมัติของ {productName} ({workflow.length} stages)
        </div>
      </div>
      <div style={{ padding: '18px 18px 16px' }}>
        <div style={{ display: 'flex', alignItems: 'stretch', gap: 6, overflowX: 'auto' }} className="matrix-scroll">
          {/* Requester start node */}
          <ApprovalNode
            icon="plus" label="Submitted"
            who={requesterName} subLabel="Requester"
            state="done" badge="START"/>
          <ApprovalArrow done/>
          {workflow.map((stage, idx) => {
            const user  = allUsers.find(u => u.id === stage.approver);
            const state = idx < currentStageIdx ? 'done' : idx === currentStageIdx ? 'active' : 'pending';
            return (
              <React.Fragment key={stage.id}>
                <ApprovalNode
                  icon={state === 'done' ? 'check' : state === 'active' ? 'clock' : 'dot'}
                  label={user?.role || user?.name || 'Approver'}
                  who={user?.name || '—'}
                  subLabel={`Stage ${idx + 1} · ${stage.slaH}h SLA`}
                  state={state}
                  badge={state === 'active' ? 'YOU' : null}/>
                <ApprovalArrow done={state === 'done'}/>
              </React.Fragment>
            );
          })}
          {/* End node */}
          <ApprovalNode icon="check" label="Approved" subLabel="พร้อม provision" state="pending" badge="END"/>
        </div>
      </div>
    </div>
  );
};

const ApprovalNode = ({ icon, label, who, subLabel, state, badge }) => {
  const colors = {
    done:    { bg: '#e3f1ea', fg: 'var(--positive)', border: 'var(--positive)' },
    active:  { bg: '#fef0e0', fg: 'var(--accent-2)', border: 'var(--accent-2)' },
    pending: { bg: 'var(--bg-2)', fg: 'var(--ink-3)', border: 'var(--line-3)' },
  };
  const c = colors[state];
  return (
    <div style={{
      background: c.bg, border: `1px solid ${c.border}`,
      borderRadius: 4, padding: '10px 12px', minWidth: 140, position: 'relative', flexShrink: 0,
    }}>
      {badge && (
        <div style={{
          position: 'absolute', top: -8, right: 8,
          background: c.fg, color: '#fff',
          padding: '1px 6px', borderRadius: 2,
          fontSize: 9, fontWeight: 600, letterSpacing: '0.06em', fontFamily: 'IBM Plex Mono',
        }}>{badge}</div>
      )}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, color: c.fg, marginBottom: 4 }}>
        <Icon name={icon} size={11}/>
        <span style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.04em' }}>{label}</span>
      </div>
      {who && <div style={{ fontSize: 12, fontWeight: 500, color: 'var(--ink)' }}>{who}</div>}
      <div style={{ fontSize: 10.5, color: 'var(--ink-3)', marginTop: 2 }}>{subLabel}</div>
    </div>
  );
};

const ApprovalArrow = ({ done }) => (
  <div style={{ display: 'flex', alignItems: 'center', flexShrink: 0, color: done ? 'var(--positive)' : 'var(--ink-4)' }}>
    <span style={{ width: 14, height: 1, background: done ? 'var(--positive)' : 'var(--line-3)' }}/>
    <Icon name="chevron" size={11}/>
  </div>
);

const DecisionTile = ({ selected, onClick, icon, color, label, sub, disabled }) => (
  <button onClick={disabled ? undefined : onClick} style={{
    padding: '12px 14px',
    background: selected ? color : disabled ? 'var(--bg-2)' : 'var(--panel)',
    border: `1px solid ${selected ? color : disabled ? 'var(--line-2)' : 'var(--line)'}`,
    borderRadius: 3, cursor: disabled ? 'not-allowed' : 'pointer', textAlign: 'left',
    fontFamily: 'Kanit, sans-serif',
    transition: 'all 120ms', position: 'relative',
    opacity: disabled ? 0.6 : 1,
  }} onMouseEnter={e => { if (!selected && !disabled) e.currentTarget.style.borderColor = color; }}
     onMouseLeave={e => { if (!selected && !disabled) e.currentTarget.style.borderColor = 'var(--line)'; }}>
    <div style={{ display: 'flex', alignItems: 'center', gap: 6, color: selected ? '#fff' : color }}>
      <Icon name={icon} size={13}/>
      <span style={{ fontSize: 13, fontWeight: 500 }}>{label}</span>
    </div>
    <div style={{ fontSize: 11, color: selected ? 'rgba(255,255,255,0.85)' : 'var(--ink-3)', marginTop: 3 }}>{sub}</div>
  </button>
);

const DecisionBadge = ({ decision }) => {
  const cfg = {
    approved: { bg: 'var(--positive-bg)', fg: 'var(--positive)', label: 'Approved' },
    rejected: { bg: 'var(--negative-bg)', fg: 'var(--negative)', label: 'Rejected' },
    request_info: { bg: '#fef3e8', fg: '#d97b2e', label: 'Info requested' },
  }[decision];
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      padding: '2px 8px', background: cfg.bg, color: cfg.fg,
      borderRadius: 2, fontSize: 11, fontWeight: 500,
    }}>
      <span style={{ width: 5, height: 5, borderRadius: '50%', background: cfg.fg }}/>
      {cfg.label}
    </span>
  );
};

const DefRow = ({ label, value }) => (
  <div style={{ display: 'flex', justifyContent: 'space-between', padding: '5px 0', fontSize: 12 }}>
    <span style={{ color: 'var(--ink-3)' }}>{label}</span>
    <span style={{ color: 'var(--ink)', textAlign: 'right' }}>{value}</span>
  </div>
);

Object.assign(window, { ApprovalsView, ApprovalDetailView });
