/* global React, Icon, useSelectedWorkspaceId, getWorkspaceSearchParams */
const {
  useEffect: useEffectIntegrations,
  useMemo: useMemoIntegrations,
  useState: useStateIntegrations,
} = React;

const INTEGRATION_DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

const DEFAULT_HUBSPOT = {
  enabled: true,
  connected: false,
  configured: false,
  clientId: '',
  clientSecret: '',
  redirectUri: '',
  hubId: '',
  connectedAt: '',
  sendTranscript: true,
  sendSummary: true,
};

const DEFAULT_GOHIGHLEVEL = {
  enabled: true,
  connected: false,
  configured: false,
  token: '',
  locationId: '',
  sendTranscript: true,
  sendSummary: true,
};

const DEFAULT_META = {
  configured: false,
  appId: '',
  appSecret: '',
  verifyToken: '',
  redirectUri: '',
  webhookUrl: '',
  requiredPermissions: [],
};

const DEFAULT_META_CHANNEL = {
  enabled: false,
  connected: false,
  status: 'disconnected',
  displayName: '',
  externalAccountId: '',
  username: '',
  lastWebhookAt: '',
  lastOutboundAt: '',
  lastError: '',
  settings: {
    showInWidget: false,
    buttonLabel: '',
    externalUrl: '',
  },
};

const DEFAULT_WHATSAPP = {
  enabled: false,
  connected: false,
  status: 'disconnected',
  businessAccountId: '',
  phoneNumberId: '',
  accessToken: '',
  appSecret: '',
  verifyToken: '',
  callbackUrl: '',
  webhookUrl: '',
  displayName: '',
  businessPhoneNumber: '',
  tokenLast4: '',
  lastWebhookAt: '',
  lastOutboundAt: '',
  lastError: '',
  templates: [],
  recentErrors: [],
  settings: {
    consentText: 'By continuing, you agree that this business may contact you about this conversation through WhatsApp.',
    defaultLeadTemplate: '',
    defaultFollowupTemplate: '',
    ownerNotificationNumber: '',
    notifyOwner: false,
  },
};

const DEFAULT_LIVE_CHAT = {
  enabled: false,
  showHandoffButton: true,
  buttonLabel: 'Talk to a human',
  availabilityMode: 'always',
  timezone: 'UTC',
  workingDays: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
  startTime: '09:00',
  endTime: '18:00',
  unavailableMessage: 'Live support is currently unavailable. Please leave your question here and the AI assistant will help you.',
  confirmationMessage: 'Your message has been added. A team member will reply here shortly.',
  dashboardNotifications: true,
};

function getTimezoneOptions() {
  try {
    if (typeof Intl !== 'undefined' && typeof Intl.supportedValuesOf === 'function') {
      const zones = Intl.supportedValuesOf('timeZone');
      return Array.from(new Set(['UTC', ...zones])).sort((a, b) => {
        if (a === 'UTC') return -1;
        if (b === 'UTC') return 1;
        return a.localeCompare(b);
      });
    }
  } catch (error) {
    // Fallback below.
  }
  return ['UTC'];
}

