/* ============================================================
   SVLM — Chat (general SVLM support + per-booking crew threads) and
   Complaints. Ported from public/index.html's loadChatThreads()/
   openChatThread()/loadChatMessages()/sendChatMessage()/fileComplaint()
   — same real GET /chat/mine/threads, GET+POST /chat/mine or
   /chat/booking/:id, same auth'd blob-fetch for image/file attachments
   (they need an Authorization header, so a plain <img src> can't hit
   the route directly).
   ============================================================ */
const Pch = window.PALETTE;

const chatBlobCache = new Map();
async function fetchChatBlobUrl(kind, filename) {
  const cacheKey = `${kind}:${filename}`;
  if (chatBlobCache.has(cacheKey)) return chatBlobCache.get(cacheKey);
  const token = localStorage.getItem('svlm_token');
  const res = await fetch(`/api/chat/${kind}/${filename}`, { headers: { Authorization: `Bearer ${token}` } });
  const blob = await res.blob();
  const url = URL.createObjectURL(blob);
  chatBlobCache.set(cacheKey, url);
  return url;
}

function ChatImage({ filename }) {
  const [src, setSrc] = React.useState(null);
  React.useEffect(() => { fetchChatBlobUrl('image', filename).then(setSrc); }, [filename]);
  if (!src) return <div style={{ width: 72, height: 72, borderRadius: 10, background: Pch.lineSoft }} />;
  return <img src={src} alt="" onClick={() => window.open(src, '_blank')} style={{ width: 72, height: 72, borderRadius: 10, objectFit: 'cover', cursor: 'pointer' }} />;
}

async function openChatDoc(filename) {
  const url = await fetchChatBlobUrl('document', filename);
  window.open(url, '_blank');
}

