// Requests Page — Sayfa 5
// Liste + tıklanınca detay (timeline + ürün listesi + çıkarılan ürünler)
// State: selectedId; null = liste, set = detay

// ─────────── Data ───────────
const REQUEST_STATUSES = {
  draft:     { label: 'Taslak',         color: '#64748B', bg: 'rgba(100,116,139,0.10)', dot: '#94A3B8' },
  pending:   { label: 'Onay Bekliyor',  color: '#B45309', bg: 'rgba(245,158,11,0.12)',  dot: '#F59E0B' },
  approved:  { label: 'Onaylandı',      color: '#047857', bg: 'rgba(16,185,129,0.12)',  dot: '#10B981' },
  rejected:  { label: 'Reddedildi',     color: '#B91C1C', bg: 'rgba(239,68,68,0.12)',   dot: '#EF4444' },
  completed: { label: 'Tamamlandı',     color: '#1D4ED8', bg: 'rgba(37,99,235,0.12)',   dot: '#3B82F6' },
};

const REQUEST_STEPS = ['Yöneticim', 'Üst Yönetim', 'IT Onayı', 'Satınalma'];

const REQUESTS = [
  {
    id: '#IT-2026-00135',
    date: '21 May 2026',
    submittedAt: null,
    status: 'draft',
    netSubtotal: 18500,
    items: [
      { name: 'Dell UltraSharp U2723QE 27"', imgKind: 'monitor' },
    ],
    currentStep: -1,
  },
  {
    id: '#IT-2026-00123',
    date: '12 May 2026',
    submittedAt: '12 May 2026, 14:32',
    status: 'pending',
    netSubtotal: 49200, // 45000+4200 (M365 çıkarıldıktan sonra)
    originalSubtotal: 54120,
    items: [
      { id: 'p01', name: 'Dell Latitude 5550 Business Laptop', brand: 'Dell', model: 'Latitude 5550', imgKind: 'laptop', qty: 1, priceNet: 45000,
        justification: 'Mevcut Dell Latitude 5400 cihazım 2019 model. Power BI ve Excel modelleri üzerinde çalışırken sürekli takılıyor.',
        state: 'approved' },
      { id: 'p07', name: 'Logitech MX Keys S Kablosuz Klavye', brand: 'Logitech', model: 'MX Keys S', imgKind: 'keyboard', qty: 1, priceNet: 4200,
        justification: 'Mevcut klavyemde W ve E tuşları sıkışıyor, yazı yazma hızım düştü.',
        state: 'approved' },
      { id: 'p13', name: 'Microsoft 365 Business Standard', brand: 'Microsoft', model: 'M365 BS', imgKind: 'software-ms', qty: 1, priceNet: 4920,
        priceUnit: 'yıllık/kullanıcı',
        justification: 'Outlook + Teams için lisans yenilenmesi gerekiyor.',
        state: 'removed',
        removalReason: 'Mevcut M365 lisansınız 2026 Q3 sonuna kadar geçerli. Bu kalemi Q3 yenilemesinde toplu satınalma ile birleştireceğim.' },
    ],
    currentStep: 1, // 0 done, 1 pending
    timeline: [
      { kind: 'submitted', actor: 'Ayşe Kaya',     role: 'Talebi oluşturan',  time: '12 May 2026, 14:32' },
      { kind: 'approved',  actor: 'Mehmet Demir',  role: 'Yöneticim',         time: '13 May 2026, 09:15',
        note: 'Onaylandı, devam edebilir. M365 lisans kalemini Q3 satınalmaya taşıdım — şu an mevcut lisans geçerli.' },
      { kind: 'removed',   actor: 'Mehmet Demir',  role: 'Yöneticim',         time: '13 May 2026, 09:15',
        note: '1 ürün talepten çıkarıldı: Microsoft 365 Business Standard.' },
      { kind: 'pending',   actor: 'Üst Yönetim',   role: 'Departman Direktörü', time: null },
      { kind: 'queued',    actor: 'IT Onayı',      role: 'Teknik uygunluk',   time: null },
      { kind: 'queued',    actor: 'Satınalma',     role: 'Sipariş & teslim',  time: null },
    ],
  },
  {
    id: '#IT-2026-00118',
    date: '02 May 2026',
    submittedAt: '02 May 2026, 11:08',
    status: 'completed',
    netSubtotal: 28500,
    items: [
      { name: 'Dell OptiPlex 7020 Micro', imgKind: 'desktop' },
    ],
    currentStep: 4,
    timeline: [
      { kind: 'submitted', actor: 'Ayşe Kaya',     role: 'Talebi oluşturan',     time: '02 May 2026, 11:08' },
      { kind: 'approved',  actor: 'Mehmet Demir',  role: 'Yöneticim',            time: '02 May 2026, 14:20',
        note: 'Eski masaüstü yenileme talebi standartlara uygun, onaylıyorum.' },
      { kind: 'approved',  actor: 'Elif Yılmaz',   role: 'Departman Direktörü',  time: '03 May 2026, 10:45',
        note: 'Departman bütçesi uygun.' },
      { kind: 'approved',  actor: 'Ahmet Kara',    role: 'IT Onayı',             time: '03 May 2026, 16:12',
        note: 'Donanım envantere uyumlu, teknik onay verildi.' },
      { kind: 'completed', actor: 'Satınalma',     role: 'Sipariş & teslim',     time: '06 May 2026, 09:30',
        note: 'Sipariş verildi, kullanıcıya teslim edildi.' },
    ],
  },
  {
    id: '#IT-2026-00115',
    date: '28 Nis 2026',
    submittedAt: '28 Nis 2026, 16:40',
    status: 'rejected',
    netSubtotal: 124000,
    items: [
      { name: 'Network Danışmanlığı — 10 günlük paket', imgKind: 'service' },
    ],
    currentStep: 1,
    rejectedAt: 1, // Üst Yönetim
    rejectionReason: 'Q1\'de aynı danışmanlık için bütçe ayrıldı ve henüz tüketilmedi. Yeni talep Q3\'te değerlendirilebilir.',
    timeline: [
      { kind: 'submitted', actor: 'Ayşe Kaya',    role: 'Talebi oluşturan',     time: '28 Nis 2026, 16:40' },
      { kind: 'approved',  actor: 'Mehmet Demir', role: 'Yöneticim',            time: '29 Nis 2026, 10:15',
        note: 'Yöneticim onayı verildi, bütçe değerlendirmesi için Üst Yönetime sevk edildi.' },
      { kind: 'rejected',  actor: 'Elif Yılmaz',  role: 'Departman Direktörü',  time: '30 Nis 2026, 11:20',
        note: 'Q1\'de aynı danışmanlık için bütçe ayrıldı ve henüz tüketilmedi. Yeni talep Q3\'te değerlendirilebilir.' },
    ],
  },
  {
    id: '#IT-2026-00099',
    date: '15 Nis 2026',
    submittedAt: '15 Nis 2026, 10:22',
    status: 'pending',
    netSubtotal: 25000,
    items: [
      { name: 'Dell UltraSharp U2723QE', imgKind: 'monitor' },
      { name: 'Jabra Evolve2 65', imgKind: 'headset' },
    ],
    currentStep: 3, // Satınalma aşaması
    timeline: [
      { kind: 'submitted', actor: 'Ayşe Kaya',     role: 'Talebi oluşturan',     time: '15 Nis 2026, 10:22' },
      { kind: 'approved',  actor: 'Mehmet Demir',  role: 'Yöneticim',            time: '16 Nis 2026, 08:45',
        note: 'Hibrit çalışma kurulumu için onaylıyorum.' },
      { kind: 'approved',  actor: 'Elif Yılmaz',   role: 'Departman Direktörü',  time: '17 Nis 2026, 14:10',
        note: 'Departman bütçesi uygun.' },
      { kind: 'approved',  actor: 'Ahmet Kara',    role: 'IT Onayı',             time: '18 Nis 2026, 11:30',
        note: 'Teknik özellikler uyumlu, sipariş için onay verildi.' },
      { kind: 'pending',   actor: 'Satınalma',     role: 'Sipariş & teslim',     time: null,
        note: 'Tedarikçiden teslim tarihi bekleniyor.' },
    ],
  },
  {
    id: '#IT-2026-00087',
    date: '08 Nis 2026',
    submittedAt: '08 Nis 2026, 14:05',
    status: 'completed',
    netSubtotal: 4200,
    items: [
      { name: 'Logitech MX Keys S', imgKind: 'keyboard' },
    ],
    currentStep: 4,
    timeline: [
      { kind: 'submitted', actor: 'Ayşe Kaya',     role: 'Talebi oluşturan',     time: '08 Nis 2026, 14:05' },
      { kind: 'approved',  actor: 'Mehmet Demir',  role: 'Yöneticim',            time: '09 Nis 2026, 09:20',
        note: 'Klavye yenileme talebi onaylandı.' },
      { kind: 'approved',  actor: 'Elif Yılmaz',   role: 'Departman Direktörü',  time: '09 Nis 2026, 15:40' },
      { kind: 'approved',  actor: 'Ahmet Kara',    role: 'IT Onayı',             time: '10 Nis 2026, 10:05',
        note: 'Standart aksesuar talebi, onaylandı.' },
      { kind: 'completed', actor: 'Satınalma',     role: 'Sipariş & teslim',     time: '12 Nis 2026, 14:30',
        note: 'Ürün teslim edildi.' },
    ],
  },
  {
    id: '#IT-2026-00076',
    date: '01 Nis 2026',
    submittedAt: '01 Nis 2026, 09:40',
    status: 'rejected',
    netSubtotal: 58900,
    items: [
      { name: 'MacBook Air M3 13"', imgKind: 'laptop' },
    ],
    currentStep: 0,
    rejectedAt: 0, // Yöneticim
    rejectionReason: 'Mevcut Dell Latitude cihazınız standart iş yüklerine yeterli. macOS\'a geçiş için pre-approval ve teknik gereklilik dokümantasyonu gerekli.',
    timeline: [
      { kind: 'submitted', actor: 'Ayşe Kaya',    role: 'Talebi oluşturan',  time: '01 Nis 2026, 09:40' },
      { kind: 'rejected',  actor: 'Mehmet Demir', role: 'Yöneticim',         time: '01 Nis 2026, 17:15',
        note: 'Mevcut Dell Latitude cihazınız standart iş yüklerine yeterli. macOS\'a geçiş için pre-approval ve teknik gereklilik dokümantasyonu gerekli.' },
    ],
  },
];

