// whatsapp.jsx — WhatsApp conversation inbox for clinic staff (redesigned).

const { useState: useStateWA, useEffect: useEffectWA, useRef: useRefWA, useCallback: useCallbackWA, useMemo: useMemoWA } = React;

function WhatsAppInbox() {
  const t = window.MSStore.useT();
  const store = window.MSStore.useStore();
  const [conversations, setConversations] = useStateWA([]);
  const [activeConvId, setActiveConvId] = useStateWA(null);
  const [messages, setMessages] = useStateWA([]);
  const [draft, setDraft] = useStateWA("");
  const [sending, setSending] = useStateWA(false);
  const [loadingConvs, setLoadingConvs] = useStateWA(true);
  const [loadingMsgs, setLoadingMsgs] = useStateWA(false);
  const [error, setError] = useStateWA("");
  const [searchQuery, setSearchQuery] = useStateWA("");
  const [pendingAppts, setPendingAppts] = useStateWA([]);
  const [showPending, setShowPending] = useStateWA(false);
  const [deleteConfirmId, setDeleteConfirmId] = useStateWA(null);
  const [reminderSettings, setReminderSettings] = useStateWA(null);
  const [showSettings, setShowSettings] = useStateWA(false);
  const [actionLoading, setActionLoading] = useStateWA("");
  const [templates, setTemplates] = useStateWA([]);
  const [showTemplates, setShowTemplates] = useStateWA(false);
  const [templateVars, setTemplateVars] = useStateWA({});
  const [selectedTemplate, setSelectedTemplate] = useStateWA(null);
  const [activeTab, setActiveTab] = useStateWA("conversations");
  const [bundleInputMode, setBundleInputMode] = useStateWA("upload");
  const [bundleFile, setBundleFile] = useStateWA(null);
  const [bundleManualText, setBundleManualText] = useStateWA("");
  const [bundlePreview, setBundlePreview] = useStateWA(null);
  const [bundleMessage, setBundleMessage] = useStateWA("Hola {name}, ");
  const [bundleUploading, setBundleUploading] = useStateWA(false);
  const [bundleSending, setBundleSending] = useStateWA(false);
  const [bundleConsent, setBundleConsent] = useStateWA(false);
  const [bundleResults, setBundleResults] = useStateWA(null);
  const messagesEndRef = useRefWA(null);
  const pollRef = useRefWA(null);

  const activeConv = conversations.find(c => c.id === activeConvId) || null;

  // Load conversations
  const loadConversations = useCallbackWA(async () => {
    try {
      const r = await window.MSApi.apiFetch("/api/whatsapp/conversations");
      setConversations((r && r.conversations) || []);
    } catch (e) {
      if (!e.message?.includes("workspace")) setError(e?.message || "Failed to load conversations");
    } finally {
      setLoadingConvs(false);
    }
  }, []);

  // Load pending appointments
  const loadPending = useCallbackWA(async () => {
    try {
      const r = await window.MSApi.apiFetch("/api/whatsapp/pending-appointments");
      setPendingAppts((r && r.appointments) || []);
    } catch (_) {}
  }, []);

  useEffectWA(() => {
    loadConversations();
    loadPending();
    const iv = setInterval(() => { loadConversations(); loadPending(); }, 15000);
    return () => clearInterval(iv);
  }, [loadConversations, loadPending]);

  // Load messages for active conversation
  const loadMessages = useCallbackWA(async (convId) => {
    if (!convId) return;
    setLoadingMsgs(true);
    try {
      const r = await window.MSApi.apiFetch(`/api/whatsapp/conversations/${convId}/messages`);
      setMessages((r && r.messages) || []);
    } catch (e) {
      setError(e?.message || "Failed to load messages");
    } finally {
      setLoadingMsgs(false);
    }
  }, []);

  useEffectWA(() => {
    if (activeConvId) {
      loadMessages(activeConvId);
      clearInterval(pollRef.current);
      pollRef.current = setInterval(() => loadMessages(activeConvId), 5000);
    }
    return () => clearInterval(pollRef.current);
  }, [activeConvId, loadMessages]);

  // Scroll to bottom when messages change
  useEffectWA(() => {
    const node = messagesEndRef.current;
    if (node) node.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  // Send message
  async function handleSend() {
    if (!draft.trim() || !activeConv || sending) return;
    setSending(true); setError("");
    try {
      await window.MSApi.apiFetch("/api/whatsapp/send", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ patient_id: activeConv.patient_id, body: draft.trim() }),
      });
      setDraft("");
      await loadMessages(activeConvId);
      await loadConversations();
    } catch (e) {
      setError(e?.message || "Failed to send message");
    } finally {
      setSending(false);
    }
  }

  // Delete conversation
  async function handleDelete(convId) {
    try {
      await window.MSApi.apiFetch(`/api/whatsapp/conversations/${convId}`, { method: "DELETE" });
      setConversations(prev => prev.filter(c => c.id !== convId));
      if (activeConvId === convId) { setActiveConvId(null); setMessages([]); }
      setDeleteConfirmId(null);
    } catch (e) {
      setError(e?.message || "Failed to delete");
    }
  }

  // Accept/reject appointment
  async function handleAppointmentAction(apptId, action) {
    setActionLoading(apptId);
    try {
      await window.MSApi.apiFetch(`/api/whatsapp/appointments/${apptId}/${action}`, { method: "POST" });
      setPendingAppts(prev => prev.filter(a => a.id !== apptId));
      await loadMessages(activeConvId);
      await loadPending();
      // Refresh calendar and notifications so accepted/rejected appointments appear
      if (store.loadAppointments) store.loadAppointments();
      if (store.loadNotifications) store.loadNotifications();
    } catch (e) {
      setError(e?.message || `Failed to ${action}`);
    } finally {
      setActionLoading("");
    }
  }

  // Load templates
  useEffectWA(() => {
    (async () => {
      try {
        const r = await window.MSApi.apiFetch("/api/whatsapp/templates");
        setTemplates((r && r.templates) || []);
      } catch (_) {}
    })();
  }, []);

  function selectTemplate(tpl) {
    if (tpl.id === "custom") {
      setSelectedTemplate(null);
      setShowTemplates(false);
      return;
    }
    setSelectedTemplate(tpl);
    const vars = {};
    if (activeConv && activeConv.patient_name) vars.patient_name = activeConv.patient_name;
    setTemplateVars(vars);
  }

  function insertTemplate() {
    if (!selectedTemplate) return;
    const lang = window.MSi18n.getLang() === "es" ? "es" : "en";
    let body = lang === "es" ? selectedTemplate.body_es : selectedTemplate.body_en;
    for (const [k, v] of Object.entries(templateVars)) {
      body = body.replace(new RegExp("\\{" + k + "\\}", "g"), v);
    }
    body = body.replace(/\{[a-z_]+\}/g, "___");
    setDraft(body);
    setSelectedTemplate(null);
    setShowTemplates(false);
    setTemplateVars({});
  }

  // Load reminder settings
  useEffectWA(() => {
    (async () => {
      try {
        const r = await window.MSApi.apiFetch("/api/whatsapp/reminders/settings");
        setReminderSettings(r && r.settings);
      } catch (_) {}
    })();
  }, []);

  async function saveReminderSettings(updates) {
    try {
      const r = await window.MSApi.apiFetch("/api/whatsapp/reminders/settings", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ ...reminderSettings, ...updates }),
      });
      setReminderSettings(r && r.settings);
    } catch (e) {
      setError(e?.message || "Failed to save settings");
    }
  }

  function formatTime(iso) {
    if (!iso) return "";
    try {
      const d = new Date(iso);
      const lang = window.MSi18n.getLang() === "es" ? "es-ES" : "en-US";
      const now = new Date();
      if (d.toDateString() === now.toDateString()) {
        return d.toLocaleTimeString(lang, { hour: "2-digit", minute: "2-digit" });
      }
      return d.toLocaleDateString(lang, { month: "short", day: "numeric" }) + " " +
             d.toLocaleTimeString(lang, { hour: "2-digit", minute: "2-digit" });
    } catch (_) { return iso; }
  }

  function formatDateTime(iso) {
    if (!iso) return "";
    try {
      const d = new Date(iso);
      const lang = window.MSi18n.getLang() === "es" ? "es-ES" : "en-US";
      return d.toLocaleDateString(lang, { weekday: "short", month: "short", day: "numeric" }) + " " +
             d.toLocaleTimeString(lang, { hour: "2-digit", minute: "2-digit" });
    } catch (_) { return iso; }
  }

  function statusBadge(status) {
    const map = { delivered: "✓✓", read: "✓✓", sent: "✓", queued: "⏳", failed: "✗", undelivered: "✗" };
    const cls = status === "failed" || status === "undelivered" ? "is-error" : status === "read" ? "is-read" : "";
    return React.createElement("span", { className: "ms-wa-status " + cls }, map[status] || "");
  }

  // Filter conversations
  const filteredConvs = useMemoWA(() => {
    if (!searchQuery.trim()) return conversations;
    const q = searchQuery.toLowerCase();
    return conversations.filter(c =>
      (c.patient_name || "").toLowerCase().includes(q) ||
      (c.from_number || "").includes(q)
    );
  }, [conversations, searchQuery]);

  // Quick replies
  const quickReplies = [
    { key: "quickConfirm", icon: Icon.Check },
    { key: "quickDirections", icon: Icon.Pin },
    { key: "quickPreVisit", icon: Icon.Clipboard },
  ];

  const bundleValidRows = ((bundlePreview && bundlePreview.rows) || []).filter(r => r.valid);
  const bundleInvalidRows = ((bundlePreview && bundlePreview.rows) || []).filter(r => !r.valid);

  function normalizeBundlePhone(raw) {
    let value = String(raw || "").trim().replace(/^whatsapp:/i, "");
    if (!value) return "";
    if (value.startsWith("00")) value = "+" + value.slice(2);
    const plus = value.startsWith("+");
    const digits = value.replace(/\D/g, "");
    if (digits.length < 8 || digits.length > 15) return "";
    return plus ? "+" + digits : "";
  }

  function buildBundlePreview(rows) {
    const seen = new Set();
    const normalized = rows.map((item, idx) => {
      const phone = item.phone || "";
      const normalizedPhone = normalizeBundlePhone(phone);
      const errors = [];
      let duplicate = false;
      if (!normalizedPhone) errors.push(t("wa.invalidPhone"));
      if (normalizedPhone && seen.has(normalizedPhone)) {
        duplicate = true;
        errors.push(t("wa.duplicatePhone"));
      }
      if (normalizedPhone && !duplicate) seen.add(normalizedPhone);
      return {
        row: idx + 1,
        name: item.name || "",
        phone,
        normalized_phone: normalizedPhone,
        language: item.language || "",
        fields: item.fields || {},
        valid: errors.length === 0,
        duplicate,
        errors,
      };
    });
    const valid = normalized.filter(r => r.valid).length;
    const duplicates = normalized.filter(r => r.duplicate).length;
    setBundlePreview({
      rows: normalized,
      summary: {
        total: normalized.length,
        valid,
        invalid: normalized.length - valid,
        duplicates,
      },
    });
  }

  function handleManualPreview() {
    const lines = bundleManualText.split(/\r?\n/).map(v => v.trim()).filter(Boolean);
    const rows = lines.map(line => {
      const parts = line.split(/[,;\t]/).map(v => v.trim()).filter(Boolean);
      if (parts.length >= 2) {
        return { name: parts[0], phone: parts[1], language: parts[2] || "", fields: {} };
      }
      return { name: "", phone: parts[0] || line, language: "", fields: {} };
    });
    buildBundlePreview(rows);
    setBundleResults(null);
  }

  function renderBundleMessage(row) {
    const fields = Object.assign({}, row.fields || {}, {
      name: row.name || "",
      patient_name: row.name || "",
      phone: row.normalized_phone || row.phone || "",
      language: row.language || "",
    });
    return (bundleMessage || "").replace(/\{([a-zA-Z0-9_]+)\}/g, (_, key) => fields[key] == null ? "" : fields[key]);
  }

  async function handleBundlePreview() {
    if (!bundleFile || bundleUploading) return;
    setBundleUploading(true); setError(""); setBundleResults(null);
    try {
      const fd = new FormData();
      fd.append("file", bundleFile);
      const r = await window.MSApi.apiFetch("/api/whatsapp/bundle/preview", { method: "POST", body: fd });
      setBundlePreview(r);
    } catch (e) {
      setError(e?.message || "Failed to upload bundle list");
    } finally {
      setBundleUploading(false);
    }
  }

  async function handleBundleSend() {
    if (!bundleValidRows.length || !bundleMessage.trim() || !bundleConsent || bundleSending) return;
    setBundleSending(true); setError(""); setBundleResults(null);
    try {
      const recipients = bundleValidRows.map(r => ({
        name: r.name || "",
        phone: r.normalized_phone,
        language: r.language || "",
        fields: r.fields || {},
      }));
      const r = await window.MSApi.apiFetch("/api/whatsapp/bundle/send", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ body: bundleMessage.trim(), recipients, consent_confirmed: bundleConsent }),
      });
      setBundleResults(r);
      await loadConversations();
    } catch (e) {
      setError(e?.message || "Failed to send bundle messages");
    } finally {
      setBundleSending(false);
    }
  }

  return (
    <div className="ms-page fade-in">
      <div className="ms-page-head">
        <div>
          <h1 className="h1">{t("wa.title")}</h1>
          <div style={{color: "var(--ink-3)", marginTop: 4, fontSize: 14}}>{t("wa.subtitle")}</div>
        </div>
        <div className="row" style={{ gap: 8 }}>
          {pendingAppts.length > 0 && (
            <button className={"btn " + (showPending ? "btn-primary" : "btn-warn")} onClick={() => setShowPending(!showPending)}>
              <Icon.Calendar size={15}/>
              {t("wa.pendingAppointments")}
              <span className="badge badge-warn" style={{marginLeft: 4}}>{pendingAppts.length}</span>
            </button>
          )}
          <button className="btn btn-ghost" onClick={() => setShowSettings(!showSettings)}>
            <Icon.Settings size={15}/>
            {t("wa.settings")}
          </button>
        </div>
      </div>

      {error && (
        <div style={{padding: "10px 14px", borderRadius: 10, background: "color-mix(in oklch, var(--accent-danger) 10%, var(--surface))", color: "var(--accent-danger)", fontSize: 13, marginBottom: 12, display: "flex", alignItems: "center", gap: 8}}>
          <span style={{flex: 1}}>{error}</span>
          <button className="btn btn-ghost btn-sm" onClick={() => setError("")} style={{padding: "0 6px", minWidth: 0}}>{"✕"}</button>
        </div>
      )}

      <div className="ms-wa-tabs">
        <button className={"ms-wa-tab" + (activeTab === "conversations" ? " is-active" : "")}
          onClick={() => setActiveTab("conversations")}>
          <Icon.MessageCircle size={15}/>
          {t("wa.conversations")}
        </button>
        <button className={"ms-wa-tab" + (activeTab === "bundle" ? " is-active" : "")}
          onClick={() => setActiveTab("bundle")}>
          <Icon.Upload size={15}/>
          {t("wa.bundleMessages")}
        </button>
      </div>

      {activeTab === "bundle" && (
        <div className="ms-wa-bundle">
          <div className="ms-wa-bundle-main card">
            <div className="ms-wa-bundle-section">
              <div className="ms-wa-bundle-head">
                <div>
                  <h3>{t("wa.bundleUpload")}</h3>
                  <p>{t("wa.bundleUploadHelp")}</p>
                </div>
                <button className="btn btn-ghost btn-sm" onClick={() => {
                  setBundleFile(null); setBundleManualText(""); setBundlePreview(null); setBundleResults(null); setBundleConsent(false);
                }}>
                  <Icon.Refresh size={14}/>
                  {t("wa.reset")}
                </button>
              </div>
              <div className="ms-wa-mode-toggle">
                <button className={bundleInputMode === "upload" ? "is-active" : ""} onClick={() => { setBundleInputMode("upload"); setBundlePreview(null); }}>
                  <Icon.Upload size={14}/>
                  {t("wa.uploadSheet")}
                </button>
                <button className={bundleInputMode === "manual" ? "is-active" : ""} onClick={() => { setBundleInputMode("manual"); setBundlePreview(null); }}>
                  <Icon.Edit size={14}/>
                  {t("wa.typeNumbers")}
                </button>
              </div>
              {bundleInputMode === "upload" ? (
                <>
                  <div className="ms-wa-upload-row">
                    <input className="input" type="file" accept=".csv,.xlsx"
                      onChange={(e) => { setBundleFile(e.target.files && e.target.files[0]); setBundlePreview(null); setBundleResults(null); }}/>
                    <button className="btn btn-primary" disabled={!bundleFile || bundleUploading} onClick={handleBundlePreview}>
                      <Icon.Upload size={15}/>
                      {bundleUploading ? t("wa.uploading") : t("wa.previewList")}
                    </button>
                  </div>
                  <div className="ms-wa-bundle-format">{t("wa.bundleFormat")}</div>
                </>
              ) : (
                <>
                  <textarea className="ms-wa-bundle-textarea is-compact" value={bundleManualText}
                    onChange={(e) => { setBundleManualText(e.target.value); setBundlePreview(null); setBundleResults(null); }}
                    placeholder={t("wa.typeNumbersPlaceholder")}/>
                  <div className="ms-wa-upload-row" style={{marginTop: 10}}>
                    <button className="btn btn-primary" disabled={!bundleManualText.trim()} onClick={handleManualPreview}>
                      <Icon.Check size={15}/>
                      {t("wa.previewList")}
                    </button>
                  </div>
                  <div className="ms-wa-bundle-format">{t("wa.typeNumbersHelp")}</div>
                </>
              )}
            </div>

            {bundlePreview && (
              <div className="ms-wa-bundle-section">
                <div className="ms-wa-bundle-stats">
                  <div><strong>{bundlePreview.summary.total}</strong><span>{t("wa.totalRows")}</span></div>
                  <div><strong>{bundlePreview.summary.valid}</strong><span>{t("wa.validRows")}</span></div>
                  <div><strong>{bundlePreview.summary.invalid}</strong><span>{t("wa.invalidRows")}</span></div>
                  <div><strong>{bundlePreview.summary.duplicates}</strong><span>{t("wa.duplicateRows")}</span></div>
                </div>
                <div className="ms-wa-bundle-table-wrap">
                  <table className="ms-wa-bundle-table">
                    <thead><tr><th>{t("wa.row")}</th><th>{t("wa.name")}</th><th>{t("wa.phone")}</th><th>{t("wa.language")}</th><th>{t("wa.status")}</th></tr></thead>
                    <tbody>
                      {(bundlePreview.rows || []).slice(0, 100).map(r => (
                        <tr key={r.row} className={r.valid ? "" : "is-invalid"}>
                          <td>{r.row}</td>
                          <td>{r.name || "-"}</td>
                          <td>{r.normalized_phone || r.phone || "-"}</td>
                          <td>{r.language || "-"}</td>
                          <td>{r.valid ? t("wa.ready") : (r.errors || []).join(", ")}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
                {bundleInvalidRows.length > 0 && <div className="ms-wa-bundle-note">{t("wa.invalidSkipped")}</div>}
              </div>
            )}

            <div className="ms-wa-bundle-section">
              <div className="ms-wa-bundle-head">
                <div>
                  <h3>{t("wa.bundleCompose")}</h3>
                  <p>{t("wa.bundleComposeHelp")}</p>
                </div>
              </div>
              <textarea className="ms-wa-bundle-textarea" value={bundleMessage}
                onChange={(e) => setBundleMessage(e.target.value)}
                placeholder={t("wa.bundlePlaceholder")}/>
              {bundleValidRows.length > 0 && (
                <div className="ms-wa-bundle-preview">
                  <div className="ms-wa-template-name">{t("wa.samplePreview")}</div>
                  <div className="ms-wa-msg-bubble">{renderBundleMessage(bundleValidRows[0])}</div>
                </div>
              )}
              <label className="ms-wa-consent-check">
                <input type="checkbox" checked={bundleConsent} onChange={(e) => setBundleConsent(e.target.checked)}/>
                <span>{t("wa.bundleConsent")}</span>
              </label>
              <div className="ms-wa-bundle-actions">
                <button className="btn btn-primary" disabled={!bundleValidRows.length || !bundleMessage.trim() || !bundleConsent || bundleSending}
                  onClick={handleBundleSend}>
                  <Icon.Send size={15}/>
                  {bundleSending ? t("wa.sending") : t("wa.sendBundle").replace("{n}", bundleValidRows.length)}
                </button>
              </div>
            </div>
          </div>

          <div className="ms-wa-bundle-side card">
            <h3>{t("wa.bundleResults")}</h3>
            {!bundleResults ? (
              <div className="ms-wa-empty" style={{padding: 20}}>{t("wa.bundleNoResults")}</div>
            ) : (
              <>
                <div className="ms-wa-bundle-stats compact">
                  <div><strong>{bundleResults.sent}</strong><span>{t("wa.sent")}</span></div>
                  <div><strong>{bundleResults.failed}</strong><span>{t("wa.failed")}</span></div>
                </div>
                <div className="ms-wa-result-list scroll">
                  {(bundleResults.results || []).map((r, idx) => (
                    <div key={idx} className={"ms-wa-result-item " + (r.error ? "is-error" : "")}>
                      <div><strong>{r.name || r.phone}</strong><span>{r.phone}</span></div>
                      <em>{r.error || r.status}</em>
                    </div>
                  ))}
                </div>
              </>
            )}
          </div>
        </div>
      )}

      {activeTab === "conversations" && (
      <>
      {/* Pending appointment requests */}
      {showPending && (
        <div className="ms-wa-pending-panel">
          <div className="ms-wa-pending-header">
            <h3>{t("wa.pendingAppointments")}</h3>
            <button className="btn btn-ghost btn-sm btn-icon" onClick={() => setShowPending(false)}>
              <Icon.X size={14}/>
            </button>
          </div>
          {pendingAppts.length === 0 ? (
            <div className="ms-wa-pending-empty">{t("wa.noPending")}</div>
          ) : (
            <div className="ms-wa-pending-list">
              {pendingAppts.map(appt => (
                <div key={appt.id} className="ms-wa-pending-card">
                  <div className="ms-wa-pending-info">
                    <div className="ms-wa-pending-name">{appt.patient_name || "Patient"}</div>
                    <div className="ms-wa-pending-detail">
                      <Icon.Calendar size={13}/>
                      <span>{formatDateTime(appt.scheduled_at)}</span>
                    </div>
                    {appt.reason && (
                      <div className="ms-wa-pending-detail">
                        <Icon.Clipboard size={13}/>
                        <span>{appt.reason}</span>
                      </div>
                    )}
                    {appt.requested_doctor_text && (
                      <div className="ms-wa-pending-detail">
                        <Icon.User size={13}/>
                        <span>{appt.requested_doctor_text}</span>
                      </div>
                    )}
                  </div>
                  <div className="ms-wa-pending-actions">
                    <button className="btn btn-sm" disabled={actionLoading === appt.id}
                      onClick={() => handleAppointmentAction(appt.id, "accept")}
                      style={{background: "var(--accent-success)", borderColor: "var(--accent-success)", color: "white"}}>
                      <Icon.Check size={14}/>
                      {t("wa.accept")}
                    </button>
                    <button className="btn btn-sm" disabled={actionLoading === appt.id}
                      onClick={() => handleAppointmentAction(appt.id, "reject")}
                      style={{background: "var(--accent-danger)", borderColor: "var(--accent-danger)", color: "white"}}>
                      <Icon.X size={14}/>
                      {t("wa.reject")}
                    </button>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {/* Settings panel */}
      {showSettings && reminderSettings && (
        <div className="card" style={{ marginBottom: 16 }}>
          <div style={{padding: "14px 16px 10px", fontWeight: 600, fontSize: 14}}>{t("wa.reminderSettings")}</div>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 16, alignItems: "center", padding: "4px 16px 16px" }}>
            <label className="ms-wa-setting-label">
              <input type="checkbox" checked={reminderSettings.enabled}
                onChange={(e) => saveReminderSettings({ enabled: e.target.checked })}/>
              {t("wa.remindersEnabled")}
            </label>
            <label className="ms-wa-setting-label">
              {t("wa.hoursBefore")}
              <select className="select" value={reminderSettings.hours_before} style={{height: 30, fontSize: 12, padding: "0 8px"}}
                onChange={(e) => saveReminderSettings({ hours_before: parseInt(e.target.value) })}>
                {[1,2,4,6,12,24,48].map(h => <option key={h} value={h}>{h}h</option>)}
              </select>
            </label>
            <label className="ms-wa-setting-label">
              {t("wa.language")}
              <select className="select" value={reminderSettings.language} style={{height: 30, fontSize: 12, padding: "0 8px"}}
                onChange={(e) => saveReminderSettings({ language: e.target.value })}>
                <option value="en">English</option>
                <option value="es">Espa&ntilde;ol</option>
              </select>
            </label>
          </div>
        </div>
      )}

      <div className="ms-wa-layout">
        {/* Conversation list */}
        <div className="ms-wa-sidebar card">
          <div className="ms-wa-sidebar-head">
            <h3>{t("wa.conversations")}</h3>
            <button className="btn btn-ghost btn-sm btn-icon" onClick={loadConversations} title={t("wa.refresh")}>
              <Icon.Refresh size={14}/>
            </button>
          </div>
          <div className="ms-wa-search-wrap">
            <Icon.Search size={14}/>
            <input className="ms-wa-search" type="text" value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              placeholder={t("wa.search")}/>
          </div>
          <div className="ms-wa-conv-list scroll">
            {loadingConvs ? (
              <div className="ms-wa-empty">{t("wa.loading")}</div>
            ) : filteredConvs.length === 0 ? (
              <div className="ms-wa-empty">
                <Icon.Phone size={24}/>
                <p>{t("wa.noConversations")}</p>
              </div>
            ) : filteredConvs.map(c => (
              <div key={c.id} className={"ms-wa-conv-item" + (c.id === activeConvId ? " is-active" : "")}
                onClick={() => { setActiveConvId(c.id); setMessages([]); }}>
                <div className="avatar avatar-sm">{(c.patient_name || "?")[0].toUpperCase()}</div>
                <div className="ms-wa-conv-info">
                  <div className="ms-wa-conv-name">{c.patient_name || c.from_number || t("wa.unknown")}</div>
                  <div className="ms-wa-conv-time">{formatTime(c.last_message_at)}</div>
                </div>
                {c.state === "awaiting_booking_detail" && (
                  <span className="badge badge-warn" style={{fontSize: 10}}>{t("wa.pending")}</span>
                )}
                <button className="ms-wa-conv-delete" title={t("wa.deleteChat")}
                  onClick={(e) => { e.stopPropagation(); setDeleteConfirmId(c.id); }}>
                  <Icon.Trash size={13}/>
                </button>
              </div>
            ))}
          </div>
        </div>

        {/* Message thread */}
        <div className="ms-wa-thread card">
          {!activeConvId ? (
            <div className="ms-wa-empty" style={{ flex: 1 }}>
              <Icon.Phone size={32}/>
              <p>{t("wa.selectConversation")}</p>
            </div>
          ) : (
            <>
              <div className="ms-wa-thread-head">
                <div className="avatar avatar-sm">{((activeConv && activeConv.patient_name) || "?")[0].toUpperCase()}</div>
                <div style={{flex: 1, minWidth: 0}}>
                  <div className="ms-wa-conv-name">{(activeConv && activeConv.patient_name) || t("wa.unknown")}</div>
                  <div className="ms-wa-conv-phone">{(activeConv && activeConv.from_number) || ""}</div>
                </div>
                <div style={{display: "flex", gap: 4}}>
                  {activeConv && activeConv.patient_id && (
                    <button className="btn btn-ghost btn-sm btn-icon" title={t("wa.viewPatient")}
                      onClick={() => store.nav && store.nav("patients", activeConv.patient_id)}>
                      <Icon.User size={14}/>
                    </button>
                  )}
                  <button className="btn btn-ghost btn-sm btn-icon" title={t("wa.deleteChat")}
                    onClick={() => setDeleteConfirmId(activeConvId)}>
                    <Icon.Trash size={14}/>
                  </button>
                </div>
              </div>

              {/* Pending appointment banner inside thread */}
              {pendingAppts.filter(a => activeConv && a.patient_id === activeConv.patient_id).map(appt => (
                <div key={appt.id} className="ms-wa-inline-appt">
                  <div className="ms-wa-inline-appt-icon">
                    <Icon.Calendar size={16}/>
                  </div>
                  <div className="ms-wa-inline-appt-info">
                    <div className="ms-wa-inline-appt-title">{t("wa.appointmentRequest")}</div>
                    <div className="ms-wa-inline-appt-time">{t("wa.scheduledFor")}: {formatDateTime(appt.scheduled_at)}</div>
                  </div>
                  <div className="ms-wa-inline-appt-actions">
                    <button className="btn btn-sm" disabled={actionLoading === appt.id}
                      onClick={() => handleAppointmentAction(appt.id, "accept")}
                      style={{background: "var(--accent-success)", borderColor: "var(--accent-success)", color: "white"}}>
                      <Icon.Check size={14}/> {t("wa.accept")}
                    </button>
                    <button className="btn btn-sm" disabled={actionLoading === appt.id}
                      onClick={() => handleAppointmentAction(appt.id, "reject")}
                      style={{background: "var(--accent-danger)", borderColor: "var(--accent-danger)", color: "white"}}>
                      <Icon.X size={14}/> {t("wa.reject")}
                    </button>
                  </div>
                </div>
              ))}

              <div className="ms-wa-messages scroll">
                {loadingMsgs && messages.length === 0 ? (
                  <div className="ms-wa-empty">{t("wa.loading")}</div>
                ) : messages.length === 0 ? (
                  <div className="ms-wa-empty"><p>{t("wa.noMessages")}</p></div>
                ) : messages.map(m => (
                  <div key={m.id} className={"ms-wa-msg " + (m.direction === "outbound" ? "is-outbound" : "is-inbound")}>
                    <div className="ms-wa-msg-bubble">
                      <div className="ms-wa-msg-body">{m.body}</div>
                      <div className="ms-wa-msg-meta">
                        <span>{formatTime(m.created_at)}</span>
                        {m.direction === "outbound" && statusBadge(m.status)}
                      </div>
                    </div>
                  </div>
                ))}
                <div ref={messagesEndRef}/>
              </div>

              {/* Template picker */}
              {showTemplates && (
                <div className="ms-wa-template-panel">
                  {!selectedTemplate ? (
                    <div className="ms-wa-template-list">
                      {templates.filter(t => t.id !== "custom").map(tpl => {
                        const lang = window.MSi18n.getLang() === "es" ? "es" : "en";
                        return (
                          <button key={tpl.id} className="ms-wa-template-item" onClick={() => selectTemplate(tpl)}>
                            <div className="ms-wa-template-name">{lang === "es" ? tpl.name_es : tpl.name_en}</div>
                            <div className="ms-wa-template-preview">{(lang === "es" ? tpl.body_es : tpl.body_en).slice(0, 60)}...</div>
                          </button>
                        );
                      })}
                    </div>
                  ) : (
                    <div className="ms-wa-template-fill">
                      <div className="ms-wa-template-fill-head">
                        <button className="btn btn-ghost btn-sm" onClick={() => setSelectedTemplate(null)}>{"←"}</button>
                        <span style={{fontWeight: 600, fontSize: 13}}>{window.MSi18n.getLang() === "es" ? selectedTemplate.name_es : selectedTemplate.name_en}</span>
                      </div>
                      <div className="ms-wa-template-fill-body">
                        {selectedTemplate.variables.map(v => (
                          <label key={v} className="ms-wa-template-field">
                            <span>{t("wa.var" + v.charAt(0).toUpperCase() + v.slice(1).replace(/_([a-z])/g, (_, c) => c.toUpperCase())) || v}</span>
                            <input type="text" value={templateVars[v] || ""} placeholder={v}
                              onChange={(e) => setTemplateVars(prev => ({...prev, [v]: e.target.value}))}/>
                          </label>
                        ))}
                      </div>
                      <button className="btn btn-primary btn-sm" onClick={insertTemplate} style={{margin: "8px 12px"}}>
                        {t("wa.insertTemplate")}
                      </button>
                    </div>
                  )}
                </div>
              )}

              {/* Quick replies */}
              <div className="ms-wa-quick-replies">
                {quickReplies.map(qr => (
                  <button key={qr.key} className="ms-wa-quick-chip" onClick={() => setDraft(t("wa." + qr.key))}>
                    <qr.icon size={12}/>
                    <span>{t("wa." + qr.key)}</span>
                  </button>
                ))}
              </div>

              <div className="ms-wa-compose">
                <button className={"ms-wa-compose-action" + (showTemplates ? " is-active" : "")}
                  title={t("wa.templates")} onClick={() => { setShowTemplates(!showTemplates); setSelectedTemplate(null); }}>
                  <Icon.Clipboard size={16}/>
                </button>
                <input className="ms-wa-input" type="text" value={draft}
                  placeholder={t("wa.typePlaceholder")}
                  onChange={(e) => setDraft(e.target.value)}
                  onKeyDown={(e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); handleSend(); } }}
                  disabled={sending}/>
                <button className="btn btn-primary" onClick={handleSend} disabled={sending || !draft.trim()}>
                  {sending ? t("wa.sending") : t("wa.send")}
                </button>
              </div>
            </>
          )}
        </div>
      </div>
      </>
      )}

      {/* Delete confirmation dialog */}
      {deleteConfirmId && (
        <div className="ms-cmd-overlay" onClick={() => setDeleteConfirmId(null)}>
          <div className="ms-wa-delete-dialog slide-up" onClick={e => e.stopPropagation()}>
            <Icon.Trash size={24} style={{color: "var(--accent-danger)"}}/>
            <p style={{margin: "12px 0 4px", fontWeight: 600, fontSize: 15}}>{t("wa.deleteChat")}</p>
            <p style={{margin: 0, fontSize: 13.5, color: "var(--ink-3)"}}>{t("wa.deleteChatConfirm")}</p>
            <div style={{display: "flex", gap: 8, marginTop: 16, justifyContent: "center"}}>
              <button className="btn btn-ghost" onClick={() => setDeleteConfirmId(null)}>
                {t("wa.cancel")}
              </button>
              <button className="btn" onClick={() => handleDelete(deleteConfirmId)}
                style={{background: "var(--accent-danger)", borderColor: "var(--accent-danger)", color: "white"}}>
                <Icon.Trash size={14}/>
                {t("wa.deleteChat")}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

window.WhatsAppInbox = WhatsAppInbox;