function ChatThreadsScreen({ app }) {
  const [threads, setThreads] = React.useState(null);
  React.useEffect(() => {
    api('/chat/mine/threads').then(data => {
      const supportName = t('customer', 'svlm_support_name') || 'SVLM Support';
      setThreads([
        { kind: 'general', bookingId: null, name: supportName, photo: null, online: null, last_message: data.general.last_message, last_at: data.general.last_at },
        ...data.bookings.map(b => ({ kind: 'booking', bookingId: b.booking_id, name: b.staff_name, photo: b.staff_photo, online: b.availability_status === 'online', last_message: b.last_message || b.service_name, last_at: b.last_at })),
      ]);
    });
  }, []);

  const timeLabel = (iso) => {
    if (!iso) return '';
    const d = new Date(iso);
    const isToday = d.toDateString() === new Date().toDateString();
    return isToday ? d.toLocaleTimeString(app.lang, { hour: '2-digit', minute: '2-digit' }) : d.toLocaleDateString(app.lang, { month: 'short', day: 'numeric' });
  };

  return (
    <div>
      <AppHeader onBack={app.back} title={t('customer', 'chat_with_svlm') || 'Chat'} />
      <div style={{ padding: '0 20px 30px' }}>
        {threads === null ? null : threads.map(r => (
          <div key={`${r.kind}-${r.bookingId}`} onClick={() => app.go('chat-thread', { kind: r.kind, bookingId: r.bookingId, name: r.name, online: r.online })}
            style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 4px', borderBottom: `1px solid ${Pch.lineSoft}`, cursor: 'pointer' }}>
            <div style={{ position: 'relative', flexShrink: 0 }}>
              <div style={{ width: 46, height: 46, borderRadius: 99, background: Pch.tintBlue, display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 800, color: Pch.primary, overflow: 'hidden' }}>
                {r.photo ? <img src={r.photo} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} /> : (r.name || '?').trim().charAt(0).toUpperCase()}
              </div>
              {r.online !== null && <span style={{ position: 'absolute', bottom: 0, right: 0, width: 12, height: 12, borderRadius: 99, border: '2px solid #fff', background: r.online ? Pch.mint : Pch.faint }} />}
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontWeight: 700, fontSize: 14, color: Pch.ink }}>{r.name}</div>
              <div style={{ fontSize: 12, color: Pch.faint, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r.last_message || (t('customer', 'no_chat_messages') || 'No messages yet')}</div>
            </div>
            <div style={{ fontSize: 11, color: Pch.faint, flexShrink: 0 }}>{timeLabel(r.last_at)}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

function ChatThreadScreen({ app, params }) {
  const { kind, bookingId, name, online } = params;
  const [messages, setMessages] = React.useState(null);
  const [text, setText] = React.useState('');
  const [images, setImages] = React.useState([]);
  const fileRef = React.useRef(null);
  const scrollRef = React.useRef(null);

  const load = () => {
    const endpoint = kind === 'booking' ? `/chat/booking/${bookingId}` : '/chat/mine';
    return api(endpoint).then(setMessages);
  };
  React.useEffect(() => {
    load();
    const poll = setInterval(load, 5000);
    return () => clearInterval(poll);
  }, [kind, bookingId]);
  React.useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [messages]);

  const send = async () => {
    if (!text.trim() && images.length === 0) return;
    const form = new FormData();
    if (text.trim()) form.append('body', text.trim());
    images.forEach(f => form.append('images', f));
    setText(''); setImages([]);
    const endpoint = kind === 'booking' ? `/chat/booking/${bookingId}` : '/chat/mine';
    await api(endpoint, { method: 'POST', body: form });
    load();
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
      <AppHeader onBack={app.back} title={name} sub={online === null ? undefined : (online ? (t('customer', 'online_status') || 'Online') : (t('customer', 'offline_status') || 'Offline'))} />
      <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', padding: '0 20px' }}>
        {messages === null ? null : messages.length === 0
          ? <p style={{ fontSize: 13, color: Pch.faint, textAlign: 'center', marginTop: 30 }}>{t('customer', 'no_chat_messages') || 'No messages yet — say hello!'}</p>
          : messages.map((m, i) => {
            const isSelf = m.sender === 'customer';
            return (
              <div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: isSelf ? 'flex-end' : 'flex-start', marginBottom: 12 }}>
                <div style={{ fontSize: 10.5, color: Pch.faint, marginBottom: 3, fontWeight: 600 }}>{isSelf ? (t('customer', 'you_label') || 'You') : (m.sender === 'ai' ? (t('customer', 'ai_assistant_label') || 'SVLM Assistant') : (m.sender === 'ops' ? 'SVLM' : m.sender))}</div>
                {m.body && <div style={{ maxWidth: '75%', padding: '10px 14px', borderRadius: 16, background: isSelf ? Pch.primary : '#fff', color: isSelf ? '#fff' : Pch.ink, fontSize: 13.5, border: isSelf ? 'none' : `1px solid ${Pch.line}`, boxShadow: isSelf ? 'none' : '0 1px 2px rgba(11,37,69,0.04)' }}>{m.body}</div>}
                {m.image_urls?.length > 0 && <div style={{ display: 'flex', gap: 6, marginTop: m.body ? 6 : 0 }}>{m.image_urls.map((f, j) => <ChatImage key={j} filename={f} />)}</div>}
                {m.file_urls?.length > 0 && <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: m.body ? 6 : 0 }}>{m.file_urls.map((f, j) => (
                  <button key={j} onClick={() => openChatDoc(f)} style={{ padding: '8px 12px', borderRadius: 12, border: `1.5px solid ${Pch.line}`, background: '#fff', fontWeight: 700, fontSize: 12, color: Pch.ink, cursor: 'pointer' }}>📄 {t('customer', 'open_document') || 'Open document'}</button>
                ))}</div>}
              </div>
            );
          })}
      </div>
      <div style={{ padding: '10px 16px calc(10px + env(safe-area-inset-bottom))', borderTop: `1px solid ${Pch.line}`, background: '#fff' }}>
        {images.length > 0 && <div style={{ fontSize: 11.5, color: Pch.faint, marginBottom: 6 }}>{images.length} image{images.length > 1 ? 's' : ''} attached</div>}
        <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
          <button onClick={() => fileRef.current.click()} style={{ width: 40, height: 40, borderRadius: 12, border: `1.5px solid ${Pch.line}`, background: '#fff', flexShrink: 0, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="camera" size={18} color={Pch.muted} /></button>
          <input ref={fileRef} type="file" multiple accept="image/jpeg,image/png,image/webp" style={{ display: 'none' }} onChange={e => setImages([...e.target.files])} />
          <input value={text} onChange={e => setText(e.target.value)} onKeyDown={e => e.key === 'Enter' && send()} placeholder={t('customer', 'type_message') || 'Type a message...'} style={{ flex: 1, height: 40, borderRadius: 12, border: `1.5px solid ${Pch.line}`, padding: '0 14px', fontFamily: 'inherit', fontSize: 13.5 }} />
          <button onClick={send} style={{ width: 40, height: 40, borderRadius: 12, border: 'none', background: Pch.primary, flexShrink: 0, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="chevR" size={18} color="#fff" /></button>
        </div>
      </div>
    </div>
  );
}

/* ---------- File a complaint — real POST /complaints, same fields as index.html's
   fileComplaint(). ---------- */
function ComplaintScreen({ app }) {
  const [bookingId, setBookingId] = React.useState('');
  const [severity, setSeverity] = React.useState('low');
  const [text, setText] = React.useState('');
  const [err, setErr] = React.useState('');
  const [done, setDone] = React.useState(false);

  const submit = async () => {
    setErr('');
    try {
      await api('/complaints', { method: 'POST', body: JSON.stringify({ booking_id: bookingId.trim(), severity, text_en: text.trim() }) });
      setDone(true);
    } catch (e) { setErr(e.message); }
  };

  if (done) {
    return (
      <div style={{ minHeight: '100vh', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 24, textAlign: 'center' }}>
        <div style={{ width: 76, height: 76, borderRadius: 99, background: Pch.mintSoft, display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 20 }}>
          <Icon name="check" size={36} color={Pch.mint} sw={2.6} />
        </div>
        <h2 style={{ fontSize: 19, fontWeight: 800, color: Pch.ink, margin: '0 0 20px' }}>{app.lang === 'th' ? 'ส่งเรื่องร้องเรียนแล้ว' : 'Complaint submitted'}</h2>
        <Btn style={{ maxWidth: 260 }} onClick={() => app.go('tab-account')}>{app.lang === 'th' ? 'กลับโปรไฟล์' : 'Back to Profile'}</Btn>
      </div>
    );
  }

  return (
    <div>
      <AppHeader onBack={app.back} title={t('customer', 'file_complaint') || 'File complaint'} />
      <div style={{ padding: '0 20px 40px' }}>
        <Field label={t('customer', 'booking_id_label') || 'Booking ID'}>
          <input value={bookingId} onChange={e => setBookingId(e.target.value)} placeholder="SV-20001" style={inputStyle} />
        </Field>
        <Field label={t('customer', 'severity_label') || 'Severity'}>
          <select value={severity} onChange={e => setSeverity(e.target.value)} style={selStyle}>
            <option value="low">{app.lang === 'th' ? 'ต่ำ' : 'Low'}</option>
            <option value="medium">{app.lang === 'th' ? 'ปานกลาง' : 'Medium'}</option>
            <option value="high">{app.lang === 'th' ? 'สูง' : 'High'}</option>
          </select>
        </Field>
        <Field label={t('customer', 'details_label') || 'Details'}>
          <textarea value={text} onChange={e => setText(e.target.value)} rows={5} style={{ ...inputStyle, height: 'auto', padding: 12, resize: 'vertical' }} />
        </Field>
        {err && <p style={{ color: '#d23a3a', fontSize: 13, marginBottom: 10 }}>{err}</p>}
        <Btn onClick={submit}>{t('customer', 'file_complaint') || 'File complaint'}</Btn>
      </div>
    </div>
  );
}

Object.assign(window, { ChatThreadsScreen, ChatThreadScreen, ComplaintScreen });