// ─────────── Görsel eşleştirici ───────────
// Talep kalemleri bazen sadece isim içerir; CATALOG_PRODUCTS üzerinden imgFolder'ı bulur.
function resolveRequestItemImg(item) {
  if (!item) return null;
  if (item.imgFolder) return { folder: item.imgFolder, ext: item.imgExt || 'jpg' };
  const list = window.CATALOG_PRODUCTS || [];
  let cp = null;
  if (item.id) cp = list.find((p) => p.id === item.id);
  if (!cp && item.name) {
    cp = list.find((p) => p.name === item.name)
      || list.find((p) => p.name.startsWith(item.name))
      || list.find((p) => item.name.startsWith(p.name));
  }
  if (!cp || !cp.imgFolder) return null;
  return { folder: cp.imgFolder, ext: cp.imgExt || 'jpg' };
}
function requestItemImgSrc(item) {
  const r = resolveRequestItemImg(item);
  return r ? `images/products/${r.folder}/1.${r.ext}` : null;
}

// ─────────── Status badge & mini progress ───────────
function StatusBadge({ status, c, size = 'md' }) {
  const s = REQUEST_STATUSES[status];
  const padding = size === 'sm' ? '4px 9px' : '5px 11px';
  const fontSize = size === 'sm' ? 11 : 12;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding, borderRadius: 999,
      background: s.bg, color: s.color,
      fontSize, fontWeight: 600,
    }}>
      <span style={{
        width: 6, height: 6, borderRadius: 999, background: s.dot,
        animation: status === 'pending' ? 'pulseDot 1.6s ease-in-out infinite' : 'none',
      }} />
      {s.label}
    </span>
  );
}

