/* global React, Icon, AppInfoTip, AppFieldLabel, useSelectedWorkspaceId, getEmbeddedBuilderDraft, saveEmbeddedBuilderDraft, EMBEDDED_MODEL_OPTIONS, EMBEDDED_VOICE_OPTIONS, embeddedModelSupportsTemperature, capitalizeEmbedded */
const {
  useEffect: useEffectCustomize,
  useMemo: useMemoCustomize,
  useState: useStateCustomize,
} = React;

function CustomizePage() {
  const workspaceId = useSelectedWorkspaceId();
  const [settings, setSettings] = useStateCustomize(() => getEmbeddedBuilderDraft());
  const [saved, setSaved] = useStateCustomize(false);
  const [domainInput, setDomainInput] = useStateCustomize('');
  const [domainError, setDomainError] = useStateCustomize('');
  const [editingDomain, setEditingDomain] = useStateCustomize('');
  const [modelOptions, setModelOptions] = useStateCustomize(() => uniqueModels([
    getEmbeddedBuilderDraft().model,
    ...EMBEDDED_MODEL_OPTIONS,
  ]));
  const [modelsLoading, setModelsLoading] = useStateCustomize(false);
  const [modelError, setModelError] = useStateCustomize('');

  useEffectCustomize(() => {
    const nextSettings = getEmbeddedBuilderDraft();
    setSettings(nextSettings);
    setSaved(false);
    setDomainInput('');
    setDomainError('');
    setEditingDomain('');
    setModelOptions(uniqueModels([nextSettings.model, ...EMBEDDED_MODEL_OPTIONS]));
    setModelError('');
  }, [workspaceId]);

  const supportsTemperature = embeddedModelSupportsTemperature(settings.model);

  const allowedDomainList = useMemoCustomize(() => {
    return parseAllowedDomains(settings.allowedDomains);
  }, [settings.allowedDomains]);

  const updateSetting = (key, value) => {
    setSaved(false);
    setSettings(previous => ({ ...previous, [key]: value }));
  };

  const setAllowedDomainList = domains => {
    updateSetting('allowedDomains', domains.join(', '));
  };

  const addAllowedDomain = () => {
    const validation = validateAllowedDomain(domainInput);

    if (!validation.ok) {
      setDomainError(validation.error);
      return;
    }

    if (allowedDomainList.includes(validation.domain)) {
      setDomainError('This domain is already added.');
      return;
    }

    setAllowedDomainList([...allowedDomainList, validation.domain]);
    setDomainInput('');
    setDomainError('');
  };

  const editAllowedDomain = domain => {
    setEditingDomain(domain);
    setDomainInput(domain);
    setDomainError('');
  };

  const deleteAllowedDomain = domain => {
    setAllowedDomainList(allowedDomainList.filter(item => item !== domain));

    if (editingDomain === domain) {
      setEditingDomain('');
      setDomainInput('');
      setDomainError('');
    }
  };

  const saveEditedDomain = () => {
    const validation = validateAllowedDomain(domainInput);

    if (!validation.ok) {
      setDomainError(validation.error);
      return;
    }

    if (allowedDomainList.some(domain => domain !== editingDomain && domain === validation.domain)) {
      setDomainError('This domain is already added.');
      return;
    }

    setAllowedDomainList(allowedDomainList.map(domain => (
      domain === editingDomain ? validation.domain : domain
    )));
    setEditingDomain('');
    setDomainInput('');
    setDomainError('');
  };

  const cancelEditingDomain = () => {
    setEditingDomain('');
    setDomainInput('');
    setDomainError('');
  };

  const loadAvailableModels = async () => {
    if (!settings.editingBotId) {
      setModelError('Save this website first. PluginChatBot will provision its private AI key before live models can be refreshed.');
      return;
    }

    setModelsLoading(true);
    setModelError('');

    try {
      const response = await fetch('/api/openai/models', {
        method: 'POST',
        credentials: 'include',
        cache: 'no-store',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ botId: settings.editingBotId }),
      });

      const data = await response.json().catch(() => ({}));

      if (response.status === 401) {
        window.location.href = (['localhost','127.0.0.1'].includes(location.hostname)?'http://localhost:8788':'https://pluginchatbot.com')+'/login.html?redirect=' + encodeURIComponent(window.location.href);
        return;
      }

      if (!response.ok || !data.ok) {
        throw new Error(data.error || 'Unable to load OpenAI models.');
      }

      const nextModels = uniqueModels([settings.model, ...(Array.isArray(data.models) ? data.models : [])]);
      setModelOptions(nextModels);

      if (!settings.model && nextModels.length) {
        updateSetting('model', nextModels[0]);
      }
    } catch (error) {
      setModelError(error.message || 'Unable to load OpenAI models.');
    } finally {
      setModelsLoading(false);
    }
  };

  const saveSettings = () => {
  if (!String(settings.model || '').trim()) {
    setSaved(false);
    setModelError('Error, Select Model.');
    return;
  }

  setModelError('');
  saveEmbeddedBuilderDraft(settings);

  setSaved(true);
  };

  return (
    <div className="view customize-view">
      <div className="view-head">
        <div>
          <h1>Customize</h1>
          <div className="sub">Configure website access, visitor capture, voice, and AI behavior</div>
        </div>
        <button className="btn btn-primary" type="button" onClick={saveSettings}>Save Changes</button>
      </div>

      {saved && <CustomizeSavedNotice />}

      <div className="customize-settings-grid">
        <SettingsCard
          className="customize-openai-card"
          title="AI Setup"
          icon="brain"
          description="Choose how the chatbot prepares replies. PluginChatBot manages one private AI key for each registered website."
        >
          <p className="app-info-note">Your website’s private AI key is securely managed by PluginChatBot and is never shown in this dashboard.</p>

          <CustomizeFormRow
            label="GPT Model"
            help="Choose the model that will answer visitors. After the website key is provisioned, refresh to load available models."
            hint={modelError || (modelsLoading ? 'Loading available models…' : 'The list is filtered to models suitable for chatbot text responses.')}
            hintTone={modelError ? 'error' : ''}
          >
            <div className="app-model-picker">
              <select
                className="embedded-input"
                value={settings.model}
                onChange={event => updateSetting('model', event.target.value)}
              >
                <option value="">Choose a reply model</option>
                {modelOptions.map(model => <option key={model} value={model}>{model}</option>)}
              </select>
              <button
                className="btn btn-secondary"
                type="button"
                onClick={loadAvailableModels}
              disabled={modelsLoading || !settings.editingBotId}
              >
                <Icon name="refresh" size={14}/>{modelsLoading ? 'Loading' : 'Refresh Models'}
              </button>
            </div>
          </CustomizeFormRow>

          <CustomizeFormRow
            label="Creativity"
            help="Lower values keep replies more consistent and focused. Higher values allow more variation. Some reasoning models manage this automatically."
            hint={!supportsTemperature ? 'The selected reasoning model manages creativity automatically.' : ''}
          >
            <div className={`embedded-range-row ${supportsTemperature ? '' : 'is-disabled'}`}>
              <input
                type="range"
                min="0"
                max="1"
                step="0.1"
                value={settings.temperature}
                disabled={!supportsTemperature}
                onChange={event => updateSetting('temperature', event.target.value)}
              />
              <span>{supportsTemperature ? settings.temperature : 'Auto'}</span>
            </div>
          </CustomizeFormRow>

          <CustomizeFormRow
            label="Rate Limit"
            help="Limit how many messages one visitor can send each second. This helps reduce automated abuse and unexpected API usage."
            hint="Set the value to 0 to disable this limit."
          >
            <div className="embedded-range-row">
              <input
                type="range"
                min="0"
                max="20"
                step="1"
                value={settings.rateLimit}
                onChange={event => updateSetting('rateLimit', event.target.value)}
              />
              <span>{settings.rateLimit}</span>
            </div>
          </CustomizeFormRow>
        </SettingsCard>

        <SettingsCard
          className="customize-access-card"
          title="Website Access"
          icon="globe"
          description="Choose which websites are allowed to load this chatbot."
        >
          <div className="embedded-form-row">
            <AppFieldLabel
              label="Allowed Domains"
              help="Add each approved website without http, https, www, a path, or spaces."
            />

            <div className="domain-list">
              {allowedDomainList.length > 0 ? allowedDomainList.map(domain => (
                <div className="domain-item" key={domain}>
                  <span>{domain}</span>
                  <div>
                    <button type="button" onClick={() => editAllowedDomain(domain)}>Edit</button>
                    <button type="button" onClick={() => deleteAllowedDomain(domain)}>Delete</button>
                  </div>
                </div>
              )) : <div className="domain-empty">No domains added yet.</div>}
            </div>

            <div className="domain-add-row">
              <input
                className="embedded-input"
                type="text"
                value={domainInput}
                placeholder="example.com"
                onChange={event => {
                  setDomainInput(event.target.value);
                  setDomainError('');
                }}
                onKeyDown={event => {
                  if (event.key === 'Enter') {
                    event.preventDefault();
                    editingDomain ? saveEditedDomain() : addAllowedDomain();
                  }
                }}
              />
              <button className="btn btn-primary" type="button" onClick={editingDomain ? saveEditedDomain : addAllowedDomain}>
                {editingDomain ? 'Update' : 'Add'}
              </button>
              {editingDomain && <button className="btn btn-secondary" type="button" onClick={cancelEditingDomain}>Cancel</button>}
            </div>

            {domainError && <div className="domain-error">{domainError}</div>}
          </div>
        </SettingsCard>

        <SettingsCard
          className="customize-visitor-card"
          title="Visitor Capture"
          icon="contact"
          description="Collect useful contact details before or during a conversation."
        >
          <CustomizeToggleRow
            label="Enable Visitor Capture"
            help="When enabled, the chatbot asks visitors for contact details so your team can follow up after the conversation."
            description="Ask visitors for contact details before or during chat."
            checked={settings.visitorCaptureEnabled}
            onChange={value => updateSetting('visitorCaptureEnabled', value)}
          />

          <CustomizeFormRow
            label="Capture Mode"
            help="Choose whether details are collected inside the first chat message or through a separate form when the widget opens."
          >
            <div className="embedded-radio-grid">
              <label>
                <input
                  type="radio"
                  name="visitor_capture_mode"
                  value="chat"
                  checked={settings.visitorCaptureMode === 'chat'}
                  disabled={!settings.visitorCaptureEnabled}
                  onChange={event => updateSetting('visitorCaptureMode', event.target.value)}
                />
                <span>Chat (capture on first message)</span>
              </label>
              <label>
                <input
                  type="radio"
                  name="visitor_capture_mode"
                  value="form"
                  checked={settings.visitorCaptureMode === 'form'}
                  disabled={!settings.visitorCaptureEnabled}
                  onChange={event => updateSetting('visitorCaptureMode', event.target.value)}
                />
                <span>Popup form (when opening the chatbot)</span>
              </label>
            </div>
          </CustomizeFormRow>

          <CustomizeFormRow
            label="Capture Message"
            help="Use a short, welcoming explanation so visitors understand why their details are being requested."
          >
            <textarea
              className="embedded-input"
              rows="5"
              disabled={!settings.visitorCaptureEnabled}
              value={settings.visitorCapturePrompt}
              onChange={event => updateSetting('visitorCapturePrompt', event.target.value)}
            />
          </CustomizeFormRow>
        </SettingsCard>

        <SettingsCard
          className="customize-voice-card"
          title="Voice Settings"
          icon="sparkles"
          description="Offer an optional AI-generated audio version of chatbot replies."
        >
          <CustomizeToggleRow
            label="Enable Voice Replies"
            help="Eligible chatbot replies include an audio playback option. Voice generation uses the connected OpenAI account."
            description="Let visitors listen to an AI-generated version of a reply."
            checked={settings.enableTts}
            onChange={value => updateSetting('enableTts', value)}
          />

          <CustomizeFormRow
            label="TTS Model"
            help="Choose the OpenAI text-to-speech model used to create audio replies."
          >
            <select
              className="embedded-input"
              value={settings.ttsModel}
              disabled={!settings.enableTts}
              onChange={event => updateSetting('ttsModel', event.target.value)}
            >
              <option value="gpt-4o-mini-tts">gpt-4o-mini-tts</option>
              <option value="tts-1">tts-1</option>
              <option value="tts-1-hd">tts-1-hd</option>
            </select>
          </CustomizeFormRow>

          <CustomizeFormRow
            label="Voice"
            help="Select the speaking style visitors will hear when they play an audio reply."
          >
            <select
              className="embedded-input"
              value={settings.voice}
              disabled={!settings.enableTts}
              onChange={event => updateSetting('voice', event.target.value)}
            >
              {EMBEDDED_VOICE_OPTIONS.map(voice => (
                <option key={voice} value={voice}>{capitalizeEmbedded(voice)}</option>
              ))}
            </select>
          </CustomizeFormRow>
        </SettingsCard>
      </div>
    </div>
  );
}

