// tickets.jsx — Platform complaint / escalation ticket system
console.log('[tickets.jsx] v5 loaded ✓');

/* ── inject styles ─────────────────────────────────────────── */
(() => {
  if (document.getElementById('tickets-css')) return;
  const s = document.createElement('style');
  s.id = 'tickets-css';
  s.textContent = `
/* ── overlay ── */
.tk-overlay {
  position: fixed; inset: 0; z-index: 1100;
  background: var(--bg,#f7f7f7);
  display: flex; flex-direction: column;
  font-family: 'IBM Plex Sans Thai', sans-serif;
}
/* ── header ── */
.tk-header {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 18px; border-bottom: 1px solid var(--line,#e5e5e5);
  background: #fff; flex-shrink: 0;
}
.tk-header-info { flex: 1; min-width: 0; }
.tk-header-title { font-size: 15px; font-weight: 700; }
.tk-header-sub   { font-size: 11px; color: var(--ink-3,#aaa); margin-top: 1px; }
.tk-icon-btn {
  display: flex; align-items: center; gap: 5px;
  padding: 6px 12px; border-radius: 7px; font-size: 13px; font-weight: 500;
  border: 1px solid var(--line,#e0e0e0); background: none; cursor: pointer;
  color: var(--ink-2,#555); white-space: nowrap; transition: background .12s;
}
.tk-icon-btn:hover { background: var(--bg,#f5f5f5); }
.tk-primary-btn {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: 7px; font-size: 13px; font-weight: 500;
  border: none; background: var(--accent,#2A6FDB); color: #fff; cursor: pointer;
  white-space: nowrap; transition: opacity .12s;
}
.tk-primary-btn:hover { opacity: .9; }
.tk-close-btn {
  width: 30px; height: 30px; border-radius: 7px; border: 1px solid var(--line,#e0e0e0);
  background: none; cursor: pointer; font-size: 19px; color: var(--ink-2,#666);
  display: flex; align-items: center; justify-content: center; transition: background .12s;
}
.tk-close-btn:hover { background: var(--bg,#f5f5f5); }
/* ── body layout ── */
.tk-body { flex: 1; overflow: hidden; display: flex; min-height: 0; }
.tk-sidebar {
  width: 360px; min-width: 260px; flex-shrink: 0;
  border-right: 1px solid var(--line,#e5e5e5);
  display: flex; flex-direction: column; background: #fff; overflow: hidden;
}
.tk-main { flex: 1; overflow-y: auto; background: var(--bg,#f7f7f7); }
/* ── sidebar filters ── */
.tk-tabs {
  display: flex; gap: 3px; padding: 10px 10px 0; flex-wrap: wrap; flex-shrink: 0;
}
.tk-tab {
  padding: 4px 10px; border-radius: 20px; font-size: 12px; font-weight: 500;
  border: 1px solid transparent; background: none; cursor: pointer;
  color: var(--ink-2,#666); transition: all .13s; display: flex; align-items: center; gap: 3px;
}
.tk-tab.active { background: var(--accent,#2A6FDB); color: #fff; }
.tk-tab:not(.active):hover { background: var(--bg,#f0f0f0); }
.tk-tab-count {
  font-size: 10px; background: rgba(0,0,0,0.08); padding: 0 4px;
  border-radius: 8px; font-weight: 600;
}
.tk-tab.active .tk-tab-count { background: rgba(255,255,255,0.25); }
.tk-pchips { display: flex; gap: 4px; padding: 6px 10px; flex-shrink: 0; flex-wrap: wrap; }
.tk-pchip {
  display: flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 20px; font-size: 11px; font-weight: 500;
  border: 1px solid; background: none; cursor: pointer; opacity: .4; transition: opacity .13s;
}
.tk-pchip.active { opacity: 1; }
/* ── ticket list ── */
.tk-list { flex: 1; overflow-y: auto; padding: 6px 8px; }
.tk-list-empty {
  padding: 40px 16px; text-align: center; color: var(--ink-3,#aaa); font-size: 13px; line-height: 1.6;
}
/* ── ticket card ── */
.tk-card {
  border: 1px solid var(--line,#e8e8e8); border-left: 3px solid;
  border-radius: 9px; padding: 11px 13px; margin-bottom: 5px;
  cursor: pointer; background: #fff; transition: box-shadow .13s, border-color .13s;
}
.tk-card:hover { box-shadow: 0 2px 6px rgba(0,0,0,.07); }
.tk-card.selected { border-color: var(--accent,#2A6FDB) !important; box-shadow: 0 0 0 1px var(--accent,#2A6FDB)22; }
.tk-card-top { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }
.tk-card-title { flex: 1; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tk-card-cat { font-size: 11px; color: var(--ink-3,#999); margin-bottom: 5px; }
.tk-card-meta { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--ink-3,#999); flex-wrap: wrap; }
/* ── badges ── */
.tk-status-badge {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 2px 7px; border-radius: 20px; font-size: 11px; font-weight: 500; white-space: nowrap;
}
.tk-status-open        { background: oklch(.96 .04 55);  color: oklch(.50 .18 50);  }
.tk-status-in_progress { background: oklch(.95 .04 245); color: oklch(.42 .16 245); }
.tk-status-waiting     { background: oklch(.95 .03 285); color: oklch(.44 .14 285); }
.tk-status-resolved    { background: oklch(.95 .04 155); color: oklch(.40 .14 155); }
.tk-pri-badge {
  display: inline-flex; align-items: center;
  padding: 1px 6px; border-radius: 4px; font-size: 10px; font-weight: 700;
}
/* ── detail ── */
.tk-detail { padding: 22px 26px; max-width: 740px; }
.tk-detail-title { font-size: 20px; font-weight: 700; line-height: 1.3; margin-bottom: 12px; }
.tk-detail-meta {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px solid var(--line,#eee);
}
.tk-status-sel {
  padding: 4px 10px; border-radius: 7px; font-size: 12px; font-weight: 600;
  border: 1.5px solid currentColor; cursor: pointer; background: none; outline: none;
}
.tk-detail-actions { display: flex; gap: 6px; margin-left: auto; }
.tk-edit-btn {
  padding: 5px 11px; border-radius: 6px; border: 1px solid var(--line,#e0e0e0);
  background: none; cursor: pointer; font-size: 12px; color: var(--ink-2,#555);
  display: flex; align-items: center; gap: 4px;
}
.tk-edit-btn:hover { background: var(--bg,#f5f5f5); }
.tk-del-btn {
  padding: 5px 11px; border-radius: 6px; font-size: 12px; cursor: pointer;
  border: 1px solid oklch(.80 .08 18); background: none; color: oklch(.52 .22 18);
  display: flex; align-items: center; gap: 4px;
}
.tk-del-btn:hover { background: oklch(.97 .02 18); }
.tk-del-confirm {
  padding: 5px 11px; border-radius: 6px; font-size: 12px; cursor: pointer;
  border: none; background: oklch(.52 .22 18); color: #fff;
}
/* ── detail sections ── */
.tk-section { margin-bottom: 20px; }
.tk-section-label {
  font-size: 11px; font-weight: 700; color: var(--ink-3,#aaa);
  text-transform: uppercase; letter-spacing: .05em; margin-bottom: 7px;
}
.tk-desc-text {
  font-size: 14px; line-height: 1.65; color: var(--ink-1,#333);
  white-space: pre-wrap; word-break: break-word;
}
.tk-meta-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: 6px; font-size: 12px;
  background: var(--bg,#f0f0f0); color: var(--ink-2,#555);
}
.tk-order-chip {
  font-family: 'JetBrains Mono', monospace; font-size: 12px;
  padding: 3px 9px; background: var(--bg,#f0f0f0); border-radius: 6px;
  display: inline-flex; align-items: center; gap: 4px;
}
/* ── image grid ── */
.tk-img-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.tk-img-wrap { position: relative; }
.tk-img-thumb {
  width: 82px; height: 82px; object-fit: cover; border-radius: 7px;
  cursor: pointer; border: 1px solid var(--line,#e0e0e0);
  transition: transform .13s;
}
.tk-img-thumb:hover { transform: scale(1.04); }
.tk-img-del {
  position: absolute; top: -5px; right: -5px;
  width: 18px; height: 18px; border-radius: 50%; font-size: 11px;
  background: rgba(0,0,0,.65); color: #fff; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.tk-img-add-btn {
  width: 82px; height: 82px; border-radius: 7px;
  border: 1.5px dashed var(--line,#ccc); background: none; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; font-size: 11px; color: var(--ink-3,#aaa); transition: all .13s;
}
.tk-img-add-btn:hover { border-color: var(--accent,#2A6FDB); color: var(--accent,#2A6FDB); }
/* ── comments ── */
.tk-comments { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.tk-comment { display: flex; gap: 10px; }
.tk-comment-avatar {
  width: 28px; height: 28px; border-radius: 50%; background: var(--bg,#ebebeb);
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  font-size: 13px;
}
.tk-comment-body { flex: 1; }
.tk-comment-text {
  font-size: 13px; line-height: 1.55; padding: 8px 12px;
  background: #fff; border: 1px solid var(--line,#e5e5e5);
  border-radius: 4px 10px 10px 10px; white-space: pre-wrap; word-break: break-word;
}
.tk-comment-time { font-size: 11px; color: var(--ink-3,#aaa); margin-top: 3px; padding-left: 3px; }
.tk-add-comment { display: flex; gap: 8px; align-items: flex-end; }
.tk-comment-ta {
  flex: 1; padding: 8px 12px; border: 1px solid var(--line,#ddd);
  border-radius: 9px; font-size: 13px; resize: none; min-height: 56px;
  font-family: 'IBM Plex Sans Thai', sans-serif; outline: none; transition: border .13s;
}
.tk-comment-ta:focus { border-color: var(--accent,#2A6FDB); }
.tk-send-btn {
  padding: 9px 16px; border-radius: 9px; border: none;
  background: var(--accent,#2A6FDB); color: #fff; font-size: 13px; cursor: pointer;
}
.tk-send-btn:disabled { opacity: .35; cursor: default; }
/* ── form ── */
.tk-form-wrap { padding: 22px 26px; max-width: 640px; }
.tk-form-heading { font-size: 17px; font-weight: 700; margin-bottom: 18px; }
.tk-field { margin-bottom: 14px; }
.tk-label { display: block; font-size: 12px; font-weight: 600; color: var(--ink-2,#555); margin-bottom: 5px; }
.tk-input, .tk-textarea, .tk-select {
  width: 100%; padding: 9px 12px; border: 1px solid var(--line,#ddd);
  border-radius: 8px; font-size: 14px; font-family: 'IBM Plex Sans Thai', sans-serif;
  background: #fff; box-sizing: border-box; outline: none; color: var(--ink-1,#333);
  transition: border .13s;
}
.tk-input:focus, .tk-textarea:focus, .tk-select:focus { border-color: var(--accent,#2A6FDB); }
.tk-textarea { resize: vertical; min-height: 96px; }
.tk-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.tk-form-footer {
  display: flex; gap: 8px; justify-content: flex-end; margin-top: 18px;
  padding-top: 14px; border-top: 1px solid var(--line,#eee);
}
/* ── lightbox ── */
.tk-lightbox {
  position: fixed; inset: 0; background: rgba(0,0,0,.88);
  display: flex; align-items: center; justify-content: center; z-index: 9999; cursor: pointer;
}
.tk-lightbox img { max-width: 92vw; max-height: 90vh; border-radius: 5px; cursor: default; }
.tk-lightbox-x {
  position: absolute; top: 14px; right: 18px;
  width: 36px; height: 36px; border-radius: 50%; border: none;
  background: rgba(255,255,255,.15); color: #fff; font-size: 22px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
/* ── no-selection placeholder ── */
.tk-placeholder {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 100%; padding: 40px; text-align: center; color: var(--ink-3,#bbb);
}
.tk-placeholder svg { opacity: .18; margin-bottom: 14px; }
.tk-placeholder p { font-size: 14px; }
/* ── responsive: mobile ── */
@media (max-width: 640px) {
  .tk-sidebar { width: 100%; border-right: none; flex-shrink: 0; }
  .tk-main { display: none; width: 100%; }
  .tk-body.show-detail .tk-sidebar { display: none; }
  .tk-body.show-detail .tk-main   { display: flex; flex-direction: column; }
  .tk-mob-back { display: flex !important; }
  .tk-detail, .tk-form-wrap { padding: 16px; }
  .tk-row2 { grid-template-columns: 1fr; }
}
.tk-mob-back { display: none; }
`;
  document.head.appendChild(s);
})();