function MiniProgress({ req, c }) {
  // 4 dots in a row connected by lines
  // states: done (green check), current-pending (amber pulse), current-rejected (red x), queued (gray)
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 0, width: '100%', maxWidth: 360 }}>
      {REQUEST_STEPS.map((step, i) => {
        let kind = 'queued';
        if (req.status === 'completed') kind = 'done';
        else if (req.status === 'rejected') {
          if (i < req.rejectedAt) kind = 'done';
          else if (i === req.rejectedAt) kind = 'rejected';
        } else if (req.status === 'pending') {
          if (i < req.currentStep) kind = 'done';
          else if (i === req.currentStep) kind = 'pending';
        } else if (req.status === 'draft') {
          kind = 'queued';
        }

        const colors = {
          done:     { bg: c.success,       fg: '#fff',     line: c.success },
          pending:  { bg: '#F59E0B',       fg: '#fff',     line: c.borderSoft },
          rejected: { bg: c.danger,        fg: '#fff',     line: c.borderSoft },
          queued:   { bg: c.borderSoft,    fg: c.muted,    line: c.borderSoft },
        }[kind];

        return (
          <React.Fragment key={i}>
            <div title={step + (kind === 'done' ? ' · tamamlandı' : kind === 'pending' ? ' · bekliyor' : kind === 'rejected' ? ' · reddedildi' : ' · sırada')}
              style={{
                width: 22, height: 22, borderRadius: 999,
                background: colors.bg, color: colors.fg,
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 10, fontWeight: 700, flexShrink: 0,
                animation: kind === 'pending' ? 'pulseDot 1.6s ease-in-out infinite' : 'none',
                boxShadow: kind === 'pending' ? `0 0 0 4px ${colors.bg}33` : 'none',
              }}>
              {kind === 'done' && (
                <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3.4" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M20 6L9 17l-5-5" />
                </svg>
              )}
              {kind === 'rejected' && (
                <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3.4" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M18 6L6 18M6 6l12 12" />
                </svg>
              )}
              {(kind === 'queued' || kind === 'pending') && <span>{i + 1}</span>}
            </div>
            {i < REQUEST_STEPS.length - 1 && (
              <div style={{ flex: 1, height: 2, background: colors.line, minWidth: 24 }} />
            )}
          </React.Fragment>
        );
      })}
    </div>
  );
}