function IntegrationsPage() {
  const workspaceId = useSelectedWorkspaceId();
  const [templates, setTemplates] = useStateIntegrations([]);
  const [selectedBotId, setSelectedBotId] = useStateIntegrations('');
  const [loadingTemplates, setLoadingTemplates] = useStateIntegrations(true);
  const [loadingIntegration, setLoadingIntegration] = useStateIntegrations(false);
  const [busy, setBusy] = useStateIntegrations('');
  const [error, setError] = useStateIntegrations('');
  const [success, setSuccess] = useStateIntegrations('');
  const [canManage, setCanManage] = useStateIntegrations(false);
  const [openIntegration, setOpenIntegration] = useStateIntegrations('');
  const [hubspot, setHubspot] = useStateIntegrations(DEFAULT_HUBSPOT);
  const [gohighlevel, setGohighlevel] = useStateIntegrations(DEFAULT_GOHIGHLEVEL);
  const [meta, setMeta] = useStateIntegrations(DEFAULT_META);
  const [messenger, setMessenger] = useStateIntegrations(() => normalizeMetaChannel(null, 'messenger'));
  const [instagram, setInstagram] = useStateIntegrations(() => normalizeMetaChannel(null, 'instagram'));
  const [metaAccounts, setMetaAccounts] = useStateIntegrations([]);
  const [metaSessionId, setMetaSessionId] = useStateIntegrations('');
  const [selectedMetaPageId, setSelectedMetaPageId] = useStateIntegrations('');
  const [connectMessenger, setConnectMessenger] = useStateIntegrations(true);
  const [connectInstagram, setConnectInstagram] = useStateIntegrations(false);
  const [whatsapp, setWhatsapp] = useStateIntegrations(DEFAULT_WHATSAPP);
  const [whatsappTestNumber, setWhatsappTestNumber] = useStateIntegrations('');
  const [liveChat, setLiveChat] = useStateIntegrations(DEFAULT_LIVE_CHAT);

  const timezoneOptions = useMemoIntegrations(() => getTimezoneOptions(), []);
  const selectedTemplate = useMemoIntegrations(
    () => templates.find(item => item.botId === selectedBotId) || null,
    [templates, selectedBotId]
  );
  const hasTemplates = templates.length > 0;
  const integrationsLocked = !hasTemplates || !selectedBotId;
  const apiBase = selectedBotId ? `/api/embedded-bots/${encodeURIComponent(selectedBotId)}/integrations` : '';

  useEffectIntegrations(() => {
    let mounted = true;
    setLoadingTemplates(true);
    setError('');
    setSuccess('');

    fetch(`/api/embedded-bots${getWorkspaceSearchParams(workspaceId)}`, {
      credentials: 'include',
      cache: 'no-store',
    })
      .then(readIntegrationResponse)
      .then(data => {
        if (!mounted) return;
        const items = Array.isArray(data.bots) ? data.bots : [];
        setTemplates(items);
        setSelectedBotId(items[0]?.botId || '');
      })
      .catch(fetchError => {
        if (mounted) setError(fetchError.message || 'Unable to load templates.');
      })
      .finally(() => {
        if (mounted) setLoadingTemplates(false);
      });

    return () => { mounted = false; };
  }, [workspaceId]);

  useEffectIntegrations(() => {
    if (!selectedBotId) return undefined;
    let mounted = true;
    setLoadingIntegration(true);
    setError('');

    fetch(`/api/embedded-bots/${encodeURIComponent(selectedBotId)}/integrations`, {
      credentials: 'include',
      cache: 'no-store',
    })
      .then(readIntegrationResponse)
      .then(data => {
        if (!mounted) return;
        const integrations = data.integrations || {};
        setCanManage(Boolean(data.permissions?.canManage));
        setHubspot(normalizeHubspot(integrations.hubspot));
        setGohighlevel(normalizeGohighlevel(integrations.gohighlevel));
        setMeta(normalizeMeta(integrations.meta));
        setWhatsapp(normalizeWhatsapp(integrations.whatsapp));
        setMessenger(normalizeMetaChannel(integrations.messenger, 'messenger'));
        setInstagram(normalizeMetaChannel(integrations.instagram, 'instagram'));
        setLiveChat(normalizeLiveChat(integrations.liveChat));
        if (Array.isArray(data.warnings) && data.warnings.length) {
          console.warn('Optional integration diagnostics unavailable:', data.warnings);
        }
      })
      .catch(fetchError => {
        if (mounted) setError(fetchError.message || 'Unable to load integration settings.');
      })
      .finally(() => {
        if (mounted) setLoadingIntegration(false);
      });

    return () => { mounted = false; };
  }, [selectedBotId]);

  useEffectIntegrations(() => {
    if (!openIntegration) return undefined;

    const handleKeyDown = event => {
      if (event.key === 'Escape') setOpenIntegration('');
    };

    document.documentElement.classList.add('has-app-modal');
    window.addEventListener('keydown', handleKeyDown);

    return () => {
      document.documentElement.classList.remove('has-app-modal');
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [openIntegration]);

  const runAction = async (label, action) => {
    if (!apiBase) {
      setError('Create a chatbot template first, then configure integrations.');
      return null;
    }
    if (busy) return null;
    setBusy(label);
    setError('');
    setSuccess('');
    try {
      const result = await action();
      return result;
    } catch (actionError) {
      setError(actionError.message || 'Request failed.');
      return null;
    } finally {
      setBusy('');
    }
  };

  const saveHubspot = () => runAction('hubspot-save', async () => {
    const data = await sendJson(`${apiBase}/hubspot`, 'PATCH', {
      clientId: hubspot.clientId,
      clientSecret: hubspot.clientSecret,
      redirectUri: hubspot.redirectUri,
      enabled: hubspot.enabled,
      sendTranscript: hubspot.sendTranscript,
      sendSummary: hubspot.sendSummary,
    });
    setHubspot(normalizeHubspot(data.integration));
    setSuccess(data.message || 'HubSpot credentials saved successfully.');
  });

  const connectHubspot = () => runAction('hubspot-connect', async () => {
    const data = await sendJson(`${apiBase}/hubspot/start`, 'POST', {});
    if (!data.authUrl) throw new Error('HubSpot authorization URL was not returned.');
    window.open(data.authUrl, 'pluginchatbot-hubspot', 'width=760,height=820');
    setSuccess('HubSpot authorization opened. Approve access, then refresh the status.');
  });

  const refreshHubspot = () => runAction('hubspot-refresh', async () => {
    const data = await fetchJson(`${apiBase}/hubspot/status`);
    setHubspot(normalizeHubspot(data.integration));
    setSuccess('HubSpot status refreshed.');
  });

  const disconnectHubspot = () => runAction('hubspot-disconnect', async () => {
    if (!window.confirm('Disconnect HubSpot for this account? Lead sync will stop for all templates under this account.')) return;
    const data = await sendJson(`${apiBase}/hubspot/disconnect`, 'POST', {});
    setHubspot(normalizeHubspot(data.integration));
    setSuccess(data.message || 'HubSpot disconnected successfully.');
  });

  const saveGohighlevel = () => runAction('gohighlevel-save', async () => {
    const data = await sendJson(`${apiBase}/gohighlevel`, 'PATCH', {
      token: gohighlevel.token,
      locationId: gohighlevel.locationId,
      enabled: gohighlevel.enabled,
      sendTranscript: gohighlevel.sendTranscript,
      sendSummary: gohighlevel.sendSummary,
    });
    setGohighlevel(normalizeGohighlevel(data.integration));
    setSuccess(data.message || 'GoHighLevel settings saved successfully.');
  });

  const testGohighlevel = () => runAction('gohighlevel-test', async () => {
    const data = await sendJson(`${apiBase}/gohighlevel/test`, 'POST', {});
    setSuccess(data.message || 'GoHighLevel connection is working.');
  });

  const refreshGohighlevel = () => runAction('gohighlevel-refresh', async () => {
    const data = await fetchJson(`${apiBase}/gohighlevel/status`);
    setGohighlevel(normalizeGohighlevel(data.integration));
    setSuccess('GoHighLevel status refreshed.');
  });

  const disconnectGohighlevel = () => runAction('gohighlevel-disconnect', async () => {
    if (!window.confirm('Disconnect GoHighLevel for this account? Lead sync will stop for all templates under this account.')) return;
    const data = await sendJson(`${apiBase}/gohighlevel/disconnect`, 'POST', {});
    setGohighlevel(normalizeGohighlevel(data.integration));
    setSuccess(data.message || 'GoHighLevel disconnected successfully.');
  });

  const startMetaConnection = () => runAction('meta-start', async () => {
    const data = await sendJson(`${apiBase}/meta/start`, 'POST', {
      appId: meta.appId,
      appSecret: meta.appSecret,
      verifyToken: meta.verifyToken,
      redirectUri: meta.redirectUri,
      channels: selectedMetaChannels(connectMessenger, connectInstagram),
    });
    setMeta(normalizeMeta({ ...meta, ...(data.appConfig || {}) }));
    if (!data.authorizationUrl) throw new Error('Meta authorization URL was not returned.');
    window.open(data.authorizationUrl, 'pluginchatbot-meta', 'width=760,height=820');
    setSuccess('Meta authorization opened. Approve access, then load authorized Pages.');
  });

  const loadMetaAccounts = () => runAction('meta-accounts', async () => {
    const data = await fetchJson(`${apiBase}/meta/accounts`);
    const accounts = Array.isArray(data.accounts) ? data.accounts : [];
    setMetaSessionId(data.session?.sessionId || '');
    setMetaAccounts(accounts);
    setSelectedMetaPageId(accounts[0]?.pageId || '');
    setConnectMessenger(true);
    setConnectInstagram(Boolean(accounts[0]?.instagram));
    setSuccess(accounts.length ? 'Meta Pages loaded. Select a Page and connect channels.' : 'No authorized Pages found yet.');
  });

  const connectSelectedMetaChannels = () => runAction('meta-connect', async () => {
    const channels = selectedMetaChannels(connectMessenger, connectInstagram);
    const account = metaAccounts.find(item => item.pageId === selectedMetaPageId);
    if (!metaSessionId || !account) throw new Error('Authorize Meta and select a Facebook Page first.');
    if (channels.includes('instagram') && !account.instagram) {
      throw new Error('The selected Facebook Page has no linked Instagram Professional account.');
    }

    const data = await sendJson(`${apiBase}/meta/connect`, 'POST', {
      sessionId: metaSessionId,
      pageId: selectedMetaPageId,
      channels,
    });
    if (data.integrations?.messenger) setMessenger(normalizeMetaChannel(data.integrations.messenger, 'messenger'));
    if (data.integrations?.instagram) setInstagram(normalizeMetaChannel(data.integrations.instagram, 'instagram'));
    setMetaAccounts([]);
    setMetaSessionId('');
    setSelectedMetaPageId('');
    setSuccess(data.message || 'Meta channels connected successfully.');
  });

  const updateMetaChannelSettings = (channelType, key, value) => {
    const setter = channelType === 'instagram' ? setInstagram : setMessenger;
    setter(current => ({ ...current, settings: { ...current.settings, [key]: value } }));
    setError('');
    setSuccess('');
  };

  const saveMetaChannel = channelType => runAction(`${channelType}-save`, async () => {
    const current = channelType === 'instagram' ? instagram : messenger;
    const data = await sendJson(`${apiBase}/${channelType}`, 'PATCH', {
      settings: {
        showInWidget: current.settings?.showInWidget !== false,
        buttonLabel: current.settings?.buttonLabel || '',
        externalUrl: current.settings?.externalUrl || '',
      },
    });
    const setter = channelType === 'instagram' ? setInstagram : setMessenger;
    setter(normalizeMetaChannel(data.integration, channelType));
    setSuccess(data.message || `${formatChannelName(channelType)} settings saved.`);
  });

  const testMetaChannel = channelType => runAction(`${channelType}-test`, async () => {
    await sendJson(`${apiBase}/${channelType}/test`, 'POST', {});
    setSuccess(`${formatChannelName(channelType)} connection is working.`);
  });

  const refreshMetaChannel = channelType => runAction(`${channelType}-status`, async () => {
    const data = await fetchJson(`${apiBase}/${channelType}/status`);
    const diagnostics = data.diagnostics || {};
    const setter = channelType === 'instagram' ? setInstagram : setMessenger;
    setter(current => normalizeMetaChannel({
      ...current,
      ...(diagnostics.channel || {}),
      connected: Boolean(diagnostics.connected),
      recentErrors: diagnostics.recentErrors || [],
    }, channelType));
    setSuccess(`${formatChannelName(channelType)} status refreshed.`);
  });

  const disconnectMetaChannel = channelType => runAction(`${channelType}-disconnect`, async () => {
    if (!window.confirm(`Disconnect ${formatChannelName(channelType)} for this account?`)) return;
    await sendJson(`${apiBase}/${channelType}/disconnect`, 'POST', {});
    if (channelType === 'instagram') setInstagram(normalizeMetaChannel(null, 'instagram'));
    else setMessenger(normalizeMetaChannel(null, 'messenger'));
    setSuccess(`${formatChannelName(channelType)} disconnected.`);
  });

  const connectWhatsapp = () => runAction('whatsapp-connect', async () => {
    const data = await sendJson(`${apiBase}/whatsapp/connect`, 'POST', {
      businessAccountId: whatsapp.businessAccountId,
      phoneNumberId: whatsapp.phoneNumberId,
      accessToken: whatsapp.accessToken,
      appSecret: whatsapp.appSecret,
      verifyToken: whatsapp.verifyToken,
      settings: whatsapp.settings,
    });
    setWhatsapp(normalizeWhatsapp(data.integration));
    setSuccess(data.message || 'WhatsApp connected successfully.');
  });

  const saveWhatsapp = () => runAction('whatsapp-save', async () => {
    const data = await sendJson(`${apiBase}/whatsapp`, 'PATCH', { settings: whatsapp.settings });
    setWhatsapp(current => normalizeWhatsapp({ ...current, ...(data.integration || {}) }));
    setSuccess(data.message || 'WhatsApp settings saved successfully.');
  });

  const disconnectWhatsapp = () => runAction('whatsapp-disconnect', async () => {
    if (!window.confirm('Disconnect WhatsApp for this account?')) return;
    await sendJson(`${apiBase}/whatsapp/disconnect`, 'POST', {});
    setWhatsapp(normalizeWhatsapp(null));
    setSuccess('WhatsApp disconnected.');
  });

  const testWhatsapp = () => runAction('whatsapp-test', async () => {
    await sendJson(`${apiBase}/whatsapp/test`, 'POST', {});
    setSuccess('WhatsApp API connection is working.');
  });

  const sendWhatsappTest = () => runAction('whatsapp-message', async () => {
    if (!whatsappTestNumber.trim()) throw new Error('Enter the recipient WhatsApp number with country code.');
    await sendJson(`${apiBase}/whatsapp/test-message`, 'POST', {
      recipient: whatsappTestNumber,
      message: 'PluginChatBot WhatsApp connection test.',
    });
    setSuccess('WhatsApp test message sent.');
  });

  const saveLiveChat = () => runAction('live-chat-save', async () => {
    const data = await sendJson(`${apiBase}/live-chat`, 'PATCH', liveChat);
    setLiveChat(normalizeLiveChat(data.integration));
    setSuccess(data.message || 'Live chat settings saved successfully.');
  });

  const toggleLiveChatListValue = (key, value) => {
    setLiveChat(current => {
      const selected = Array.isArray(current[key]) ? current[key] : [];
      return {
        ...current,
        [key]: selected.includes(value)
          ? selected.filter(item => item !== value)
          : [...selected, value],
      };
    });
    setError('');
    setSuccess('');
  };

  const toggleIntegrationPanel = panelKey => {
    if (integrationsLocked) return;
    setError('');
    setSuccess('');
    setOpenIntegration(current => current === panelKey ? '' : panelKey);
  };

  return (
    <div className="view">
      <div className="view-head">
        <div>
          <h1>Integrations</h1>
          <div className="sub">Connect your CRM and messaging channels once, then use them across every chatbot in this account.</div>
        </div>
      </div>

      {error && (
        <div className="embedded-api-feedback is-error app-page-feedback">
          <strong>Something went wrong</strong>
          <span>{error}</span>
        </div>
      )}

      {success && (
        <div className="embedded-api-feedback is-success app-page-feedback">
          <strong>Saved</strong>
          <span>{success}</span>
        </div>
      )}

      {loadingTemplates ? (
        <div className="card app-empty-state">Loading integrations…</div>
      ) : (
        <>
          {integrationsLocked && (
            <div className="card app-empty-state integration-template-warning">
              <div className="app-empty-icon"><Icon name="link" size={22}/></div>
              <h2>No chatbot templates yet</h2>
              <p>Create a chatbot template first. After that, you can connect the account tools that every chatbot will use.</p>
              <div className="app-empty-actions">
                <a className="btn btn-primary" href="/ai-builder">Start setup</a>
                <a className="btn btn-secondary" href="/templates">View templates</a>
              </div>
            </div>
          )}

          <div className={`integration-layout ${integrationsLocked ? 'is-disabled' : ''}`}>
            <div className="card embedded-settings-card integration-template-card">
              <div className="embedded-settings-head">
                <span className="icon-chip"><Icon name="bot" size={20}/></span>
                <h3>Account-wide integrations</h3>
              </div>

              <div className="embedded-api-feedback integration-scope-note" style={{marginBottom: 14}}>
                <strong>Connect once, use everywhere</strong>
                <span>Set up HubSpot, Meta and WhatsApp one time for this account. Every chatbot uses the same connected business tools, so leads, messages and support conversations stay in one place.</span>
              </div>

              <div className="app-template-overview">
                <IntegrationOverviewItem label="Works with" value="Every chatbot in this account" />
                <IntegrationOverviewItem label="Main benefit" value="One setup for all customer conversations" />
              </div>

              <small className="integration-scope-helper" style={{display:'block', marginTop:12}}>Changing an integration here updates it for all chatbot templates in this account.</small>
            </div>

            <div className="integration-panel-stack">
              <IntegrationPanel
                panelKey="liveChat"
                icon="messagesSquare"
                title="Live Chat & Channels"
                description="Let visitors ask for a human and continue the conversation in your inbox"
                status={integrationsLocked ? 'Template required' : (liveChat.enabled ? 'Enabled' : 'Disabled')}
                statusClass={integrationsLocked ? 'dim' : (liveChat.enabled ? 'ok' : 'dim')}
                disabled={integrationsLocked}
                isOpen={openIntegration === 'liveChat'}
                onToggle={toggleIntegrationPanel}
                error={error}
                success={success}
              >
                <div className="card embedded-settings-card live-chat-settings-card">
                  <div className="embedded-settings-head">
                    <span className="icon-chip"><Icon name="messageCircle" size={20}/></span>
                    <h3>Live Chat &amp; Channels</h3>
                    <span className={`pill ${liveChat.enabled ? 'ok' : 'dim'}`} style={{marginLeft:'auto'}}>{liveChat.enabled ? 'Enabled' : 'Disabled'}</span>
                  </div>

                  {loadingIntegration ? (
                    <div className="app-empty-state" style={{padding:18}}>Loading live chat settings…</div>
                  ) : (
                    <>
                      {!canManage && <ReadOnlyNotice />}
                      <IntegrationToggleRow
                        title="Enable Live Chat"
                        description="Let visitors request a human and continue the conversation in the PluginChatBot inbox."
                        checked={liveChat.enabled}
                        disabled={!canManage || Boolean(busy)}
                        onToggle={() => setLiveChat(current => ({ ...current, enabled: !current.enabled }))}
                      />
                      <IntegrationToggleRow
                        title="Show Talk to a Human Button"
                        description="Display a small dismissible handoff button inside the website widget."
                        checked={liveChat.showHandoffButton}
                        disabled={!canManage || Boolean(busy)}
                        onToggle={() => setLiveChat(current => ({ ...current, showHandoffButton: !current.showHandoffButton }))}
                      />
                      <IntegrationField label="Button Label">
                        <input className="embedded-input" value={liveChat.buttonLabel} disabled={!canManage || Boolean(busy)} onChange={event => setLiveChat({ ...liveChat, buttonLabel: event.target.value })} />
                      </IntegrationField>
                      <IntegrationField label="Availability">
                        <select className="embedded-input" value={liveChat.availabilityMode} disabled={!canManage || Boolean(busy)} onChange={event => setLiveChat({ ...liveChat, availabilityMode: event.target.value })}>
                          <option value="always">Available all time</option>
                          <option value="business_hours">Use business hours</option>
                        </select>
                      </IntegrationField>
                      {liveChat.availabilityMode === 'business_hours' && (
                        <>
                          <div className="live-settings-grid">
                            <IntegrationField label="Timezone"><select className="embedded-input" value={liveChat.timezone || 'UTC'} disabled={!canManage || Boolean(busy)} onChange={event => setLiveChat({ ...liveChat, timezone: event.target.value })}>{timezoneOptions.map(timezone => <option key={timezone} value={timezone}>{timezone}</option>)}</select></IntegrationField>
                            <IntegrationField label="Start Time"><input className="embedded-input" type="time" value={liveChat.startTime} disabled={!canManage || Boolean(busy)} onChange={event => setLiveChat({ ...liveChat, startTime: event.target.value })}/></IntegrationField>
                            <IntegrationField label="End Time"><input className="embedded-input" type="time" value={liveChat.endTime} disabled={!canManage || Boolean(busy)} onChange={event => setLiveChat({ ...liveChat, endTime: event.target.value })}/></IntegrationField>
                          </div>
                          <div className="embedded-form-row">
                            <span>Working Days</span>
                            <div className="live-settings-options">
                              {INTEGRATION_DAYS.map(day => (
                                <label key={day}>
                                  <input type="checkbox" checked={(liveChat.workingDays || []).includes(day)} disabled={!canManage || Boolean(busy)} onChange={() => toggleLiveChatListValue('workingDays', day)} />
                                  {day}
                                </label>
                              ))}
                            </div>
                          </div>
                        </>
                      )}
                      <IntegrationField label="Unavailable Message"><textarea className="embedded-input" rows="3" maxLength="600" value={liveChat.unavailableMessage} disabled={!canManage || Boolean(busy)} onChange={event => setLiveChat({ ...liveChat, unavailableMessage: event.target.value })}/></IntegrationField>
                      <IntegrationField label="Handoff Confirmation Message"><textarea className="embedded-input" rows="3" maxLength="600" value={liveChat.confirmationMessage} disabled={!canManage || Boolean(busy)} onChange={event => setLiveChat({ ...liveChat, confirmationMessage: event.target.value })}/><small>This message is shown once when the visitor starts human support.</small></IntegrationField>
                      <IntegrationToggleRow
                        title="Dashboard Notifications"
                        description="Notify workspace members when a visitor requests human support."
                        checked={liveChat.dashboardNotifications}
                        disabled={!canManage || Boolean(busy)}
                        onToggle={() => setLiveChat(current => ({ ...current, dashboardNotifications: !current.dashboardNotifications }))}
                      />
                      <div style={{display:'flex', justifyContent:'flex-end', marginTop:12}}>
                        <button className="btn btn-primary" type="button" onClick={saveLiveChat} disabled={!canManage || Boolean(busy)}>{busy === 'live-chat-save' ? 'Saving…' : 'Save Live Chat'}</button>
                      </div>
                    </>
                  )}
                </div>
              </IntegrationPanel>

              <IntegrationPanel
                panelKey="whatsapp"
                icon="phone"
                title="WhatsApp Integration"
                description="Connect your WhatsApp Business number for customer messages and inbox replies"
                status={integrationsLocked ? 'Template required' : (whatsapp.connected ? 'Connected' : 'Not connected')}
                statusClass={integrationsLocked ? 'dim' : (whatsapp.connected ? 'ok' : 'dim')}
                disabled={integrationsLocked}
                isOpen={openIntegration === 'whatsapp'}
                onToggle={toggleIntegrationPanel}
                error={error}
                success={success}
              >
                <div className="card embedded-settings-card">
                  <div className="embedded-settings-head">
                    <span className="icon-chip"><Icon name="phone" size={20}/></span>
                    <h3>WhatsApp Business Platform</h3>
                    <span className={`pill ${whatsapp.connected ? 'ok' : 'dim'}`} style={{marginLeft:'auto'}}>{whatsapp.connected ? 'Connected' : 'Not connected'}</span>
                  </div>
                  {loadingIntegration ? (
                    <div className="app-empty-state" style={{padding:18}}>Loading WhatsApp settings…</div>
                  ) : (
                    <>
                      {!canManage && <ReadOnlyNotice />}
                      <div className="integration-business-note" style={{padding:'12px 14px', border:'1px solid var(--pc-border)', borderRadius:12, marginBottom:14, color:'var(--pc-text-muted)', fontSize:13, lineHeight:1.6}}>
                        <strong style={{color:'var(--pc-text)'}}>WhatsApp setup:</strong> enter the details from your Meta dashboard. The webhook URL is unique to this account.
                      </div>
                      <div style={{display:'grid', gap:12}}>
                        <IntegrationField label="WhatsApp Business Account ID"><input className="embedded-input" value={whatsapp.businessAccountId} placeholder="ex: 1234567890" disabled={!canManage || Boolean(busy)} onChange={event => setWhatsapp({ ...whatsapp, businessAccountId: event.target.value.replace(/\D/g, '') })}/></IntegrationField>
                        <IntegrationField label="Phone Number ID"><input className="embedded-input" value={whatsapp.phoneNumberId} placeholder="ex: 1234567890" disabled={!canManage || Boolean(busy)} onChange={event => setWhatsapp({ ...whatsapp, phoneNumberId: event.target.value.replace(/\D/g, '') })}/></IntegrationField>
                        <IntegrationField label="Permanent Access Token"><input className="embedded-input" type="password" value={whatsapp.accessToken} placeholder={whatsapp.connected ? 'Enter again only when reconnecting' : 'ex: EAAB...'} autoComplete="new-password" disabled={!canManage || Boolean(busy)} onChange={event => setWhatsapp({ ...whatsapp, accessToken: event.target.value })}/><small>For security, this value is saved safely and will not be shown again.</small></IntegrationField>
                        <IntegrationField label="Meta App Secret"><input className="embedded-input" type="password" value={whatsapp.appSecret} placeholder={whatsapp.connected ? 'Enter again only when reconnecting' : 'From the customer Meta app'} autoComplete="new-password" disabled={!canManage || Boolean(busy)} onChange={event => setWhatsapp({ ...whatsapp, appSecret: event.target.value })}/></IntegrationField>
                        <IntegrationField label="Webhook Verify Token"><input className="embedded-input" type="password" value={whatsapp.verifyToken} placeholder={whatsapp.connected ? 'Enter again only when reconnecting' : 'Create a strong verify token'} autoComplete="new-password" disabled={!canManage || Boolean(busy)} onChange={event => setWhatsapp({ ...whatsapp, verifyToken: event.target.value })}/></IntegrationField>
                        <CopyInput label="Webhook Callback URL" value={whatsapp.webhookUrl || whatsapp.callbackUrl} empty="Generated after connecting WhatsApp" onCopy={message => setSuccess(message)} />
                        <IntegrationField label="Consent Text"><textarea className="embedded-input" rows="3" value={whatsapp.settings.consentText} disabled={!canManage || Boolean(busy)} onChange={event => setWhatsapp({ ...whatsapp, settings: { ...whatsapp.settings, consentText: event.target.value } })}/></IntegrationField>
                      </div>

                      {whatsapp.connected && (
                        <div className="app-template-overview" style={{margin:'14px 0'}}>
                          <IntegrationOverviewItem label="Business" value={whatsapp.displayName || 'WhatsApp Business'} />
                          <IntegrationOverviewItem label="Connection" value={`${whatsapp.status || 'connected'} · token ••••${whatsapp.tokenLast4 || '—'}`} />
                        </div>
                      )}

                      {(whatsapp.lastWebhookAt || whatsapp.lastOutboundAt || whatsapp.lastError) && (
                        <div style={{padding:'12px 14px', border:'1px solid var(--pc-border)', borderRadius:12, marginTop:14, fontSize:12, lineHeight:1.7}}>
                          <div><strong>Last webhook:</strong> {whatsapp.lastWebhookAt || 'Not received yet'}</div>
                          <div><strong>Last outbound:</strong> {whatsapp.lastOutboundAt || 'Not sent yet'}</div>
                          {whatsapp.lastError && <div style={{color:'var(--pc-danger)'}}><strong>Last error:</strong> {whatsapp.lastError}</div>}
                        </div>
                      )}

                      <div style={{display:'flex', flexWrap:'wrap', justifyContent:'flex-end', gap:8, marginTop:16}}>
                        <button className="btn btn-primary" type="button" onClick={connectWhatsapp} disabled={!canManage || Boolean(busy)}>{busy === 'whatsapp-connect' ? 'Connecting…' : whatsapp.connected ? 'Reconnect WhatsApp' : 'Connect WhatsApp'}</button>
                        <button className="btn btn-ghost" type="button" onClick={testWhatsapp} disabled={!canManage || Boolean(busy) || !whatsapp.connected}>Test API</button>
                        <button className="btn btn-ghost" type="button" onClick={saveWhatsapp} disabled={!canManage || Boolean(busy) || !whatsapp.connected}>Save Settings</button>
                        {whatsapp.connected && <button className="btn btn-danger" type="button" onClick={disconnectWhatsapp} disabled={!canManage || Boolean(busy)}>Disconnect</button>}
                      </div>

                      {whatsapp.connected && (
                        <div style={{borderTop:'1px solid var(--pc-border)', paddingTop:14, marginTop:16}}>
                          <strong style={{display:'block', marginBottom:8}}>Send a test message</strong>
                          <div style={{display:'grid', gridTemplateColumns:'minmax(0,1fr) auto', gap:8}}>
                            <input className="embedded-input" type="tel" value={whatsappTestNumber} placeholder="+61400000000" onChange={event => setWhatsappTestNumber(event.target.value)} disabled={!canManage || Boolean(busy)}/>
                            <button className="btn btn-ghost" type="button" onClick={sendWhatsappTest} disabled={!canManage || Boolean(busy) || !whatsappTestNumber}>Send test</button>
                          </div>
                        </div>
                      )}
                    </>
                  )}
                </div>
              </IntegrationPanel>

              <IntegrationPanel
                panelKey="metaChannels"
                icon="messagesSquare"
                title="Messenger & Instagram"
                description="Connect your Facebook Page and Instagram account for customer conversations"
                status={integrationsLocked ? 'Template required' : (messenger.connected || instagram.connected ? 'Connected' : meta.configured ? 'Configured' : 'Not connected')}
                statusClass={integrationsLocked ? 'dim' : (messenger.connected || instagram.connected ? 'ok' : meta.configured ? 'warn' : 'dim')}
                disabled={integrationsLocked}
                isOpen={openIntegration === 'metaChannels'}
                onToggle={toggleIntegrationPanel}
                error={error}
                success={success}
              >
                <div className="card embedded-settings-card">
                  <div className="embedded-settings-head">
                    <span className="icon-chip"><Icon name="messagesSquare" size={20}/></span>
                    <h3>Meta Messaging</h3>
                    <span className={`pill ${messenger.connected || instagram.connected ? 'ok' : 'dim'}`} style={{marginLeft:'auto'}}>{messenger.connected || instagram.connected ? 'Connected' : 'Not connected'}</span>
                  </div>
                  {loadingIntegration ? (
                    <div className="app-empty-state" style={{padding:18}}>Loading Meta channels…</div>
                  ) : (
                    <>
                      {!canManage && <ReadOnlyNotice />}
                      <p className="integration-helper-copy" style={{margin:'0 0 14px', color:'var(--pc-text-muted)', fontSize:13, lineHeight:1.6}}>Enter your Meta app details, authorize Facebook, then choose the Page and Instagram account you want to connect.</p>
                      <div style={{display:'grid', gap:12, marginBottom:14}}>
                        <IntegrationField label="Meta App ID"><input className="embedded-input" value={meta.appId} placeholder="Meta App ID" disabled={!canManage || Boolean(busy)} onChange={event => setMeta({ ...meta, appId: event.target.value })}/></IntegrationField>
                        <IntegrationField label="Meta App Secret"><input className="embedded-input" type="password" value={meta.appSecret} placeholder={meta.configured ? 'Leave blank to keep existing secret' : 'From the customer Meta app'} autoComplete="new-password" disabled={!canManage || Boolean(busy)} onChange={event => setMeta({ ...meta, appSecret: event.target.value })}/></IntegrationField>
                        <IntegrationField label="Webhook Verify Token"><input className="embedded-input" type="password" value={meta.verifyToken} placeholder={meta.configured ? 'Leave blank to keep existing token' : 'Create a strong verify token'} autoComplete="new-password" disabled={!canManage || Boolean(busy)} onChange={event => setMeta({ ...meta, verifyToken: event.target.value })}/></IntegrationField>
                        <IntegrationField label="OAuth Redirect URI"><input className="embedded-input" value={meta.redirectUri} placeholder={`${window.location.origin}/api/integrations/meta/callback`} disabled={!canManage || Boolean(busy)} onChange={event => setMeta({ ...meta, redirectUri: event.target.value })}/></IntegrationField>
                        <CopyInput label="Webhook Callback URL" value={meta.webhookUrl} empty="Generated after saving Meta credentials" onCopy={message => setSuccess(message)} />
                      </div>
                      <div style={{display:'flex', flexWrap:'wrap', gap:16, margin:'0 0 14px'}}>
                        <label><input type="checkbox" checked={connectMessenger} disabled={!canManage || Boolean(busy)} onChange={event => setConnectMessenger(event.target.checked)}/> Connect Messenger</label>
                        <label><input type="checkbox" checked={connectInstagram} disabled={!canManage || Boolean(busy)} onChange={event => setConnectInstagram(event.target.checked)}/> Connect Instagram</label>
                      </div>
                      <div style={{display:'flex', flexWrap:'wrap', gap:8, marginBottom:14}}>
                        <button className="btn btn-primary" type="button" onClick={startMetaConnection} disabled={!canManage || Boolean(busy)}>{busy === 'meta-start' ? 'Opening…' : 'Save & Authorize Meta'}</button>
                        <button className="btn btn-ghost" type="button" onClick={loadMetaAccounts} disabled={!canManage || Boolean(busy)}>{busy === 'meta-accounts' ? 'Loading…' : 'Load Authorized Pages'}</button>
                      </div>
                      {metaAccounts.length > 0 && (
                        <div style={{border:'1px solid var(--pc-border)', borderRadius:14, padding:14, marginBottom:16}}>
                          <IntegrationField label="Facebook Page">
                            <select className="embedded-input" value={selectedMetaPageId} onChange={event => {
                              const pageId = event.target.value;
                              const account = metaAccounts.find(item => item.pageId === pageId);
                              setSelectedMetaPageId(pageId);
                              setConnectInstagram(Boolean(account?.instagram));
                            }} disabled={Boolean(busy)}>
                              {metaAccounts.map(account => (
                                <option key={account.pageId} value={account.pageId}>{account.pageName}{account.instagram ? ` · @${account.instagram.username || 'Instagram linked'}` : ' · No Instagram linked'}</option>
                              ))}
                            </select>
                          </IntegrationField>
                          <button className="btn btn-primary" type="button" onClick={connectSelectedMetaChannels} disabled={!canManage || Boolean(busy) || !metaSessionId || !selectedMetaPageId}>{busy === 'meta-connect' ? 'Connecting…' : 'Connect Selected Channels'}</button>
                        </div>
                      )}
                      <MetaChannelCard channelType="messenger" channel={messenger} canManage={canManage} busy={busy} onUpdateSettings={updateMetaChannelSettings} onSave={saveMetaChannel} onTest={testMetaChannel} onRefresh={refreshMetaChannel} onDisconnect={disconnectMetaChannel} />
                      <MetaChannelCard channelType="instagram" channel={instagram} canManage={canManage} busy={busy} onUpdateSettings={updateMetaChannelSettings} onSave={saveMetaChannel} onTest={testMetaChannel} onRefresh={refreshMetaChannel} onDisconnect={disconnectMetaChannel} />
                      <details style={{marginTop:14}}>
                        <summary style={{cursor:'pointer', fontWeight:700}}>Advanced details</summary>
                        <div style={{display:'grid', gap:10, marginTop:12}}>
                          <small>Permissions: {(meta.requiredPermissions || []).join(', ') || 'Not loaded'}</small>
                          <small>Private app details are saved safely and are not shown again.</small>
                        </div>
                      </details>
                    </>
                  )}
                </div>
              </IntegrationPanel>

              <IntegrationPanel
                panelKey="hubspot"
                icon="contact"
                title="HubSpot Integration"
                description="Connect your HubSpot account to sync leads from every chatbot"
                status={integrationsLocked ? 'Template required' : (hubspot.connected ? 'Connected' : hubspot.configured ? 'Configured' : 'Not connected')}
                statusClass={integrationsLocked ? 'dim' : (hubspot.connected ? 'ok' : hubspot.configured ? 'warn' : 'dim')}
                disabled={integrationsLocked}
                isOpen={openIntegration === 'hubspot'}
                onToggle={toggleIntegrationPanel}
                error={error}
                success={success}
              >
                <div className="card embedded-settings-card">
                  <div className="embedded-settings-head">
                    <span className="icon-chip" style={{background:'rgba(255, 122, 89, 0.16)', borderColor:'rgba(255, 122, 89, 0.45)', color:'#ff7a59'}}><Icon name="contact" size={20}/></span>
                    <h3>HubSpot Integration</h3>
                    <span className={`pill ${hubspot.connected ? 'ok' : 'dim'}`} style={{marginLeft:'auto'}}>{hubspot.connected ? 'Connected' : 'Not connected'}</span>
                  </div>
                  {loadingIntegration ? (
                    <div className="app-empty-state" style={{padding:18}}>Loading HubSpot connection…</div>
                  ) : (
                    <>
                      {!canManage && <ReadOnlyNotice />}
                      <p className="integration-helper-copy" style={{margin:'0 0 14px', color:'var(--pc-text-muted)', fontSize:13, lineHeight:1.6}}>Enter your HubSpot app details and connect the account. Leads captured by any chatbot will sync to this HubSpot account.</p>
                      <div style={{display:'grid', gap:12, marginBottom:14}}>
                        <IntegrationField label="Client ID"><input className="embedded-input" value={hubspot.clientId} placeholder="HubSpot app Client ID" disabled={!canManage || Boolean(busy)} onChange={event => setHubspot({ ...hubspot, clientId: event.target.value })}/></IntegrationField>
                        <IntegrationField label="Client Secret"><input className="embedded-input" type="password" value={hubspot.clientSecret} placeholder={hubspot.configured ? 'Leave blank to keep existing secret' : 'HubSpot app Client Secret'} autoComplete="new-password" disabled={!canManage || Boolean(busy)} onChange={event => setHubspot({ ...hubspot, clientSecret: event.target.value })}/><small>For security, this value is saved safely and will not be shown again.</small></IntegrationField>
                        <IntegrationField label="Redirect URI"><input className="embedded-input" value={hubspot.redirectUri} placeholder={`${window.location.origin}/api/integrations/hubspot/callback`} disabled={!canManage || Boolean(busy)} onChange={event => setHubspot({ ...hubspot, redirectUri: event.target.value })}/></IntegrationField>
                        <IntegrationToggleRow title="Enable HubSpot Sync" description="Sync captured leads to HubSpot." checked={hubspot.enabled} disabled={!canManage || Boolean(busy)} onToggle={() => setHubspot(current => ({ ...current, enabled: !current.enabled }))}/>
                        <IntegrationToggleRow title="Send Transcript Notes" description="Add chat transcript notes to synced HubSpot contacts." checked={hubspot.sendTranscript} disabled={!canManage || Boolean(busy)} onToggle={() => setHubspot(current => ({ ...current, sendTranscript: !current.sendTranscript }))}/>
                        <IntegrationToggleRow title="Send AI Summary Notes" description="Add AI summary notes to synced HubSpot contacts." checked={hubspot.sendSummary} disabled={!canManage || Boolean(busy)} onToggle={() => setHubspot(current => ({ ...current, sendSummary: !current.sendSummary }))}/>
                      </div>
                      {hubspot.connected ? (
                        <div className="app-template-overview" style={{marginBottom:14}}>
                          <IntegrationOverviewItem label="Hub ID" value={hubspot.hubId || 'Connected'} />
                          <IntegrationOverviewItem label="Connected At" value={formatIntegrationDate(hubspot.connectedAt)} />
                        </div>
                      ) : (
                        <div style={{padding:'14px 16px', border:'1px solid rgba(255, 122, 89, 0.35)', borderRadius:14, background:'rgba(255, 122, 89, 0.08)', color:'var(--pc-text-muted)', fontSize:13, marginBottom:14}}>HubSpot is not connected yet. Save the app details, then click Connect HubSpot and approve access.</div>
                      )}
                      <div style={{display:'flex', flexWrap:'wrap', justifyContent:'flex-end', gap:12, marginTop:16}}>
                        <button className="btn btn-secondary" type="button" onClick={saveHubspot} disabled={!canManage || Boolean(busy)}>{busy === 'hubspot-save' ? 'Saving…' : 'Save Credentials'}</button>
                        <button className="btn btn-primary" type="button" onClick={connectHubspot} disabled={!canManage || Boolean(busy) || !hubspot.configured}>{busy === 'hubspot-connect' ? 'Opening…' : hubspot.connected ? 'Reconnect HubSpot' : 'Connect HubSpot'}</button>
                        <button className="btn btn-secondary" type="button" onClick={refreshHubspot} disabled={Boolean(busy)}>{busy === 'hubspot-refresh' ? 'Checking…' : 'Refresh Status'}</button>
                        {hubspot.connected && <button className="btn btn-danger" type="button" onClick={disconnectHubspot} disabled={!canManage || Boolean(busy)}>Disconnect</button>}
                      </div>
                    </>
                  )}
                </div>
              </IntegrationPanel>

              {/* GoHighLevel card hidden from UI — company has no paid GHL account yet. Backend/functionality kept intact; flip to `true` to show again. */}
              {false && (
              <IntegrationPanel
                panelKey="gohighlevel"
                icon="contact"
                title="GoHighLevel Integration"
                description="Sync leads from every chatbot to your GoHighLevel account"
                status={integrationsLocked ? 'Template required' : (gohighlevel.connected ? 'Connected' : gohighlevel.configured ? 'Configured' : 'Not connected')}
                statusClass={integrationsLocked ? 'dim' : (gohighlevel.connected ? 'ok' : gohighlevel.configured ? 'warn' : 'dim')}
                disabled={integrationsLocked}
                isOpen={openIntegration === 'gohighlevel'}
                onToggle={toggleIntegrationPanel}
                error={error}
                success={success}
              >
                <div className="card embedded-settings-card">
                  <div className="embedded-settings-head">
                    <span className="icon-chip" style={{background:'rgba(45, 212, 191, 0.16)', borderColor:'rgba(45, 212, 191, 0.45)', color:'#0d9488'}}><Icon name="contact" size={20}/></span>
                    <h3>GoHighLevel Integration</h3>
                    <span className={`pill ${gohighlevel.connected ? 'ok' : 'dim'}`} style={{marginLeft:'auto'}}>{gohighlevel.connected ? 'Connected' : 'Not connected'}</span>
                  </div>
                  {loadingIntegration ? (
                    <div className="app-empty-state" style={{padding:18}}>Loading GoHighLevel connection…</div>
                  ) : (
                    <>
                      {!canManage && <ReadOnlyNotice />}
                      <p className="integration-helper-copy" style={{margin:'0 0 14px', color:'var(--pc-text-muted)', fontSize:13, lineHeight:1.6}}>Paste a GoHighLevel Private Integration Token and your Location ID. Leads captured by any chatbot will sync to this GoHighLevel account.</p>
                      <div style={{display:'grid', gap:12, marginBottom:14}}>
                        <IntegrationField label="Private Integration Token"><input className="embedded-input" type="password" value={gohighlevel.token} placeholder={gohighlevel.configured ? 'Leave blank to keep existing token' : 'GoHighLevel Private Integration Token'} autoComplete="new-password" disabled={!canManage || Boolean(busy)} onChange={event => setGohighlevel({ ...gohighlevel, token: event.target.value })}/><small>Create it in GoHighLevel → Settings → Private Integrations (with contacts read/write scopes). Saved securely and never shown again.</small></IntegrationField>
                        <IntegrationField label="Location ID"><input className="embedded-input" value={gohighlevel.locationId} placeholder="GoHighLevel Location ID" disabled={!canManage || Boolean(busy)} onChange={event => setGohighlevel({ ...gohighlevel, locationId: event.target.value })}/></IntegrationField>
                        <IntegrationToggleRow title="Enable GoHighLevel Sync" description="Sync captured leads to GoHighLevel." checked={gohighlevel.enabled} disabled={!canManage || Boolean(busy)} onToggle={() => setGohighlevel(current => ({ ...current, enabled: !current.enabled }))}/>
                        <IntegrationToggleRow title="Send Transcript Notes" description="Add chat transcript notes to synced GoHighLevel contacts." checked={gohighlevel.sendTranscript} disabled={!canManage || Boolean(busy)} onToggle={() => setGohighlevel(current => ({ ...current, sendTranscript: !current.sendTranscript }))}/>
                        <IntegrationToggleRow title="Send AI Summary Notes" description="Add AI summary notes to synced GoHighLevel contacts." checked={gohighlevel.sendSummary} disabled={!canManage || Boolean(busy)} onToggle={() => setGohighlevel(current => ({ ...current, sendSummary: !current.sendSummary }))}/>
                      </div>
                      {gohighlevel.connected ? (
                        <div className="app-template-overview" style={{marginBottom:14}}>
                          <IntegrationOverviewItem label="Location ID" value={gohighlevel.locationId || 'Connected'} />
                        </div>
                      ) : (
                        <div style={{padding:'14px 16px', border:'1px solid rgba(45, 212, 191, 0.35)', borderRadius:14, background:'rgba(45, 212, 191, 0.08)', color:'var(--pc-text-muted)', fontSize:13, marginBottom:14}}>GoHighLevel is not connected yet. Save your token and Location ID, then use Test Connection to verify.</div>
                      )}
                      <div style={{display:'flex', flexWrap:'wrap', justifyContent:'flex-end', gap:12, marginTop:16}}>
                        <button className="btn btn-secondary" type="button" onClick={saveGohighlevel} disabled={!canManage || Boolean(busy)}>{busy === 'gohighlevel-save' ? 'Saving…' : 'Save Settings'}</button>
                        <button className="btn btn-primary" type="button" onClick={testGohighlevel} disabled={!canManage || Boolean(busy) || !gohighlevel.configured}>{busy === 'gohighlevel-test' ? 'Testing…' : 'Test Connection'}</button>
                        <button className="btn btn-secondary" type="button" onClick={refreshGohighlevel} disabled={Boolean(busy)}>{busy === 'gohighlevel-refresh' ? 'Checking…' : 'Refresh Status'}</button>
                        {gohighlevel.connected && <button className="btn btn-danger" type="button" onClick={disconnectGohighlevel} disabled={!canManage || Boolean(busy)}>Disconnect</button>}
                      </div>
                    </>
                  )}
                </div>
              </IntegrationPanel>
              )}
            </div>
          </div>
        </>
      )}
    </div>
  );
}

function IntegrationPanel({ panelKey, icon, title, description, status, statusClass, isOpen, onToggle, error, success, disabled = false, children }) {
  const titleId = `integration-modal-title-${panelKey}`;

  return (
    <>
      <button
        type="button"
        className={`integration-launch-card ${disabled ? 'is-disabled' : ''}`}
        onClick={() => { if (!disabled) onToggle(panelKey); }}
        disabled={disabled}
        aria-disabled={disabled}
        aria-haspopup="dialog"
      >
        <span className="integration-launch-icon"><Icon name={icon} size={22}/></span>
        <span className="integration-launch-copy">
          <strong>{title}</strong>
          <span>{description}</span>
        </span>
        <span className={`pill ${statusClass}`}>{status}</span>
        <span className="integration-launch-action">{disabled ? 'Template required' : 'Configure'} <Icon name="arrowRight" size={16}/></span>
      </button>

      {isOpen && (
        <div
          className="integration-modal-backdrop"
          role="presentation"
          onMouseDown={event => {
            if (event.target === event.currentTarget) onToggle(panelKey);
          }}
        >
          <section className="integration-modal" role="dialog" aria-modal="true" aria-labelledby={titleId}>
            <header className="integration-modal-head">
              <span className="integration-modal-icon"><Icon name={icon} size={22}/></span>
              <div>
                <h2 id={titleId}>{title}</h2>
                <p>{description}</p>
              </div>
              <span className={`pill ${statusClass}`}>{status}</span>
              <button className="integration-modal-close" type="button" onClick={() => onToggle(panelKey)} aria-label={`Close ${title}`}>
                <Icon name="x" size={20}/>
              </button>
            </header>

            <div className="integration-modal-scroll">
              {error && (
                <div className="embedded-api-feedback is-error app-page-feedback">
                  <strong>Something went wrong</strong>
                  <span>{error}</span>
                </div>
              )}
              {success && (
                <div className="embedded-api-feedback is-success app-page-feedback">
                  <strong>Saved</strong>
                  <span>{success}</span>
                </div>
              )}
              <div className="integration-modal-body">{children}</div>
            </div>
          </section>
        </div>
      )}
    </>
  );
}

function MetaChannelCard({ channelType, channel, canManage, busy, onUpdateSettings, onSave, onTest, onRefresh, onDisconnect }) {
  const label = formatChannelName(channelType);
  if (!channel.connected) {
    return (
      <div style={{border:'1px solid var(--pc-border)', borderRadius:14, padding:14, marginTop:12}}>
        <strong>{label}</strong>
        <p style={{margin:'6px 0 0', color:'var(--pc-text-muted)', fontSize:12}}>Not connected.</p>
      </div>
    );
  }

  return (
    <div style={{border:'1px solid var(--pc-border)', borderRadius:14, padding:14, marginTop:12}}>
      <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:12}}>
        <strong>{label}</strong>
        <span className={`pill ${channel.status === 'connected' || channel.connected ? 'ok' : 'dim'}`}>{channel.status || 'connected'}</span>
        <span style={{marginLeft:'auto', color:'var(--pc-text-muted)', fontSize:12}}>{channel.displayName || channel.externalAccountId}</span>
      </div>
      <div style={{display:'grid', gap:12}}>
        <IntegrationToggleRow
          title="Show continuation button in widget"
          description="Display this connected channel in the website chatbot handoff area."
          checked={Boolean(channel.settings?.showInWidget)}
          disabled={!canManage || Boolean(busy)}
          onToggle={() => onUpdateSettings(channelType, 'showInWidget', !channel.settings?.showInWidget)}
        />
        <IntegrationField label="Button Label">
          <input className="embedded-input" value={channel.settings?.buttonLabel || ''} maxLength="80" disabled={!canManage || Boolean(busy)} onChange={event => onUpdateSettings(channelType, 'buttonLabel', event.target.value)}/>
        </IntegrationField>
        <IntegrationField label={`Public ${label} Link`}>
          <input className="embedded-input" type="url" value={channel.settings?.externalUrl || ''} placeholder={channelType === 'instagram' ? 'https://www.instagram.com/yourbusiness/' : 'https://m.me/yourpage'} disabled={!canManage || Boolean(busy)} onChange={event => onUpdateSettings(channelType, 'externalUrl', event.target.value)}/>
          <small>Visitors open this link only after they choose this channel.</small>
        </IntegrationField>
        <div style={{display:'flex', flexWrap:'wrap', gap:8}}>
          <button className="btn btn-primary" type="button" onClick={() => onSave(channelType)} disabled={!canManage || Boolean(busy)}>Save {label}</button>
          <button className="btn btn-ghost" type="button" onClick={() => onTest(channelType)} disabled={!canManage || Boolean(busy)}>Test connection</button>
          <button className="btn btn-ghost" type="button" onClick={() => onRefresh(channelType)} disabled={Boolean(busy)}>Refresh status</button>
          <button className="btn btn-danger" type="button" onClick={() => onDisconnect(channelType)} disabled={!canManage || Boolean(busy)}>Disconnect</button>
        </div>
        <div style={{fontSize:12, lineHeight:1.7, color:'var(--pc-text-muted)'}}>
          <div><strong>Account ID:</strong> {channel.externalAccountId || '—'}</div>
          <div><strong>Last webhook:</strong> {channel.lastWebhookAt || 'Not received yet'}</div>
          <div><strong>Last outbound:</strong> {channel.lastOutboundAt || 'Not sent yet'}</div>
          {channel.lastError && <div style={{color:'var(--pc-danger)'}}><strong>Last error:</strong> {channel.lastError}</div>}
        </div>
      </div>
    </div>
  );
}