/* ── shared React hooks ──────────────────────────────────────── */
const { useState, useEffect, useCallback, useRef, useMemo } = React;

/* ── constants ───────────────────────────────────────────────── */
const TK_STATUSES = {
  open:        { id: 'open',        label: 'เปิดคำร้อง',     dot: 'oklch(.52 .22 50)'  },
  in_progress: { id: 'in_progress', label: 'กำลังดำเนินการ', dot: 'oklch(.48 .16 245)' },
  waiting:     { id: 'waiting',     label: 'รอ Platform ตอบ',dot: 'oklch(.46 .14 285)' },
  resolved:    { id: 'resolved',    label: 'แก้ไขแล้ว',      dot: 'oklch(.44 .14 155)' },
};
const TK_STATUS_LIST = ['open','in_progress','waiting','resolved'];

const TK_PRIORITIES = {
  low:    { id: 'low',    label: 'ต่ำ',   color: '#9ca3af' },
  normal: { id: 'normal', label: 'ปกติ',  color: '#3b82f6' },
  high:   { id: 'high',   label: 'สูง',   color: '#f59e0b' },
  urgent: { id: 'urgent', label: 'ด่วน!', color: '#ef4444' },
};
const TK_PRIORITY_LIST = ['low','normal','high','urgent'];