// ─────────── List row card ───────────
function RequestRow({ req, c, onOpen }) {
  const [hover, setHover] = React.useState(false);
  const status = REQUEST_STATUSES[req.status];
  return (
    <div
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        background: c.card,
        border: `1px solid ${c.border}`,
        borderRadius: 14,
        padding: 18,
        display: 'grid', gridTemplateColumns: '210px 1fr 240px 130px', gap: 24,
        alignItems: 'center',
        transition: 'border-color 160ms, box-shadow 160ms',
        borderColor: hover ? c.primary + '55' : c.border,
        boxShadow: hover ? `0 4px 14px -6px rgba(15,23,42,0.10)` : 'none',
      }}>
      {/* Left: ID + date + status */}
      <div>
        <div style={{
          fontFamily: 'ui-monospace, "SF Mono", Menlo, monospace',
          fontSize: 13, fontWeight: 700, color: c.text,
          letterSpacing: '0.02em',
        }}>{req.id}</div>
        <div style={{ fontSize: 11.5, color: c.muted, marginTop: 3 }}>
          {req.submittedAt ? req.submittedAt : 'Henüz gönderilmedi'}
        </div>
        <div style={{ marginTop: 9, display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
          <StatusBadge status={req.status} c={c} size="sm" />
          {req.kind === 'custom' && (
            <span style={{
              display: 'inline-flex', alignItems: 'center', gap: 4,
              padding: '4px 9px', borderRadius: 999,
              background: 'rgba(245,158,11,0.12)', color: '#B45309',
              fontSize: 11, fontWeight: 600,
              border: '1px solid rgba(245,158,11,0.30)',
            }}>
              <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M12 2l2.39 4.84L19.8 7.6l-3.9 3.8.92 5.37L12 14.27l-4.82 2.5.92-5.37L4.2 7.6l5.41-.76L12 2z" />
              </svg>
              Özel Talep
            </span>
          )}
        </div>
      </div>

      {/* Middle: product thumbs + count + amount */}
      <div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 8 }}>
          {req.items.slice(0, 4).map((it, i) => (
            <div key={i} style={{
              width: 40, height: 40, borderRadius: 8, overflow: 'hidden',
              border: `1px solid ${c.border}`, flexShrink: 0,
            }}>
              <ProductPlaceholder kind={it.imgKind} c={c} imgSrc={requestItemImgSrc(it)} />
            </div>
          ))}
          {req.items.length > 4 && (
            <div style={{
              width: 40, height: 40, borderRadius: 8,
              border: `1px solid ${c.border}`, background: c.borderSoft,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontSize: 11, fontWeight: 600, color: c.muted,
            }}>+{req.items.length - 4}</div>
          )}
        </div>
        <div style={{ fontSize: 12.5, color: c.text }}>
          <strong style={{ fontWeight: 600 }}>{req.items.length} ürün</strong>
          <span style={{ color: c.muted }}> · {formatTL(req.netSubtotal)} <span style={{ color: c.subtle, fontSize: 11 }}>KDV hariç</span></span>
        </div>
      </div>

      {/* Progress */}
      <div>
        {req.status === 'draft' ? (
          <div style={{
            fontSize: 12, color: c.muted,
            padding: '10px 12px',
            background: c.borderSoft,
            border: `1px dashed ${c.border}`, borderRadius: 8,
            display: 'inline-block',
          }}>Onaya gönderilmedi · taslak</div>
        ) : (
          <React.Fragment>
            <MiniProgress req={req} c={c} />
            {req.status === 'pending' && (
              <div style={{ fontSize: 11.5, color: c.muted, marginTop: 8 }}>
                Aşama: <strong style={{ color: c.text, fontWeight: 600 }}>{REQUEST_STEPS[req.currentStep]}</strong>
              </div>
            )}
            {req.status === 'rejected' && (
              <div style={{ fontSize: 11.5, color: c.danger, marginTop: 8, fontWeight: 500 }}>
                Aşamada reddedildi: {REQUEST_STEPS[req.rejectedAt]}
              </div>
            )}
            {req.status === 'completed' && (
              <div style={{ fontSize: 11.5, color: c.muted, marginTop: 8 }}>
                Tüm aşamalar tamamlandı
              </div>
            )}
          </React.Fragment>
        )}
      </div>

      {/* Right: button */}
      <div style={{ textAlign: 'right' }}>
        <button
          onClick={() => {
            if (req.status === 'draft') {
              // Taslaktaki ürünleri katalogtan eşleştirip sepete yükle
              const list = window.CATALOG_PRODUCTS || [];
              const found = []; // { pid, qty }
              const missing = [];
              req.items.forEach((it) => {
                let cp = null;
                if (it.id) cp = list.find((p) => p.id === it.id);
                if (!cp && it.name) {
                  cp = list.find((p) => p.name === it.name)
                    || list.find((p) => p.name.startsWith(it.name))
                    || list.find((p) => it.name.startsWith(p.name));
                }
                if (cp) found.push({ pid: cp.id, qty: it.qty || 1 }); else missing.push(it.name);
              });
              if (found.length === 0) {
                alert('Taslaktaki ürünler katalogda bulunamadı.');
                return;
              }
              if (window.__cart && typeof window.__cart.add === 'function') {
                found.forEach((f) => window.__cart.add(f.pid, f.qty));
              }
              // Taslak sepete yüklendi; aynı taslak listede kalmasın
              if (window.__requests && typeof window.__requests.remove === 'function') {
                window.__requests.remove(req.id);
              }
              const msg = `${found.length} ürün sepete yüklendi.` + (missing.length ? `\n\nKatalogdan eşleşmeyen: ${missing.join(', ')}` : '');
              alert(msg);
              if (typeof window.__navigate === 'function') window.__navigate('cart');
              return;
            }
            onOpen();
          }}
          style={{
          appearance: 'none', cursor: 'pointer',
          padding: '10px 16px', borderRadius: 10,
          background: hover ? c.primary : 'transparent',
          color: hover ? '#fff' : c.text,
          border: `1px solid ${hover ? c.primary : c.border}`,
          fontSize: 13, fontWeight: 500, fontFamily: 'inherit',
          transition: 'all 160ms',
          display: 'inline-flex', alignItems: 'center', gap: 6,
        }}>
          {req.status === 'draft' ? 'Düzenle' : 'Detayları Gör'}
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M9 18l6-6-6-6" />
          </svg>
        </button>
      </div>
    </div>
  );
}