function IntegrationToggleRow({ title, description, checked, disabled, onToggle }) {
  return (
    <div className="embedded-toggle-row">
      <div>
        <strong>{title}</strong>
        {description && <span>{description}</span>}
      </div>
      <button type="button" className={`embedded-toggle ${checked ? 'is-on' : ''}`} onClick={onToggle} disabled={disabled} aria-pressed={checked}><span /></button>
    </div>
  );
}

function IntegrationField({ label, children }) {
  return <label className="embedded-form-row"><span>{label}</span>{children}</label>;
}

function CopyInput({ label, value, empty, onCopy }) {
  const copy = async () => {
    if (!value) return;
    try {
      await navigator.clipboard.writeText(value);
      if (onCopy) onCopy('Copied to clipboard.');
    } catch (error) {
      if (onCopy) onCopy('Copy failed. Select and copy the value manually.');
    }
  };

  return (
    <IntegrationField label={label}>
      <div style={{display:'flex', gap:8}}>
        <input className="embedded-input" readOnly value={value || empty || ''}/>
        <button className="btn btn-ghost" type="button" onClick={copy} disabled={!value}>Copy</button>
      </div>
    </IntegrationField>
  );
}

function ReadOnlyNotice() {
  return (
    <div className="embedded-api-feedback" style={{marginBottom:12}}>
      <strong>View only</strong>
      <span>Only account owners and admins can change these settings.</span>
    </div>
  );
}