function SettingsCard({ title, icon, description, className = '', children }) {
  const [isOpen, setIsOpen] = useStateCustomize(true);
  const panelId = `customize-${String(title || '').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`;

  return (
    <section className={`app-settings-panel ${isOpen ? 'is-open' : ''} ${className}`.trim()}>
      <button
        className="app-settings-panel-summary"
        type="button"
        onClick={() => setIsOpen(current => !current)}
        aria-expanded={isOpen}
        aria-controls={panelId}
      >
        <span className="icon-chip"><Icon name={icon} size={20}/></span>
        <span className="app-settings-panel-heading">
          <span className="app-settings-panel-title">{title}</span>
          {description && <small>{description}</small>}
        </span>
        <span className="app-settings-panel-toggle"><Icon name={isOpen ? 'chevronUp' : 'chevronDown'} size={18}/></span>
      </button>
      <div id={panelId} className="app-settings-panel-body" hidden={!isOpen}>{children}</div>
    </section>
  );
}

function CustomizeFormRow({ label, help, hint, hintTone = '', children }) {
  return (
    <div className="embedded-form-row">
      <AppFieldLabel label={label} help={help}/>
      {children}
      {hint && <small className={hintTone ? `is-${hintTone}` : ''}>{hint}</small>}
    </div>
  );
}