// ─────────── List filter bar ───────────
function ListFilterBar({ c, statusFilter, setStatusFilter, search, setSearch, requests }) {
  const all = requests || [];
  const tabs = [
    { v: 'all', label: 'Tümü', count: all.length },
    { v: 'pending',   label: 'Onay Bekliyor', count: all.filter((r) => r.status === 'pending').length },
    { v: 'approved',  label: 'Onaylandı',     count: 0 },
    { v: 'rejected',  label: 'Reddedildi',    count: all.filter((r) => r.status === 'rejected').length },
    { v: 'completed', label: 'Tamamlandı',    count: all.filter((r) => r.status === 'completed').length },
    { v: 'draft',     label: 'Taslak',        count: all.filter((r) => r.status === 'draft').length },
  ];
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
        {tabs.map((t) => {
          const active = statusFilter === t.v;
          return (
            <button key={t.v} onClick={() => setStatusFilter(t.v)} style={{
              appearance: 'none', cursor: 'pointer',
              padding: '8px 14px', borderRadius: 999,
              background: active ? c.primary : c.surface,
              color: active ? '#fff' : c.text,
              border: `1px solid ${active ? c.primary : c.border}`,
              fontSize: 12.5, fontWeight: 500, fontFamily: 'inherit',
              display: 'inline-flex', alignItems: 'center', gap: 7,
              transition: 'all 120ms',
            }}>
              {t.label}
              {t.count > 0 && (
                <span style={{
                  fontSize: 10.5, fontWeight: 600,
                  padding: '1px 6px', borderRadius: 999,
                  background: active ? 'rgba(255,255,255,0.22)' : c.chipBg,
                  color: active ? '#fff' : c.muted,
                  minWidth: 18, textAlign: 'center',
                }}>{t.count}</span>
              )}
            </button>
          );
        })}
      </div>

      <div style={{
        marginTop: 14, display: 'flex', alignItems: 'center', gap: 10,
      }}>
        {/* Search */}
        <div style={{ flex: 1, maxWidth: 420, position: 'relative' }}>
          <span style={{
            position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)',
            color: c.muted, display: 'flex', pointerEvents: 'none',
          }}>{UIIcons.search}</span>
          <input
            type="text"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="Talep numarası veya ürün adı ile ara..."
            style={{
              width: '100%', boxSizing: 'border-box',
              padding: '9px 14px 9px 38px',
              background: c.inputBg, color: c.text,
              border: `1px solid ${c.border}`, borderRadius: 10,
              fontSize: 13, fontFamily: 'inherit', outline: 'none',
            }}
          />
        </div>

        {/* Date range */}
        <button
          onClick={() => alert('Tarih aralığı filtresi prototipte henüz aktif değil.\n\nGerçek uygulamada burada özel tarih aralığı seçilebilecek.')}
          style={{
          appearance: 'none', cursor: 'pointer',
          padding: '9px 14px', borderRadius: 10,
          background: c.surface, color: c.text,
          border: `1px solid ${c.border}`,
          fontSize: 12.5, fontWeight: 500, fontFamily: 'inherit',
          display: 'inline-flex', alignItems: 'center', gap: 8,
        }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
            <rect x="3" y="4" width="18" height="18" rx="2" /><path d="M16 2v4M8 2v4M3 10h18" />
          </svg>
          Son 60 gün
          <span style={{ display: 'flex', color: c.muted }}>{UIIcons.chevDown}</span>
        </button>
      </div>
    </div>
  );
}

// ─────────── List view ───────────
function RequestsListView({ c, onOpen, requests }) {
  const [statusFilter, setStatusFilter] = React.useState('all');
  const [search, setSearch] = React.useState('');

  const filtered = (requests || []).filter((r) => {
    if (statusFilter !== 'all' && r.status !== statusFilter) return false;
    if (search.trim()) {
      const q = search.trim().toLowerCase();
      if (!r.id.toLowerCase().includes(q) &&
          !r.items.some((it) => it.name.toLowerCase().includes(q))) return false;
    }
    return true;
  });

  return (
    <div>
      <div style={{ marginBottom: 10 }}>
        <h1 style={{ margin: 0, fontSize: 26, fontWeight: 600, letterSpacing: '-0.015em', color: c.text }}>
          Taleplerim
        </h1>
        <p style={{ margin: '6px 0 0', fontSize: 13, color: c.muted }}>
          Aktif ve geçmiş tüm IT taleplerinizi buradan takip edin.
        </p>
      </div>

      <div style={{ marginTop: 20 }}>
        <ListFilterBar c={c} statusFilter={statusFilter} setStatusFilter={setStatusFilter} search={search} setSearch={setSearch} requests={requests} />
      </div>

      <div style={{ marginTop: 22, display: 'flex', flexDirection: 'column', gap: 12 }}>
        {filtered.length === 0 ? (
          <div style={{
            padding: 36, textAlign: 'center',
            background: c.surface, border: `1px dashed ${c.border}`, borderRadius: 14,
            color: c.muted, fontSize: 13,
          }}>Bu filtreye uygun talep bulunamadı.</div>
        ) : (
          filtered.map((r) => (
            <RequestRow key={r.id} req={r} c={c} onOpen={() => onOpen(r.id)} />
          ))
        )}
      </div>
    </div>
  );
}