function IntegrationOverviewItem({ label, value }) {
  return (
    <div>
      <span>{label}</span>
      <strong>{value || '—'}</strong>
    </div>
  );
}

function normalizeHubspot(value) {
  const next = value && typeof value === 'object' ? value : {};
  return {
    ...DEFAULT_HUBSPOT,
    ...next,
    clientSecret: '',
    redirectUri: next.redirectUri || `${window.location.origin}/api/integrations/hubspot/callback`,
  };
}

function normalizeGohighlevel(value) {
  const next = value && typeof value === 'object' ? value : {};
  return {
    ...DEFAULT_GOHIGHLEVEL,
    ...next,
    token: '',
  };
}

function normalizeMeta(value) {
  const next = value && typeof value === 'object' ? value : {};
  return {
    ...DEFAULT_META,
    ...next,
    appSecret: '',
    verifyToken: '',
    redirectUri: next.redirectUri || `${window.location.origin}/api/integrations/meta/callback`,
    requiredPermissions: Array.isArray(next.requiredPermissions) ? next.requiredPermissions : [],
  };
}

function normalizeMetaChannel(value, channelType) {
  const next = value && typeof value === 'object' ? value : {};
  return {
    ...DEFAULT_META_CHANNEL,
    ...next,
    settings: {
      ...DEFAULT_META_CHANNEL.settings,
      buttonLabel: channelType === 'instagram' ? 'Continue on Instagram' : 'Continue on Messenger',
      ...(next.settings || {}),
    },
  };
}