const TK_CATEGORIES = [
  'ของหาย / สินค้าไม่ครบ',
  'ของเสียหาย',
  'ยกเลิกคำสั่งซื้อ',
  'ลูกค้าร้องเรียน',
  'ปัญหาการชำระเงิน',
  'ปัญหาระบบ Platform',
  'ส่งผิดที่อยู่',
  'อื่นๆ',
];

/* ── localStorage helpers ────────────────────────────────────── */
const LS_KEY = 'tickets_v1';
function lsLoad()       { try { return JSON.parse(localStorage.getItem(LS_KEY) || '[]'); } catch { return []; } }
function lsSave(t)      { const a = lsLoad(); const i = a.findIndex(x => x.id === t.id); if (i >= 0) a[i] = t; else a.unshift(t); localStorage.setItem(LS_KEY, JSON.stringify(a)); }
function lsDel(id)      { localStorage.setItem(LS_KEY, JSON.stringify(lsLoad().filter(t => t.id !== id))); }

/* ── Supabase data layer ─────────────────────────────────────── */
async function tkFetch() {
  if (!window.DB_READY) return lsLoad();
  try {
    const { data, error } = await window.db.from('tickets').select('data').order('created_at', { ascending: false });
    if (error) throw error;
    const remote = (data || []).map(r => r.data).filter(Boolean);
    // merge: remote lacks images (too large), fill from localStorage
    const local = lsLoad();
    const localMap = Object.fromEntries(local.map(t => [t.id, t]));
    return remote.map(r => localMap[r.id] ? { ...r, images: localMap[r.id].images || [] } : r);
  } catch (e) {
    console.warn('[Tickets] fetch failed, localStorage fallback:', e.message);
    return lsLoad();
  }
}