// ─────────── Detail view ───────────
function RequestDetailView({ req, c, onBack }) {
  if (!req) return null;
  const removedItems = req.items ? req.items.filter((x) => x.state === 'removed') : [];
  const keptItems = req.items ? req.items.filter((x) => x.state !== 'removed') : (req.items || []);
  const status = REQUEST_STATUSES[req.status];

  return (
    <div>
      {/* Back + header */}
      <button onClick={onBack} style={{
        appearance: 'none', cursor: 'pointer',
        background: 'transparent', border: 'none', padding: 0,
        color: c.muted, fontSize: 12.5, fontFamily: 'inherit', fontWeight: 500,
        display: 'inline-flex', alignItems: 'center', gap: 6,
        marginBottom: 14,
      }}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
          <path d="M15 18l-6-6 6-6" />
        </svg>
        Taleplerime dön
      </button>

      <div style={{
        display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between',
        gap: 20, flexWrap: 'wrap', marginBottom: 6,
      }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
            <h1 style={{
              margin: 0, fontSize: 24, fontWeight: 700,
              fontFamily: 'ui-monospace, "SF Mono", Menlo, monospace',
              letterSpacing: '0.01em', color: c.text,
            }}>{req.id}</h1>
            <StatusBadge status={req.status} c={c} />
            {req.kind === 'custom' && (
              <span style={{
                display: 'inline-flex', alignItems: 'center', gap: 5,
                padding: '4px 10px', borderRadius: 999,
                background: 'rgba(245,158,11,0.12)', color: '#B45309',
                fontSize: 11.5, fontWeight: 600,
                border: '1px solid rgba(245,158,11,0.30)',
              }}>
                <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M12 2l2.39 4.84L19.8 7.6l-3.9 3.8.92 5.37L12 14.27l-4.82 2.5.92-5.37L4.2 7.6l5.41-.76L12 2z" />
                </svg>
                Özel Talep
              </span>
            )}
          </div>
          <div style={{ marginTop: 6, fontSize: 13, color: c.muted }}>
            {req.submittedAt ? `Gönderildi: ${req.submittedAt}` : `Oluşturuldu: ${req.date}`}
            {req.status === 'pending' && (
              <React.Fragment>
                {' · '}<strong style={{ color: c.text, fontWeight: 600 }}>{REQUEST_STEPS[req.currentStep]}</strong> aşamasında
              </React.Fragment>
            )}
          </div>
        </div>

        <div style={{ display: 'flex', gap: 10 }}>
          {req.status === 'pending' && req.currentStep === 0 && (
            <button
              onClick={() => {
                if (confirm(`${req.id} numaralı talebi iptal etmek istediğinize emin misiniz?\n\nBu işlem geri alınamaz.`)) {
                  alert('Talep iptal edildi.\n\n(Prototip: gerçek bir değişiklik yapılmaz, demo veriler korunur.)');
                }
              }}
              style={cancelBtn(c)}>Talebi İptal Et</button>
          )}
          <button
            onClick={() => alert(`${req.id} için PDF indirme prototipte henüz aktif değil.\n\nGerçek uygulamada bu butonla talep özeti PDF olarak indirilebilecek.`)}
            style={primaryGhost(c)}>PDF İndir</button>
        </div>
      </div>

      {/* Rejection banner */}
      {req.status === 'rejected' && (
        <div style={{
          marginTop: 14,
          padding: 14,
          background: 'rgba(239,68,68,0.08)',
          border: `1px solid ${c.danger}33`,
          borderRadius: 12,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, color: c.danger, fontSize: 13, fontWeight: 600, marginBottom: 4 }}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <circle cx="12" cy="12" r="9" /><path d="M15 9l-6 6M9 9l6 6" />
            </svg>
            {REQUEST_STEPS[req.rejectedAt]} aşamasında reddedildi
          </div>
          <div style={{ fontSize: 13, color: c.text, lineHeight: 1.55 }}>{req.rejectionReason}</div>
        </div>
      )}

      {/* Main grid: timeline + items */}
      <div style={{
        marginTop: 22,
        display: 'grid', gridTemplateColumns: '380px 1fr', gap: 28,
        alignItems: 'flex-start',
      }}>
        {/* Timeline */}
        <div style={{
          background: c.card, border: `1px solid ${c.border}`, borderRadius: 14,
          padding: 22,
        }}>
          <h3 style={{ margin: 0, fontSize: 14, fontWeight: 600, color: c.text, marginBottom: 18 }}>
            Onay zaman çizelgesi
          </h3>
          <Timeline events={req.timeline || []} c={c} />
        </div>

        {/* Items */}
        <div>
          <h3 style={{ margin: 0, fontSize: 14, fontWeight: 600, color: c.text, marginBottom: 12 }}>
            Talep edilen ürünler <span style={{ color: c.muted, fontWeight: 500 }}>· {keptItems.length} kalem</span>
          </h3>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {keptItems.map((it) => (
              <DetailItemCard key={it.id} item={it} c={c} />
            ))}
          </div>

          {removedItems.length > 0 && (
            <div style={{ marginTop: 22 }}>
              <h3 style={{
                margin: 0, fontSize: 13, fontWeight: 600, color: c.danger,
                marginBottom: 10, display: 'flex', alignItems: 'center', gap: 6,
              }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <circle cx="12" cy="12" r="9" /><path d="M8 12h8" />
                </svg>
                Yönetici tarafından çıkarılan ürünler · {removedItems.length} kalem
              </h3>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                {removedItems.map((it) => (
                  <DetailItemCard key={it.id} item={it} c={c} removed />
                ))}
              </div>
            </div>
          )}

          {/* Totals */}
          <div style={{
            marginTop: 18, padding: 16,
            background: c.card, border: `1px solid ${c.border}`, borderRadius: 12,
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          }}>
            <div>
              <div style={{ fontSize: 12, color: c.muted }}>Talep tutarı (KDV hariç)</div>
              {req.originalSubtotal && (
                <div style={{ fontSize: 11.5, color: c.subtle, marginTop: 2, textDecoration: 'line-through' }}>
                  Orijinal: {formatTL(req.originalSubtotal)}
                </div>
              )}
            </div>
            <div style={{ fontSize: 22, fontWeight: 700, color: c.text, letterSpacing: '-0.015em' }}>
              {formatTL(req.netSubtotal)}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function cancelBtn(c) {
  return {
    appearance: 'none', cursor: 'pointer',
    padding: '9px 14px', borderRadius: 10,
    background: 'transparent', color: c.danger,
    border: `1px solid ${c.danger}55`,
    fontSize: 12.5, fontWeight: 600, fontFamily: 'inherit',
  };
}
function primaryGhost(c) {
  return {
    appearance: 'none', cursor: 'pointer',
    padding: '9px 14px', borderRadius: 10,
    background: 'transparent', color: c.text,
    border: `1px solid ${c.border}`,
    fontSize: 12.5, fontWeight: 500, fontFamily: 'inherit',
  };
}

// ─────────── Timeline ───────────
function Timeline({ events, c }) {
  return (
    <ol style={{ listStyle: 'none', margin: 0, padding: 0, position: 'relative' }}>
      {/* connecting line */}
      <div style={{
        position: 'absolute', left: 11, top: 8, bottom: 8,
        width: 2, background: c.borderSoft,
      }} />
      {events.map((e, i) => (
        <TimelineEvent key={i} event={e} c={c} isLast={i === events.length - 1} />
      ))}
    </ol>
  );
}

function TimelineEvent({ event, c }) {
  const styles = {
    submitted: { bg: c.selectedBg,    color: c.selectedText, icon: 'send' },
    approved:  { bg: 'rgba(16,185,129,0.14)', color: c.success, icon: 'check' },
    removed:   { bg: 'rgba(245,158,11,0.14)', color: '#B45309', icon: 'minus' },
    pending:   { bg: 'rgba(245,158,11,0.14)', color: '#B45309', icon: 'clock' },
    queued:    { bg: c.borderSoft,    color: c.muted,        icon: 'dot' },
    rejected:  { bg: 'rgba(239,68,68,0.14)',  color: c.danger,  icon: 'x' },
  }[event.kind] || { bg: c.borderSoft, color: c.muted, icon: 'dot' };

  const isPending = event.kind === 'pending';
  const isQueued = event.kind === 'queued';

  return (
    <li style={{
      position: 'relative', paddingLeft: 36, paddingBottom: 18,
      opacity: isQueued ? 0.55 : 1,
    }}>
      <div style={{
        position: 'absolute', left: 0, top: 0,
        width: 24, height: 24, borderRadius: 999,
        background: styles.bg, color: styles.color,
        border: `2px solid ${c.bg}`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        zIndex: 1,
        boxShadow: isPending ? `0 0 0 4px ${styles.color}22` : 'none',
        animation: isPending ? 'pulseDot 1.6s ease-in-out infinite' : 'none',
      }}>
        <TimelineIcon name={styles.icon} />
      </div>
      <div>
        <div style={{ fontSize: 12.5, fontWeight: 600, color: c.text }}>
          {event.kind === 'submitted' && 'Talep oluşturuldu'}
          {event.kind === 'approved' && `${event.actor} tarafından onaylandı`}
          {event.kind === 'removed' && `${event.actor} ürün çıkardı`}
          {event.kind === 'pending' && `${event.actor} onayı bekleniyor`}
          {event.kind === 'queued' && `${event.actor}`}
          {event.kind === 'rejected' && `${event.actor} reddetti`}
        </div>
        <div style={{ fontSize: 11.5, color: c.muted, marginTop: 2 }}>
          {event.role && <span>{event.role} · </span>}
          {event.time || 'Henüz başlamadı'}
        </div>
        {event.note && (
          <div style={{
            marginTop: 8,
            padding: '8px 10px',
            background: c.borderSoft,
            border: `1px solid ${c.border}`,
            borderRadius: 8,
            fontSize: 12, lineHeight: 1.55, color: c.text,
            fontStyle: 'italic',
          }}>
            "{event.note}"
          </div>
        )}
      </div>
    </li>
  );
}

function TimelineIcon({ name }) {
  const props = { width: 12, height: 12, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2.4, strokeLinecap: 'round', strokeLinejoin: 'round' };
  if (name === 'check') return <svg {...props}><path d="M20 6L9 17l-5-5" /></svg>;
  if (name === 'x')     return <svg {...props}><path d="M18 6L6 18M6 6l12 12" /></svg>;
  if (name === 'clock') return <svg {...props}><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></svg>;
  if (name === 'send')  return <svg {...props}><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z" /></svg>;
  if (name === 'minus') return <svg {...props}><path d="M5 12h14" /></svg>;
  return <svg {...props}><circle cx="12" cy="12" r="4" /></svg>;
}

// ─────────── Detail item card ───────────
function DetailItemCard({ item, c, removed }) {
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: '72px 1fr 120px', gap: 16,
      alignItems: 'flex-start',
      background: c.card,
      border: `1px solid ${removed ? c.danger + '44' : c.border}`,
      borderRadius: 12, padding: 14,
      position: 'relative',
      overflow: 'hidden',
    }}>
      {/* Removed strikethrough overlay accent */}
      {removed && (
        <div style={{
          position: 'absolute', left: 0, top: 0, bottom: 0, width: 3,
          background: c.danger,
        }} />
      )}
      <div style={{ width: 72, height: 72, borderRadius: 8, overflow: 'hidden', border: `1px solid ${c.border}` }}>
        <ProductPlaceholder kind={item.imgKind} c={c} imgSrc={requestItemImgSrc(item)} />
      </div>
      <div style={{ minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
          {(item.brand || item.model) ? (
            <span style={{
              fontSize: 10, fontWeight: 600, letterSpacing: '0.06em',
              color: c.muted, background: c.chipBg, padding: '2px 6px',
              borderRadius: 4, textTransform: 'uppercase',
            }}>{[item.brand, item.model].filter(Boolean).join(' · ')}</span>
          ) : (
            <span style={{
              fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
              color: '#B45309', background: 'rgba(245,158,11,0.12)',
              padding: '2px 6px', borderRadius: 4, textTransform: 'uppercase',
              border: '1px solid rgba(245,158,11,0.30)',
            }}>Katalog dışı</span>
          )}
          {removed && (
            <span style={{
              fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
              color: c.danger, background: 'rgba(239,68,68,0.12)',
              padding: '2px 6px', borderRadius: 4, textTransform: 'uppercase',
            }}>Çıkarıldı</span>
          )}
        </div>
        <div style={{
          fontSize: 13.5, fontWeight: 600, color: c.text, marginTop: 5,
          textDecoration: removed ? 'line-through' : 'none',
          textDecorationColor: removed ? c.danger : 'inherit',
          textDecorationThickness: removed ? 1 : 'auto',
        }}>{item.name}</div>
        <div style={{
          marginTop: 8, padding: '8px 10px',
          background: c.borderSoft, border: `1px solid ${c.border}`, borderRadius: 8,
          fontSize: 12, lineHeight: 1.55, color: c.text, fontStyle: 'italic',
        }}>"{item.justification}"</div>

        {(item.link || item.budget) && (
          <div style={{ marginTop: 8, display: 'flex', gap: 14, flexWrap: 'wrap', fontSize: 12, color: c.muted }}>
            {item.link && (
              <a href={item.link} target="_blank" rel="noopener noreferrer" style={{
                display: 'inline-flex', alignItems: 'center', gap: 5,
                color: c.primary, textDecoration: 'none', fontWeight: 500,
              }}>
                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
                  <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
                </svg>
                Referans linki
              </a>
            )}
            {item.budget && (
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}>
                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M12 1v22M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" />
                </svg>
                Tahmini bütçe: <strong style={{ color: c.text, fontWeight: 600 }}>{item.budget}</strong>
              </span>
            )}
          </div>
        )}

        {removed && item.removalReason && (
          <div style={{
            marginTop: 8, padding: '10px 12px',
            background: 'rgba(239,68,68,0.06)',
            border: `1px solid ${c.danger}33`, borderRadius: 8,
            fontSize: 12, lineHeight: 1.55, color: c.text,
          }}>
            <div style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: '0.06em', color: c.danger, marginBottom: 4, textTransform: 'uppercase' }}>
              Yönetici notu
            </div>
            {item.removalReason}
          </div>
        )}
      </div>
      <div style={{ textAlign: 'right' }}>
        <div style={{ fontSize: 11, color: c.muted, marginBottom: 2 }}>{item.qty} adet</div>
        <div style={{
          fontSize: 15, fontWeight: 700,
          color: removed ? c.subtle : c.text,
          textDecoration: removed ? 'line-through' : 'none',
        }}>{formatTL((item.priceNet || 0) * (item.qty || 1))}</div>
        {item.priceUnit && (
          <div style={{ fontSize: 10.5, color: c.subtle, marginTop: 2 }}>/ {item.priceUnit}</div>
        )}
      </div>
    </div>
  );
}