function normalizeWhatsapp(value) {
  const next = value && typeof value === 'object' ? value : {};
  const appConfig = next.appConfig || {};
  return {
    ...DEFAULT_WHATSAPP,
    ...next,
    accessToken: '',
    appSecret: '',
    verifyToken: '',
    templates: Array.isArray(next.templates) ? next.templates : [],
    recentErrors: Array.isArray(next.recentErrors) ? next.recentErrors : [],
    webhookUrl: appConfig.webhookUrl || next.webhookUrl || next.callbackUrl || '',
    settings: { ...DEFAULT_WHATSAPP.settings, ...(next.settings || {}) },
  };
}

function normalizeLiveChat(value) {
  const next = value && typeof value === 'object' ? value : {};
  return {
    ...DEFAULT_LIVE_CHAT,
    ...next,
    workingDays: Array.isArray(next.workingDays) ? next.workingDays : DEFAULT_LIVE_CHAT.workingDays,
  };
}

function selectedMetaChannels(messenger, instagram) {
  const channels = [];
  if (messenger) channels.push('messenger');
  if (instagram) channels.push('instagram');
  return channels.length ? channels : ['messenger'];
}

function formatChannelName(channelType) {
  return channelType === 'instagram' ? 'Instagram' : 'Messenger';
}