async function tkSync(ticket) {
  lsSave(ticket);
  if (!window.DB_READY) return;
  try {
    // Strip images before sending to Supabase (base64 too large)
    const slim = { ...ticket, images: [] };
    await window.db.from('tickets').upsert({
      id: ticket.id, platform: ticket.platform,
      status: ticket.status, priority: ticket.priority,
      created_at: ticket.created, data: slim,
    });
  } catch (e) { console.warn('[Tickets] sync failed:', e.message); }
}

async function tkDelete(id) {
  lsDel(id);
  if (!window.DB_READY) return;
  try { await window.db.from('tickets').delete().eq('id', id); } catch (e) { console.warn('[Tickets] delete failed:', e.message); }
}

/* ── utilities ───────────────────────────────────────────────── */
function tkId()  { return 'tk-' + Date.now().toString(36) + Math.random().toString(36).slice(2,6); }
function cId()   { return 'c-'  + Math.random().toString(36).slice(2,9); }

function fmtTs(s) {
  if (!s) return '';
  const d = new Date(s);
  const M = ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.','ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'];
  return `${d.getDate()} ${M[d.getMonth()]} ${(d.getFullYear()+543).toString().slice(-2)} ${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}`;
}
function relTs(s) {
  const m = Math.round((Date.now() - new Date(s)) / 60000);
  if (m < 1) return 'เมื่อกี้';
  if (m < 60) return `${m} นาที`;
  if (m < 1440) return `${Math.round(m/60)} ชม.`;
  return `${Math.round(m/1440)} วัน`;
}

async function compressImg(file) {
  return new Promise((res, rej) => {
    const r = new FileReader();
    r.onload = e => {
      const img = new Image();
      img.onload = () => {
        const max = 1000, sc = Math.min(1, max / Math.max(img.width, img.height));
        const c = document.createElement('canvas');
        c.width = Math.round(img.width*sc); c.height = Math.round(img.height*sc);
        c.getContext('2d').drawImage(img, 0, 0, c.width, c.height);
        res({ id: 'img-'+Math.random().toString(36).slice(2,8), dataUrl: c.toDataURL('image/jpeg',.78), name: file.name });
      };
      img.onerror = rej; img.src = e.target.result;
    };
    r.onerror = rej; r.readAsDataURL(file);
  });
}

/* ── sub-components ──────────────────────────────────────────── */

function StatusBadge({ status }) {
  return <span className={`tk-status-badge tk-status-${status}`}>{TK_STATUSES[status]?.label || status}</span>;
}

function PriBadge({ priority }) {
  const p = TK_PRIORITIES[priority] || TK_PRIORITIES.normal;
  return <span className="tk-pri-badge" style={{ color: p.color, background: p.color+'20' }}>{p.label}</span>;
}

function Lightbox({ src, onClose }) {
  useEffect(() => {
    const fn = e => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', fn);
    return () => window.removeEventListener('keydown', fn);
  }, [onClose]);
  return (
    <div className="tk-lightbox" onClick={onClose}>
      <img src={src} onClick={e => e.stopPropagation()} alt="ขยาย" />
      <button className="tk-lightbox-x" onClick={onClose}>×</button>
    </div>
  );
}

function ImgGrid({ images = [], onAdd, onRemove, editable }) {
  const [lb, setLb] = useState(null);
  const inp = useRef();
  const pick = async (files) => {
    const imgs = await Promise.all([...files].filter(f => f.type.startsWith('image/')).map(compressImg));
    if (imgs.length) onAdd(imgs);
  };
  return (
    <>
      <div className="tk-img-grid">
        {images.map(img => (
          <div key={img.id} className="tk-img-wrap">
            <img className="tk-img-thumb" src={img.dataUrl} alt={img.name} onClick={() => setLb(img.dataUrl)} />
            {editable && <button className="tk-img-del" onClick={() => onRemove(img.id)}>×</button>}
          </div>
        ))}
        {editable && (
          <>
            <button className="tk-img-add-btn" onClick={() => inp.current?.click()}>
              <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M10 4v12M4 10h12" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg>
              เพิ่มรูป
            </button>
            <input ref={inp} type="file" accept="image/*" multiple style={{display:'none'}} onChange={e => pick(e.target.files)} />
          </>
        )}
      </div>
      {lb && <Lightbox src={lb} onClose={() => setLb(null)} />}
    </>
  );
}