// ─────────── MAIN PAGE ───────────
function RequestsPage({ initialDark = false, initialDetailId = null }) {
  const [dark, setDark] = React.useState(initialDark);
  React.useEffect(() => { setDark(initialDark); }, [initialDark]);

  const [selectedId, setSelectedId] = React.useState(initialDetailId);
  const [headerSearch, setHeaderSearch] = React.useState('');

  const c = catalogTheme(dark);
  const requests = useRequestsSnapshot();
  const selected = requests.find((r) => r.id === selectedId);

  return (
    <div style={{
      width: '100%', height: '100%',
      background: c.bg, color: c.text,
      fontFamily: 'Inter, system-ui, sans-serif',
      display: 'flex', flexDirection: 'column',
      position: 'relative',
    }}>
      <CatalogHeader
        c={c} dark={dark}
        onToggleDark={() => setDark((x) => !x)}
        search={headerSearch} setSearch={setHeaderSearch}
        cartCount={0}
        notifCount={3}
      />

      <div style={{ padding: '28px 32px 40px' }}>
        {selected
          ? <RequestDetailView req={selected} c={c} onBack={() => setSelectedId(null)} />
          : <RequestsListView c={c} onOpen={(id) => setSelectedId(id)} requests={requests} />}
      </div>

      <style>{`
        @keyframes pulseDot {
          0%, 100% { opacity: 1; transform: scale(1); }
          50%      { opacity: 0.55; transform: scale(0.92); }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, {
  RequestsPage, REQUESTS, REQUEST_STATUSES, REQUEST_STEPS,
  StatusBadge, MiniProgress, RequestRow, ListFilterBar,
  RequestsListView, RequestDetailView, Timeline, TimelineEvent, DetailItemCard,
});