function formatIntegrationDate(value) {
  if (!value) return '—';
  try {
    // Server timestamps are UTC without a zone suffix; browsers parse that
    // space-separated form as local time. Normalize to UTC before display.
    const raw = String(value).trim();
    const normalized = /[zZ]|[+-]\d{2}:?\d{2}$/.test(raw) ? raw : `${raw.replace(' ', 'T')}Z`;
    return new Date(normalized).toLocaleString();
  } catch (error) {
    return value;
  }
}

async function fetchJson(url) {
  const response = await fetch(url, { credentials: 'include', cache: 'no-store' });
  return readIntegrationResponse(response);
}

async function sendJson(url, method, body) {
  const response = await fetch(url, {
    method,
    credentials: 'include',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify(body || {}),
  });
  return readIntegrationResponse(response);
}

async function readIntegrationResponse(response) {
  const data = await response.json().catch(() => ({}));
  const authenticationRequired = response.status === 401
    && String(data.error || '').trim().toLowerCase() === 'authentication required.';

  if (authenticationRequired) {
    const isLocalhost = ['localhost', '127.0.0.1'].includes(window.location.hostname);
    if (!isLocalhost) {
      window.location.href = (['localhost','127.0.0.1'].includes(location.hostname)?'http://localhost:8788':'https://pluginchatbot.com')+'/login.html?redirect=' + encodeURIComponent(window.location.href);
    }
    throw new Error(isLocalhost
      ? 'Your local dashboard session has expired. Sign in again and retry.'
      : 'Your session has expired. Redirecting to sign in.');
  }

  if (!response.ok || data.ok === false) {
    throw new Error(data.error || `Request failed with HTTP ${response.status}`);
  }
  return data;
}

window.IntegrationsPage = IntegrationsPage;