function CustomizeToggleRow({ label, help, description, checked, onChange }) {
  return (
    <div className="embedded-toggle-row">
      <div>
        <strong><span>{label}</span>{help && <AppInfoTip text={help} label={label}/>}</strong>
        <span>{description}</span>
      </div>
      <button
        type="button"
        className={`embedded-toggle ${checked ? 'is-on' : ''}`}
        onClick={() => onChange(!checked)}
        aria-pressed={checked}
        aria-label={`${checked ? 'Disable' : 'Enable'} ${label}`}
      ><span/></button>
    </div>
  );
}

function uniqueModels(models) {
  return Array.from(new Set(models.map(model => String(model || '').trim().toLowerCase()).filter(Boolean)));
}

function parseAllowedDomains(value) {
  return String(value || '')
    .split(',')
    .map(domain => String(domain || '').trim().toLowerCase())
    .filter(Boolean)
    .filter((domain, index, domains) => domains.indexOf(domain) === index);
}

function validateAllowedDomain(value) {
  const domain = String(value || '').trim().toLowerCase();

  if (!domain) return { ok: false, error: 'Please enter a domain name.' };
  if (domain.includes(',') || domain.split(/\s+/).length > 1) return { ok: false, error: 'Please add only one domain at a time.' };
  if (/^https?:\/\//i.test(domain)) return { ok: false, error: 'Do not include http:// or https://. Use domain (example.com) only.' };
  if (domain.startsWith('www.')) return { ok: false, error: 'Do not include www. Use domain (example.com) instead.' };
  if (domain.includes('/') || domain.includes('?') || domain.includes('#')) return { ok: false, error: 'Do not include paths or query strings. Use domain (example.com) only.' };

  const isValidDomain = /^(?!-)([a-z0-9-]{1,63}\.)+[a-z]{2,63}$/.test(domain);

  if (!isValidDomain) {
    return { ok: false, error: 'Please enter a valid domain, like example.com or app.example.com.' };
  }

  return { ok: true, domain };
}

function CustomizeSavedNotice() {
  return (
    <div className="app-save-notice">
      Settings saved. Generate or update the embed code from <a href="/ai-builder">AI Builder</a> when ready.
    </div>
  );
}

window.CustomizePage = CustomizePage;