function CommentThread({ comments = [], onAdd }) {
  const [text, setText] = useState('');
  const send = () => {
    const t = text.trim(); if (!t) return;
    onAdd({ id: cId(), text: t, created: new Date().toISOString() });
    setText('');
  };
  return (
    <div>
      <div className="tk-comments">
        {comments.map(c => (
          <div key={c.id} className="tk-comment">
            <div className="tk-comment-avatar">💬</div>
            <div className="tk-comment-body">
              <div className="tk-comment-text">{c.text}</div>
              <div className="tk-comment-time">{fmtTs(c.created)}</div>
            </div>
          </div>
        ))}
      </div>
      <div className="tk-add-comment">
        <textarea className="tk-comment-ta" placeholder="เพิ่มความเคลื่อนไหว / บันทึกการติดต่อ Platform…&#10;กด Enter เพื่อส่ง"
          value={text} onChange={e => setText(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
        />
        <button className="tk-send-btn" onClick={send} disabled={!text.trim()}>ส่ง</button>
      </div>
    </div>
  );
}

/* ── TicketCard ──────────────────────────────────────────────── */
function TicketCard({ ticket, selected, onClick }) {
  const plat = PLATFORMS[ticket.platform] || PLATFORMS.shopee;
  return (
    <div className={`tk-card ${selected ? 'selected' : ''}`} style={{ borderLeftColor: plat.dot }} onClick={onClick}>
      <div className="tk-card-top">
        <span className="platform-badge" style={{ width:17, height:17, background:plat.dot, fontSize:7, borderRadius:3 }}>{plat.short}</span>
        <span className="tk-card-title">{ticket.title}</span>
        <StatusBadge status={ticket.status} />
      </div>
      <div className="tk-card-cat">{ticket.category}</div>
      <div className="tk-card-meta">
        <span>อัปเดต {relTs(ticket.updated || ticket.created)}</span>
        {ticket.order_code  && <><span>·</span><span style={{fontFamily:'monospace',fontSize:10}}>Order: {ticket.order_code}</span></>}
        {ticket.case_number && <><span>·</span><span style={{fontFamily:'monospace',fontSize:10}}>Case: {ticket.case_number}</span></>}
        {(ticket.images||[]).length > 0   && <><span>·</span><span>🖼 {ticket.images.length}</span></>}
        {(ticket.comments||[]).length > 0 && <><span>·</span><span>💬 {ticket.comments.length}</span></>}
      </div>
    </div>
  );
}

/* ── TicketDetail ────────────────────────────────────────────── */
function TicketDetail({ ticket, onUpdate, onDelete, onBack }) {
  const [editing, setEditing]         = useState(false);
  const [confirmDel, setConfirmDel]   = useState(false);
  const plat = PLATFORMS[ticket.platform] || PLATFORMS.shopee;

  if (editing) {
    return <TicketForm initial={ticket} mode="edit"
      onSave={t => { onUpdate(t); setEditing(false); }}
      onCancel={() => setEditing(false)} />;
  }

  const patch = (extra) => onUpdate({ ...ticket, ...extra, updated: new Date().toISOString() });

  return (
    <div className="tk-detail">
      {/* mobile back */}
      <button className="tk-mob-back tk-icon-btn" style={{ marginBottom:14 }} onClick={onBack}>
        <svg width="13" height="13" viewBox="0 0 14 14" fill="none"><path d="M9 2L4 7l5 5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/></svg>
        กลับ
      </button>

      <div className="tk-detail-title">{ticket.title}</div>

      {/* meta bar */}
      <div className="tk-detail-meta">
        <span className="platform-badge" style={{ width:22, height:22, background:plat.dot, fontSize:9, borderRadius:4 }}>{plat.short}</span>
        <span style={{fontSize:13,fontWeight:500}}>{plat.name}</span>

        {/* status changer */}
        <select className={`tk-status-sel tk-status-${ticket.status}`}
          style={{ color: TK_STATUSES[ticket.status]?.dot, borderColor: TK_STATUSES[ticket.status]?.dot }}
          value={ticket.status} onChange={e => patch({ status: e.target.value })}>
          {TK_STATUS_LIST.map(s => <option key={s} value={s}>{TK_STATUSES[s].label}</option>)}
        </select>

        <span style={{fontSize:11,color:'var(--ink-3)',marginLeft:'auto'}}>
          สร้าง {fmtTs(ticket.created)}
        </span>

        {/* action buttons */}
        <div className="tk-detail-actions">
          <button className="tk-edit-btn" onClick={() => setEditing(true)}>
            <svg width="11" height="11" viewBox="0 0 14 14" fill="none"><path d="M9.5 2a2 2 0 0 1 0 2.83L3.5 10.83 1 11.5l.67-2.5L7.67 2.5A2 2 0 0 1 9.5 2z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round"/></svg>
            แก้ไข
          </button>
          {confirmDel ? (
            <>
              <button className="tk-del-confirm" onClick={() => { onDelete(ticket.id); }}>ยืนยันลบ</button>
              <button className="tk-icon-btn" style={{padding:'5px 10px'}} onClick={() => setConfirmDel(false)}>ยกเลิก</button>
            </>
          ) : (
            <button className="tk-del-btn" onClick={() => setConfirmDel(true)}>
              <svg width="11" height="11" viewBox="0 0 14 14" fill="none"><path d="M2 3.5h10M5 3.5V2h4v1.5M5.5 6v4.5M8.5 6v4.5M3 3.5l.5 8.5h7l.5-8.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round"/></svg>
              ลบ
            </button>
          )}
        </div>
      </div>

      {/* category + order code + case number */}
      <div style={{display:'flex',gap:8,flexWrap:'wrap',marginBottom:18}}>
        <span className="tk-meta-chip">{ticket.category}</span>
        {ticket.order_code && <span className="tk-order-chip">
          <svg width="10" height="10" viewBox="0 0 12 12" fill="none"><rect x="1" y="2" width="10" height="8" rx="1.5" stroke="currentColor" strokeWidth="1.1"/><path d="M3 5h6M3 7h4" stroke="currentColor" strokeWidth="1.1" strokeLinecap="round"/></svg>
          Order: {ticket.order_code}
        </span>}
        {ticket.case_number && <span className="tk-order-chip" style={{background:'oklch(.94 .04 285)',color:'oklch(.42 .14 285)'}}>
          <svg width="10" height="10" viewBox="0 0 12 12" fill="none"><circle cx="6" cy="6" r="4.5" stroke="currentColor" strokeWidth="1.1"/><path d="M6 4v2.5l1.5 1.5" stroke="currentColor" strokeWidth="1.1" strokeLinecap="round"/></svg>
          Case: {ticket.case_number}
        </span>}
      </div>

      {/* description */}
      <div className="tk-section">
        <div className="tk-section-label">รายละเอียด</div>
        <div className="tk-desc-text">{ticket.description || <span style={{color:'var(--ink-3)'}}>ไม่มีรายละเอียด</span>}</div>
      </div>

      {/* images */}
      <div className="tk-section">
        <div className="tk-section-label">รูปหลักฐาน</div>
        <ImgGrid images={ticket.images||[]} editable
          onAdd={imgs => patch({ images: [...(ticket.images||[]), ...imgs] })}
          onRemove={id => patch({ images: (ticket.images||[]).filter(i => i.id !== id) })}
        />
      </div>

      {/* comments */}
      <div className="tk-section">
        <div className="tk-section-label">ความเคลื่อนไหว ({(ticket.comments||[]).length})</div>
        <CommentThread comments={ticket.comments||[]}
          onAdd={c => patch({ comments: [...(ticket.comments||[]), c] })} />
      </div>
    </div>
  );
}

/* ── TicketForm ──────────────────────────────────────────────── */
function TicketForm({ initial, mode='create', onSave, onCancel }) {
  const [platform,   setPlatform]   = useState(initial?.platform    || 'shopee');
  const [category,   setCategory]   = useState(initial?.category    || TK_CATEGORIES[0]);
  const [title,      setTitle]      = useState(initial?.title       || '');
  const [desc,       setDesc]       = useState(initial?.description || '');
  const [order,      setOrder]      = useState(initial?.order_code  || '');
  const [caseNumber, setCaseNumber] = useState(initial?.case_number || '');
  const [images,     setImages]     = useState(initial?.images      || []);
  const inp = useRef();

  const pickImgs = async (files) => {
    const imgs = await Promise.all([...files].filter(f => f.type.startsWith('image/')).map(compressImg));
    setImages(p => [...p, ...imgs]);
  };

  const submit = () => {
    if (!title.trim()) return alert('กรุณาใส่หัวเรื่อง');
    const now = new Date().toISOString();
    onSave({
      ...(initial || {}),
      id: initial?.id || tkId(),
      platform, category,
      title: title.trim(), description: desc.trim(),
      order_code: order.trim(), case_number: caseNumber.trim(),
      images,
      status:   initial?.status   || 'open',
      comments: initial?.comments || [],
      created:  initial?.created  || now,
      updated:  now,
    });
  };

  return (
    <div className="tk-form-wrap">
      <div className="tk-form-heading">{mode === 'edit' ? 'แก้ไขคำร้อง' : 'สร้างคำร้องใหม่'}</div>

      <div className="tk-field">
        <label className="tk-label">Platform</label>
        <select className="tk-select" value={platform} onChange={e => setPlatform(e.target.value)}>
          {Object.values(PLATFORMS).map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
        </select>
      </div>

      <div className="tk-field">
        <label className="tk-label">ประเภทปัญหา</label>
        <select className="tk-select" value={category} onChange={e => setCategory(e.target.value)}>
          {TK_CATEGORIES.map(c => <option key={c} value={c}>{c}</option>)}
        </select>
      </div>

      <div className="tk-field">
        <label className="tk-label">หัวเรื่อง *</label>
        <input className="tk-input" value={title} onChange={e => setTitle(e.target.value)}
          placeholder="เช่น ลูกค้าแจ้งของเสียหาย Order 2405121001" />
      </div>

      <div className="tk-row2" style={{marginBottom:14}}>
        <div className="tk-field" style={{marginBottom:0}}>
          <label className="tk-label">เลข Order (ถ้ามี)</label>
          <input className="tk-input" value={order} onChange={e => setOrder(e.target.value)}
            placeholder="เช่น 2405121001" style={{fontFamily:'JetBrains Mono,monospace',fontSize:13}} />
        </div>
        <div className="tk-field" style={{marginBottom:0}}>
          <label className="tk-label">เลขคำร้อง / Case No. (ถ้ามี)</label>
          <input className="tk-input" value={caseNumber} onChange={e => setCaseNumber(e.target.value)}
            placeholder="เช่น CS-20250518-001" style={{fontFamily:'JetBrains Mono,monospace',fontSize:13}} />
        </div>
      </div>

      <div className="tk-field">
        <label className="tk-label">รายละเอียด</label>
        <textarea className="tk-textarea" value={desc} onChange={e => setDesc(e.target.value)}
          placeholder="อธิบายปัญหา สิ่งที่ติดต่อ Platform ไปแล้ว ผลที่ได้รับ…" />
      </div>

      <div className="tk-field">
        <label className="tk-label">รูปหลักฐาน</label>
        <div className="tk-img-grid">
          {images.map(img => (
            <div key={img.id} className="tk-img-wrap">
              <img className="tk-img-thumb" src={img.dataUrl} alt={img.name} />
              <button className="tk-img-del" onClick={() => setImages(p => p.filter(i => i.id !== img.id))}>×</button>
            </div>
          ))}
          <button className="tk-img-add-btn" onClick={() => inp.current?.click()}>
            <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M10 4v12M4 10h12" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg>
            เพิ่มรูป
          </button>
          <input ref={inp} type="file" accept="image/*" multiple style={{display:'none'}} onChange={e => pickImgs(e.target.files)} />
        </div>
      </div>

      <div className="tk-form-footer">
        <button className="tk-icon-btn" onClick={onCancel}>ยกเลิก</button>
        <button className="tk-primary-btn" onClick={submit}>
          {mode === 'edit' ? 'บันทึกการแก้ไข' : 'สร้างคำร้อง'}
        </button>
      </div>
    </div>
  );
}

/* ── TicketsModal (main entry) ───────────────────────────────── */
function TicketsModal({ onClose }) {
  const [tickets,     setTickets]     = useState([]);
  const [loading,     setLoading]     = useState(true);
  const [statusF,     setStatusF]     = useState('all');
  const [platformF,   setPlatformF]   = useState('all');
  const [selected,    setSelected]    = useState(null);
  const [view,        setView]        = useState('list');  // 'list' | 'create'
  const [showDetail,  setShowDetail]  = useState(false);   // mobile

  useEffect(() => {
    tkFetch().then(d => { setTickets(d); setLoading(false); });
  }, []);

  useEffect(() => {
    const fn = e => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', fn);
    return () => window.removeEventListener('keydown', fn);
  }, [onClose]);

  const filtered = useMemo(() => tickets.filter(t => {
    if (statusF   !== 'all' && t.status   !== statusF)   return false;
    if (platformF !== 'all' && t.platform !== platformF) return false;
    return true;
  }), [tickets, statusF, platformF]);

  const selectedTicket = tickets.find(t => t.id === selected);

  const counts = useMemo(() => {
    const c = { all: tickets.length };
    TK_STATUS_LIST.forEach(s => { c[s] = tickets.filter(t => t.status === s).length; });
    return c;
  }, [tickets]);

  const saveTicket = (ticket) => {
    setTickets(prev => {
      const i = prev.findIndex(t => t.id === ticket.id);
      return i >= 0 ? prev.map(t => t.id === ticket.id ? ticket : t) : [ticket, ...prev];
    });
    tkSync(ticket);
    setSelected(ticket.id);
    setView('list');
    setShowDetail(true);
  };

  const updateTicket = (ticket) => {
    setTickets(prev => prev.map(t => t.id === ticket.id ? ticket : t));
    tkSync(ticket);
  };

  const deleteTicket = (id) => {
    setTickets(prev => prev.filter(t => t.id !== id));
    tkDelete(id);
    setSelected(null);
    setShowDetail(false);
  };

  const selectTicket = (id) => {
    setSelected(id);
    setShowDetail(true);
    if (view === 'create') setView('list');
  };

  return (
    <div className="tk-overlay">

      {/* ── header ── */}
      <div className="tk-header">
        {/* mobile back from detail */}
        <button className="tk-mob-back tk-icon-btn" onClick={() => { setShowDetail(false); setSelected(null); }}>
          <svg width="13" height="13" viewBox="0 0 14 14" fill="none"><path d="M9 2L4 7l5 5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/></svg>
          กลับ
        </button>

        <div className="tk-header-info">
          <div className="tk-header-title">
            <svg width="15" height="15" viewBox="0 0 16 16" fill="none" style={{verticalAlign:-2,marginRight:5}}>
              <path d="M2 3h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3z" stroke="currentColor" strokeWidth="1.3"/>
              <path d="M2 3h12" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/>
              <circle cx="5" cy="7.5" r=".8" fill="currentColor"/>
              <path d="M7.5 7.5h5M5 10.5h7" stroke="currentColor" strokeWidth="1.1" strokeLinecap="round"/>
            </svg>
            ระบบคำร้อง — Platform Tickets
          </div>
          <div className="tk-header-sub">จัดการปัญหากับ Shopee / TikTok / Lazada ในที่เดียว</div>
        </div>

        {view !== 'create' && (
          <button className="tk-primary-btn" onClick={() => { setView('create'); setShowDetail(false); }}>
            <svg width="13" height="13" viewBox="0 0 14 14" fill="none"><path d="M7 2v10M2 7h10" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"/></svg>
            สร้างคำร้องใหม่
          </button>
        )}
        <button className="tk-close-btn" onClick={onClose}>×</button>
      </div>

      {/* ── create form (full width) ── */}
      {view === 'create' && (
        <div style={{flex:1,overflowY:'auto'}}>
          <TicketForm mode="create"
            onSave={saveTicket}
            onCancel={() => setView('list')} />
        </div>
      )}

      {/* ── list + detail ── */}
      {view === 'list' && (
        <div className={`tk-body ${showDetail ? 'show-detail' : ''}`}>

          {/* sidebar */}
          <div className="tk-sidebar">

            {/* status tabs */}
            <div className="tk-tabs">
              {[{k:'all',l:'ทั้งหมด'},{k:'open',l:'เปิด'},{k:'in_progress',l:'ดำเนินการ'},{k:'waiting',l:'รอตอบ'},{k:'resolved',l:'แก้แล้ว'}].map(({k,l}) => (
                <button key={k} className={`tk-tab ${statusF===k?'active':''}`} onClick={() => setStatusF(k)}>
                  {l}
                  {counts[k] > 0 && <span className="tk-tab-count">{counts[k]}</span>}
                </button>
              ))}
            </div>

            {/* platform chips */}
            <div className="tk-pchips">
              <button className={`tk-pchip ${platformF==='all'?'active':''}`}
                style={{color:'var(--ink-2)',borderColor:'var(--ink-2)'}}
                onClick={() => setPlatformF('all')}>ทุก Platform</button>
              {Object.values(PLATFORMS).map(p => (
                <button key={p.id}
                  className={`tk-pchip ${platformF===p.id?'active':''}`}
                  style={{color:p.dot,borderColor:p.dot}}
                  onClick={() => setPlatformF(platformF===p.id?'all':p.id)}>
                  <span className="platform-badge" style={{width:11,height:11,background:p.dot,fontSize:5,borderRadius:2}}>{p.short}</span>
                  {p.name}
                </button>
              ))}
            </div>

            {/* list */}
            <div className="tk-list">
              {loading ? (
                <div className="tk-list-empty">กำลังโหลด…</div>
              ) : filtered.length === 0 ? (
                <div className="tk-list-empty">
                  {tickets.length === 0
                    ? <>ยังไม่มีคำร้อง<br/><small>กดปุ่ม "สร้างคำร้องใหม่" ด้านบน</small></>
                    : 'ไม่พบคำร้องตามเงื่อนไข'}
                </div>
              ) : filtered.map(t => (
                <TicketCard key={t.id} ticket={t} selected={selected===t.id} onClick={() => selectTicket(t.id)} />
              ))}
            </div>
          </div>

          {/* main detail */}
          <div className="tk-main">
            {selectedTicket ? (
              <TicketDetail
                ticket={selectedTicket}
                onUpdate={updateTicket}
                onDelete={deleteTicket}
                onBack={() => { setShowDetail(false); setSelected(null); }}
              />
            ) : (
              <div className="tk-placeholder">
                <svg width="56" height="56" viewBox="0 0 56 56" fill="none">
                  <rect x="8" y="8" width="40" height="40" rx="10" stroke="currentColor" strokeWidth="2"/>
                  <path d="M18 21h20M18 28h12M18 35h15" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
                </svg>
                <p>เลือกคำร้องเพื่อดูรายละเอียด</p>
              </div>
            )}
          </div>

        </div>
      )}
    </div>
  );
}

Object.assign(window, { TicketsModal });
