import React, { useEffect, useRef, useState } from 'react';
import { Switch, Input, InputNumber, Select, Button, message } from 'antd';
import { __, sprintf } from '@wordpress/i18n';
import { applyFilters } from '../extend';
import * as api from '../services/api';

/**
 * Per-form settings schema and inputs, rendered by FormSettingsPage.jsx.
 *
 * Settings are stored per form ID (forms table, `settings` column). The defaults below mirror
 * FormGlut_Form_Settings::defaults() in PHP; the server sanitizes everything again on save.
 */
export const DEFAULT_FORM_SETTINGS = {
  general: { show_title: false, form_class: '', submit_processing: '' },
  confirmation: { type: 'message', message: '', redirect_page: 0, redirect_post: 0, redirect_url: '', query_string: '', pass_fields: false, after_submit: 'reset', scroll: true, autoclose: 0, error_message: '' },
  notifications: {
    enabled: true, to: '', cc: '', bcc: '', from_name: '', from_email: '', reply_to: '', subject: '', message: '', attach_files: false,
    autoresponder: { enabled: false, email_field: '', subject: '', message: '' },
  },
  restrictions: {
    require_login: false, guest_message: __( 'You must be logged in to submit this form.', 'formglut' ), entry_limit: 0, limit_message: __( 'This form is no longer accepting entries.', 'formglut' ),
    schedule_enabled: false, schedule_start: '', schedule_end: '', before_message: __( 'This form is not open yet.', 'formglut' ), after_message: __( 'This form is closed.', 'formglut' ),
    deny_empty: false, one_per_ip: false, duplicate_message: __( 'You have already submitted this form.', 'formglut' ),
  },
  spam: { honeypot: 'global', akismet: false, stopforumspam: false, keywords: '', keyword_action: 'reject', store_ip: true, store_entries: 'global', retention_days: 0, min_time: 0, rate_limit: 0, referrer_check: false },
  style: { form_width: '', form_align: 'left', custom_css: '', custom_js: '' },
  entries: { count_views: true },
  multistep: { progress: 'steps', first_title: '', validate_step: true },
  integrations: {
    webhook_enabled: false, webhook_url: '', webhook_format: 'json', slack_enabled: false, slack_webhook: '', slack_message: '',
    discord_enabled: false, discord_webhook: '', discord_message: '',
    telegram_enabled: false, telegram_bot_token: '', telegram_chat_id: '', telegram_message: '',
    teams_enabled: false, teams_webhook: '', teams_message: '',
  },
  mailchimp: { enabled: false, list_id: '', email_field: '', first_name_field: '', last_name_field: '', tags: '', double_optin: false, consent_field: '' },
  polls: { show_results: false, fields: [], show_counts: false },
  registration: { enabled: false, email_field: '', username_field: '', password_field: '', first_name_field: '', last_name_field: '', auto_login: false },
  save_progress: { enabled: false, message: '' },
  share: { enabled: false, description: '' },
};

const EMAIL_RE = /^[^\s@,;]+@[^\s@,;]+\.[^\s@,;]+$/;

/** Warning for a list of addresses with entries that are neither an email nor a smart tag (they are dropped on save). */
function badEmails(list) {
  const bad = String(list || '').split(/[\s,;]+/).filter((x) => x && !EMAIL_RE.test(x) && !/^\{[a-z_:0-9-]+\}$/i.test(x));
  /* translators: %s: invalid entries */
  return bad.length ? sprintf(__( 'Not a valid email address: %s. It is removed when you save.', 'formglut' ), bad.join(', ')) : '';
}

/** Sends a test admin notification (current settings, sample answers) to an address. */
function TestNotification({ formId, settings }) {
  const [to, setTo] = useState((window.formglut_admin && window.formglut_admin.admin_email) || '');
  const [busy, setBusy] = useState(false);
  const send = async () => {
    setBusy(true);
    try {
      const r = await api.sendTestNotification(formId, to.trim(), settings);
      message.success(r.message || __( 'Test notification sent.', 'formglut' ));
    } catch (e) {
      message.error(e.message || __( 'The test notification could not be sent.', 'formglut' ));
    } finally { setBusy(false); }
  };
  return (
    <div style={{ display: 'flex', gap: 8 }}>
      <Input value={to} onChange={(e) => setTo(e.target.value)} placeholder="you@example.com" onPressEnter={send} />
      <Button type="primary" loading={busy} disabled={!formId || !EMAIL_RE.test(to.trim())} onClick={send}>{__( 'Send test', 'formglut' )}</Button>
    </div>
  );
}

/** Mailchimp audience picker: loads the audiences of the API key saved in Global Settings. */
function MailchimpAudience({ value, onChange }) {
  const [lists, setLists] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');
  const load = () => {
    setLoading(true);
    setError('');
    api.request('formglut_mailchimp_lists', {}, 'GET')
      .then((d) => setLists(d.lists || []))
      .catch((e) => setError(e.message))
      .finally(() => setLoading(false));
  };
  useEffect(() => { load(); }, []);
  const options = lists || (value ? [{ value, label: value }] : []);
  return (
    <div>
      <div style={{ display: 'flex', gap: 8 }}>
        <Select value={value || undefined} placeholder={__( 'Choose an audience', 'formglut' )} onChange={onChange} options={options} loading={loading} style={{ flex: 1 }} notFoundContent={__( 'No audiences found', 'formglut' )} />
        <Button onClick={load} loading={loading}>{__( 'Refresh', 'formglut' )}</Button>
      </div>
      {error && <div className="fg-fs-help fg-fs-warn" style={{ marginTop: 6 }}>{error}</div>}
    </div>
  );
}

/** Shortcode for gated content with a Copy button. */
function GateCode({ formId }) {
  const code = `[formglut_gate form="${formId}" days="30"]${__( 'Your hidden content', 'formglut' )}[/formglut_gate]`;
  const copy = () => { if (navigator.clipboard) navigator.clipboard.writeText(code).then(() => message.success(__( 'Shortcode copied.', 'formglut' )), () => {}); };
  return (
    <div style={{ display: 'flex', gap: 8 }}>
      <Input value={code} readOnly onFocus={(e) => e.target.select()} style={{ fontFamily: 'ui-monospace, Menlo, monospace', fontSize: 12 }} />
      <Button onClick={copy}>{__( 'Copy', 'formglut' )}</Button>
    </div>
  );
}

/** Address of the form's share page with Copy and Open buttons. */
function ShareLink({ formId, enabled }) {
  const data = window.formglut_admin || {};
  if (!formId || !data.share_base) return null;
  const url = new URL(data.share_base);
  url.searchParams.set(data.share_param || 'formglut_share', String(formId));
  const link = url.toString();
  const copy = () => {
    const done = () => message.success(__( 'Link copied.', 'formglut' ));
    if (navigator.clipboard) navigator.clipboard.writeText(link).then(done, () => {});
  };
  return (
    <div>
      <div style={{ display: 'flex', gap: 8 }}>
        <Input value={link} readOnly onFocus={(e) => e.target.select()} />
        <Button onClick={copy}>{__( 'Copy', 'formglut' )}</Button>
        <Button onClick={() => window.open(link, '_blank', 'noopener')} disabled={!enabled}>{__( 'Open', 'formglut' )}</Button>
      </div>
      {!enabled && <div className="fg-fs-help" style={{ marginTop: 6 }}>{__( 'Turn on the share page and save to make this link work.', 'formglut' )}</div>}
    </div>
  );
}

/** Default settings with add-on groups (formglut.formSettings.defaults; mirror formglut_form_settings_defaults in PHP). */
export function getDefaultFormSettings() {
  return applyFilters('formglut.formSettings.defaults', DEFAULT_FORM_SETTINGS);
}

/** Fill in any keys a saved form is missing (older forms have no settings at all). */
export function mergeFormSettings(saved) {
  const merge = (base, over) => {
    const out = { ...base };
    Object.keys(base).forEach((k) => {
      if (over && over[k] !== undefined && over[k] !== null) {
        out[k] = base[k] && typeof base[k] === 'object' && !Array.isArray(base[k]) ? merge(base[k], over[k]) : over[k];
      }
    });
    return out;
  };
  return merge(getDefaultFormSettings(), saved || {});
}

export const TAGS = '{form_name} {form_id} {entry_id} {site_name} {admin_email} {date} {user_email} {all_fields} {field:FIELD_ID}';

// Sections hidden until the feature is checked for release (Step Break is not in the palette yet).
const HIDDEN_SECTIONS = [];

/** Schema: one entry per collapsible section, one per control. `emailFields` is injected at render time. */
export function buildSchema(emailFields, inputFields = [], hasUploads = false, extra = {}) {
  const emailOptions = [{ value: '', label: __( '— None —', 'formglut' ) }, ...emailFields];
  const fieldOptions = [{ value: '', label: __( '— None —', 'formglut' ) }, ...inputFields];
  const pageOptions = (window.formglut_admin && window.formglut_admin.redirect_pages) || [];
  const postOptions = (window.formglut_admin && window.formglut_admin.redirect_posts) || [];
  // Add-ons add tabs or rows with formglut.formSettings.sections. A tab: { key, title, icon, desc, fields }.
  // A row: { path, type, label, tip, show(settings), options }; type 'component' draws row.render({ value, onChange, settings }).
  return applyFilters('formglut.formSettings.sections', [
    {
      key: 'general', title: __( 'General', 'formglut' ), fields: [
        { path: 'general.show_title', type: 'switch', label: __( 'Show form title', 'formglut' ), tip: __( 'Print the form title above the fields.', 'formglut' ) },
        { path: 'general.form_class', type: 'text', label: __( 'Form CSS class', 'formglut' ), tip: __( 'Extra class(es) added to the form wrapper.', 'formglut' ), placeholder: 'my-form' },
      ],
    },
    {
      key: 'confirmation', title: __( 'Confirmation', 'formglut' ), fields: [
        { path: 'confirmation.type', type: 'select', label: __( 'After a successful submit', 'formglut' ), info: __( 'Choose what happens once the form is sent: show a message on the same page, or send the visitor to a page, a post or any web address.', 'formglut' ), options: [{ value: 'message', label: __( 'Show a message', 'formglut' ) }, { value: 'page', label: __( 'Redirect to a page', 'formglut' ) }, { value: 'post', label: __( 'Redirect to a post', 'formglut' ) }, { value: 'url', label: __( 'Redirect to a URL', 'formglut' ) }] },
        { path: 'confirmation.message', tags: true, type: 'editor', label: __( 'Success message', 'formglut' ), info: __( 'The text visitors see after submitting. Smart tags such as {field:FIELD_ID} are replaced with their answers. Leave empty to use the success message from Global Settings.', 'formglut' ), show: (s) => s.confirmation.type === 'message' },
        { path: 'confirmation.redirect_page', type: 'search-select', label: __( 'Redirect page', 'formglut' ), info: __( 'Visitors are taken to this page after submitting. Only published pages work.', 'formglut' ), placeholder: __( 'Select a page', 'formglut' ), options: pageOptions, show: (s) => s.confirmation.type === 'page', note: (s) => !s.confirmation.redirect_page ? __( 'Choose a page. Until then visitors see the success message instead.', 'formglut' ) : '' },
        { path: 'confirmation.redirect_post', type: 'search-select', label: __( 'Redirect post', 'formglut' ), info: __( 'Visitors are taken to this post after submitting. Only published posts work.', 'formglut' ), placeholder: __( 'Select a post', 'formglut' ), options: postOptions, show: (s) => s.confirmation.type === 'post', note: (s) => !s.confirmation.redirect_post ? __( 'Choose a post. Until then visitors see the success message instead.', 'formglut' ) : '' },
        { path: 'confirmation.redirect_url', tags: 'url', type: 'text', label: __( 'Redirect URL', 'formglut' ), info: __( 'The full web address to send visitors to, e.g. https://site.com/thanks. Smart tags are allowed, e.g. https://site.com/thanks?entry={entry_id}; their values are URL-encoded for you.', 'formglut' ), placeholder: 'https://', show: (s) => s.confirmation.type === 'url', note: (s) => {
          const u = (s.confirmation.redirect_url || '').trim();
          if (!u) return __( 'Enter an address. Until then visitors see the success message instead.', 'formglut' );
          return /^(https?:\/\/|\/|\{site_url\})/i.test(u) ? '' : __( 'Start the address with https:// (or / for a page on this site).', 'formglut' );
        } },
        { path: 'confirmation.query_string', tags: 'url', type: 'text', label: __( 'Redirect query string', 'formglut' ), info: __( 'Extra values added to the end of the redirect address, written as name=value pairs joined with &, e.g. name={field:FIELD_ID}&ref=contact. Useful for a thank-you page that greets the visitor by name or for tracking. Values are URL-encoded.', 'formglut' ), placeholder: 'name={field:FIELD_ID}', show: (s) => s.confirmation.type !== 'message' },
        { path: 'confirmation.pass_fields', type: 'switch', label: __( 'Pass field data via query string', 'formglut' ), info: __( 'Adds every answer to the redirect address as FIELD_ID=value, so the next page can read them. Avoid it for private data: addresses are saved in browser history and server logs. Values you set in the query string above win when names clash.', 'formglut' ), show: (s) => s.confirmation.type !== 'message' },
        { path: 'confirmation.after_submit', type: 'select', label: __( 'Form after submit', 'formglut' ), info: __( 'Clear the fields: the form empties so someone can submit again. Hide the form: only the message stays. Keep the values: the answers stay filled in.', 'formglut' ), options: [{ value: 'reset', label: __( 'Clear the fields', 'formglut' ) }, { value: 'hide', label: __( 'Hide the form', 'formglut' ) }, { value: 'keep', label: __( 'Keep the values', 'formglut' ) }], show: (s) => s.confirmation.type === 'message' },
        { path: 'confirmation.scroll', type: 'switch', label: __( 'Scroll to the message', 'formglut' ), info: __( 'Scrolls the page so the success message is in view. Helpful for long forms where the message would be off screen.', 'formglut' ), show: (s) => s.confirmation.type === 'message' },
        { path: 'confirmation.autoclose', type: 'number', label: __( 'Hide message after (seconds)', 'formglut' ), info: __( 'Removes the success message after this many seconds. 0 keeps it on screen. If the form was hidden, it shows again (empty) when the message goes away.', 'formglut' ), show: (s) => s.confirmation.type === 'message' },
        { path: 'confirmation.error_message', type: 'textarea', label: __( 'Failure message', 'formglut' ), info: __( 'Shown when the submission cannot be completed, e.g. a server or connection problem or a failed captcha. Field mistakes still show their own messages. Leave empty to use the error message from Global Settings.', 'formglut' ) },
      ],
    },
    {
      key: 'notifications', title: __( 'Notifications', 'formglut' ), fields: [
        { path: 'notifications.enabled', type: 'switch', label: __( 'Send admin notification', 'formglut' ), info: __( 'Emails you (the site team) every time someone submits this form, with their answers.', 'formglut' ) },
        { path: 'notifications.to', tags: 'plain', type: 'text', label: __( 'Send to', 'formglut' ), info: __( 'Who receives the notification. Separate several addresses with commas. Smart tags such as {admin_email} work. Leave empty to use the admin email from Global Settings.', 'formglut' ), placeholder: '{admin_email}', show: (s) => s.notifications.enabled, note: (s) => badEmails(s.notifications.to) },
        { path: 'notifications.cc', tags: 'plain', type: 'text', label: __( 'CC', 'formglut' ), info: __( 'Carbon copy: these addresses also get the email, and every recipient can see them. Separate several with commas.', 'formglut' ), show: (s) => s.notifications.enabled, note: (s) => badEmails(s.notifications.cc) },
        { path: 'notifications.bcc', tags: 'plain', type: 'text', label: __( 'BCC', 'formglut' ), info: __( 'Blind carbon copy: these addresses get the email too, but the other recipients cannot see them.', 'formglut' ), show: (s) => s.notifications.enabled, note: (s) => badEmails(s.notifications.bcc) },
        { path: 'notifications.from_name', tags: 'plain', type: 'text', label: __( 'From name', 'formglut' ), info: __( 'The sender name shown in the inbox, e.g. your site name. Leave empty to use the sender name from Global Settings.', 'formglut' ), show: (s) => s.notifications.enabled },
        { path: 'notifications.from_email', type: 'text', label: __( 'From email', 'formglut' ), info: __( 'The address the email is sent from. Use one on this site’s domain (e.g. noreply@yoursite.com) or the email may land in spam. Leave empty to use the sender email from Global Settings.', 'formglut' ), placeholder: 'noreply@example.com', show: (s) => s.notifications.enabled, note: (s) => s.notifications.from_email && !EMAIL_RE.test(s.notifications.from_email.trim()) ? __( 'This is not a valid email address, so the global sender is used.', 'formglut' ) : '' },
        { path: 'notifications.reply_to', type: 'select', label: __( 'Reply-To', 'formglut' ), info: __( 'Pick the Email field of this form. When you press Reply on the notification, your answer goes straight to the visitor instead of to the sender address.', 'formglut' ), options: emailOptions, show: (s) => s.notifications.enabled, note: () => emailFields.length ? '' : __( 'Add an Email field to the form to use this.', 'formglut' ) },
        { path: 'notifications.subject', tags: 'plain', type: 'text', label: __( 'Subject', 'formglut' ), info: __( 'The email subject line. Smart tags work, e.g. New entry: {form_name}. Leave empty to use the subject from Global Settings.', 'formglut' ), placeholder: 'New entry: {form_name}', show: (s) => s.notifications.enabled },
        { path: 'notifications.message', tags: true, type: 'textarea', rows: 6, label: __( 'Message', 'formglut' ), info: __( 'The email body. Leave empty to send a neat table of all answers. Use {all_fields} to put that table inside your own text, or {field:FIELD_ID} for single answers.', 'formglut' ), show: (s) => s.notifications.enabled },
        { path: 'notifications.attach_files', type: 'switch', label: __( 'Attach uploaded files', 'formglut' ), info: __( 'Files from File Upload fields are attached to the email (each up to 20 MB). Links to the files are always in the entry.', 'formglut' ), show: (s) => s.notifications.enabled && hasUploads },
        { path: 'notifications.test', type: 'component', label: __( 'Test the notification', 'formglut' ), info: __( 'Sends this notification with sample answers to the address you enter, using the settings on screen (saved or not). CC and BCC are skipped. The subject starts with [Test].', 'formglut' ), show: (s) => s.notifications.enabled, render: ({ settings }) => <TestNotification formId={extra.formId} settings={settings} /> },
        { path: 'notifications.autoresponder.enabled', type: 'switch', label: __( 'Send a confirmation email to the visitor', 'formglut' ), info: __( 'Also emails the person who filled in the form, e.g. “Thanks, we got your message”. It goes to the address they typed in the Email field chosen below.', 'formglut' ), divider: true },
        { path: 'notifications.autoresponder.email_field', type: 'select', label: __( 'Visitor email field', 'formglut' ), info: __( 'The Email field that holds the visitor’s address. The confirmation is sent to whatever they typed there.', 'formglut' ), options: emailOptions, show: (s) => s.notifications.autoresponder.enabled, note: (s) => !emailFields.length ? __( 'This form has no Email field, so no confirmation can be sent.', 'formglut' ) : (!s.notifications.autoresponder.email_field ? __( 'Choose the Email field, or no confirmation is sent.', 'formglut' ) : '') },
        { path: 'notifications.autoresponder.subject', tags: 'plain', type: 'text', label: __( 'Subject', 'formglut' ), info: __( 'Subject of the visitor’s email. Leave empty for “Thank you for contacting {site_name}”.', 'formglut' ), placeholder: 'Thank you for contacting {site_name}', show: (s) => s.notifications.autoresponder.enabled },
        { path: 'notifications.autoresponder.message', tags: true, type: 'textarea', rows: 5, label: __( 'Message', 'formglut' ), info: __( 'Body of the visitor’s email. Leave empty for a short thank-you with a copy of their answers. It is sent from the From name and From email above.', 'formglut' ), show: (s) => s.notifications.autoresponder.enabled },
      ],
    },
    {
      key: 'restrictions', title: __( 'Restrictions', 'formglut' ), fields: [
        { path: 'restrictions.require_login', type: 'switch', label: __( 'Only logged-in users', 'formglut' ) },
        { path: 'restrictions.guest_message', type: 'text', label: __( 'Message for visitors', 'formglut' ), placeholder: __( 'You must be logged in to submit this form.', 'formglut' ), show: (s) => s.restrictions.require_login },
        { path: 'restrictions.entry_limit', type: 'number', label: __( 'Limit total entries', 'formglut' ), tip: __( '0 = unlimited. The form closes when the limit is reached. Spam and trashed entries do not count.', 'formglut' ) },
        { path: 'restrictions.limit_message', type: 'text', label: __( 'Message when the limit is reached', 'formglut' ), placeholder: __( 'This form is no longer accepting entries.', 'formglut' ), show: (s) => s.restrictions.entry_limit > 0 },
        { path: 'restrictions.schedule_enabled', type: 'switch', label: __( 'Schedule the form', 'formglut' ) },
        { path: 'restrictions.schedule_start', type: 'datetime', label: __( 'Opens', 'formglut' ), tip: __( 'In the site’s time zone (Settings › General). Leave empty for no limit.', 'formglut' ), show: (s) => s.restrictions.schedule_enabled },
        { path: 'restrictions.schedule_end', type: 'datetime', label: __( 'Closes', 'formglut' ), tip: __( 'In the site’s time zone (Settings › General). Leave empty for no limit.', 'formglut' ), show: (s) => s.restrictions.schedule_enabled },
        { path: 'restrictions.before_message', type: 'text', label: __( 'Message before opening', 'formglut' ), placeholder: __( 'This form is not open yet.', 'formglut' ), show: (s) => s.restrictions.schedule_enabled },
        { path: 'restrictions.after_message', type: 'text', label: __( 'Message after closing', 'formglut' ), placeholder: __( 'This form is closed.', 'formglut' ), show: (s) => s.restrictions.schedule_enabled },
        { path: 'restrictions.deny_empty', type: 'switch', label: __( 'Reject empty submissions', 'formglut' ) },
        { path: 'restrictions.one_per_ip', type: 'switch', label: __( 'One entry per IP address', 'formglut' ), tip: __( 'When IP addresses are not stored with entries, only a scrambled (hashed) copy is kept to recognise repeat visitors.', 'formglut' ) },
        { path: 'restrictions.duplicate_message', type: 'text', label: __( 'Message for repeat submissions', 'formglut' ), placeholder: __( 'You have already submitted this form.', 'formglut' ), show: (s) => s.restrictions.one_per_ip },
      ],
    },
    {
      key: 'spam', title: __( 'Spam & privacy', 'formglut' ), fields: [
        { path: 'spam.honeypot', type: 'select', label: __( 'Honeypot', 'formglut' ), options: [{ value: 'global', label: __( 'Use global setting', 'formglut' ) }, { value: 'on', label: __( 'On for this form', 'formglut' ) }, { value: 'off', label: __( 'Off for this form', 'formglut' ) }] },
        { path: 'spam.akismet', type: 'switch', label: __( 'Check with Akismet', 'formglut' ), tip: __( 'Needs the Akismet plugin with an API key. Spam is saved in the Spam folder.', 'formglut' ), note: (s) => s.spam.akismet && !(window.formglut_admin && window.formglut_admin.akismet_ready) ? __( 'Akismet is not active or has no API key on this site, so this check is skipped.', 'formglut' ) : '' },
        { path: 'spam.stopforumspam', type: 'switch', label: __( 'Check with Stop Forum Spam', 'formglut' ), tip: __( 'Free service that lists known spammers. The visitor’s email and IP address are sent to stopforumspam.com; listed submissions go to the Spam folder. Mention this in your privacy policy.', 'formglut' ) },
        { path: 'spam.keywords', type: 'textarea', rows: 4, label: __( 'Blocked words', 'formglut' ), tip: __( 'One word or phrase per line. Whole words only, not case-sensitive.', 'formglut' ) },
        { path: 'spam.keyword_action', type: 'select', label: __( 'When a blocked word is found', 'formglut' ), options: [{ value: 'reject', label: __( 'Reject the submission', 'formglut' ) }, { value: 'spam', label: __( 'Save it as spam', 'formglut' ) }], show: (s) => s.spam.keywords.trim() !== '' },
        { path: 'spam.rate_limit', type: 'number', label: __( 'Max submissions per visitor per hour', 'formglut' ), tip: __( '0 = no limit. Counts by IP address.', 'formglut' ) },
        { path: 'spam.referrer_check', type: 'switch', label: __( 'Only accept submissions from this site', 'formglut' ), tip: __( 'Rejects submissions that were not sent from a page on your website.', 'formglut' ) },
        { path: 'spam.min_time', type: 'number', label: __( 'Minimum time to fill (seconds)', 'formglut' ), tip: __( '0 = off. Faster submissions are treated as bots.', 'formglut' ) },
        { path: 'spam.store_entries', type: 'select', label: __( 'Save entries', 'formglut' ), options: [{ value: 'global', label: __( 'Use global setting', 'formglut' ) }, { value: 'save', label: __( 'Always save', 'formglut' ) }, { value: 'email_only', label: __( 'Email only, do not save', 'formglut' ) }] },
        { path: 'spam.store_ip', type: 'switch', label: __( 'Store IP address and browser', 'formglut' ) },
        { path: 'spam.retention_days', type: 'number', label: __( 'Delete entries after (days)', 'formglut' ), tip: __( '0 keeps entries forever.', 'formglut' ) },
      ],
    },
    {
      key: 'style', title: __( 'Layout & CSS', 'formglut' ), fields: [
        { path: 'style.form_width', type: 'text', label: __( 'Form width', 'formglut' ), tip: __( 'For example 640px, 100% or 40rem. Empty uses the default.', 'formglut' ), placeholder: '640px' },
        { path: 'style.form_align', type: 'select', label: __( 'Form alignment', 'formglut' ), options: [{ value: 'left', label: __( 'Left', 'formglut' ) }, { value: 'center', label: __( 'Center', 'formglut' ) }, { value: 'right', label: __( 'Right', 'formglut' ) }] },
        { path: 'style.custom_js', type: 'code', rows: 5, label: __( 'JavaScript after submit', 'formglut' ), tip: __( 'Runs in the browser after a successful submission (for example to track a conversion). “event.detail.entryId” holds the entry ID. Only administrators who may add scripts can save this.', 'formglut' ) },
        { path: 'style.custom_css', type: 'code', rows: 6, label: __( 'Custom CSS', 'formglut' ), tip: __( 'Use {form} for this form’s wrapper, e.g. {form} .formglut-label { color: red; }', 'formglut' ) },
      ],
    },
    {
      key: 'multistep', title: __( 'Multi-step', 'formglut' ), fields: [
        { path: 'multistep.progress', type: 'select', label: __( 'Progress indicator', 'formglut' ), tip: __( 'Shown when the form has Step Break fields.', 'formglut' ), options: [{ value: 'steps', label: __( 'Numbered steps', 'formglut' ) }, { value: 'bar', label: __( 'Progress bar', 'formglut' ) }, { value: 'none', label: __( 'None', 'formglut' ) }] },
        { path: 'multistep.first_title', type: 'text', label: __( 'First step title', 'formglut' ), tip: __( 'Each Step Break field sets the title of the step after it.', 'formglut' ), placeholder: __( 'Step 1', 'formglut' ) },
        { path: 'multistep.validate_step', type: 'switch', label: __( 'Check each step before moving on', 'formglut' ), tip: __( 'Visitors must fix errors on a step before they can go to the next one.', 'formglut' ) },
      ],
    },
    {
      key: 'integrations', title: __( 'Integrations', 'formglut' ), fields: [
        { path: 'integrations.webhook_enabled', type: 'switch', label: __( 'Send entries to a webhook', 'formglut' ), tip: __( 'Posts every submission to a URL, for example a Zapier, Make or n8n webhook.', 'formglut' ) },
        { path: 'integrations.webhook_url', type: 'text', label: __( 'Webhook URL', 'formglut' ), placeholder: 'https://hooks.example.com/…', show: (s) => s.integrations.webhook_enabled },
        { path: 'integrations.webhook_format', type: 'select', label: __( 'Format', 'formglut' ), options: [{ value: 'json', label: 'JSON' }, { value: 'form', label: __( 'Form data', 'formglut' ) }], show: (s) => s.integrations.webhook_enabled },
        { path: 'integrations.slack_enabled', type: 'switch', label: __( 'Post new entries to Slack', 'formglut' ), tip: __( 'Uses a Slack “Incoming Webhook” URL for the channel you want.', 'formglut' ), divider: true },
        { path: 'integrations.slack_webhook', type: 'text', label: __( 'Slack webhook URL', 'formglut' ), placeholder: 'https://hooks.slack.com/services/…', show: (s) => s.integrations.slack_enabled },
        { path: 'integrations.slack_message', type: 'textarea', tags: 'plain', label: __( 'Slack message', 'formglut' ), tip: __( 'Empty sends the form name and all fields.', 'formglut' ), show: (s) => s.integrations.slack_enabled },
        { path: 'integrations.discord_enabled', type: 'switch', label: __( 'Post new entries to Discord', 'formglut' ), tip: __( 'In Discord: Server Settings › Integrations › Webhooks › New Webhook, then copy its URL.', 'formglut' ), divider: true },
        { path: 'integrations.discord_webhook', type: 'text', label: __( 'Discord webhook URL', 'formglut' ), placeholder: 'https://discord.com/api/webhooks/…', show: (s) => s.integrations.discord_enabled, note: (s) => s.integrations.discord_enabled && s.integrations.discord_webhook && !/^https:\/\/([a-z0-9-]+\.)?discord(app)?\.com\//i.test(s.integrations.discord_webhook) ? __( 'This does not look like a Discord webhook URL. It will be cleared when you save.', 'formglut' ) : '' },
        { path: 'integrations.discord_message', type: 'textarea', tags: 'plain', label: __( 'Discord message', 'formglut' ), tip: __( 'Empty sends the form name and all fields. Mentions such as @everyone are never triggered.', 'formglut' ), show: (s) => s.integrations.discord_enabled },
        { path: 'integrations.telegram_enabled', type: 'switch', label: __( 'Send new entries to Telegram', 'formglut' ), tip: __( 'Create a bot with @BotFather, add it to your group or channel, then enter its token and the chat ID.', 'formglut' ), divider: true },
        { path: 'integrations.telegram_bot_token', type: 'text', label: __( 'Bot token', 'formglut' ), placeholder: '123456789:AA…', show: (s) => s.integrations.telegram_enabled },
        { path: 'integrations.telegram_chat_id', type: 'text', label: __( 'Chat ID', 'formglut' ), tip: __( 'A number such as -1001234567890, or @channelname for a public channel.', 'formglut' ), show: (s) => s.integrations.telegram_enabled },
        { path: 'integrations.telegram_message', type: 'textarea', tags: 'plain', label: __( 'Telegram message', 'formglut' ), tip: __( 'Empty sends the form name and all fields.', 'formglut' ), show: (s) => s.integrations.telegram_enabled },
        { path: 'integrations.teams_enabled', type: 'switch', label: __( 'Post new entries to Microsoft Teams', 'formglut' ), tip: __( 'In Teams: add the Workflows template “Post to a channel when a webhook request is received” and copy its URL.', 'formglut' ), divider: true },
        { path: 'integrations.teams_webhook', type: 'text', label: __( 'Teams webhook URL', 'formglut' ), placeholder: 'https://….logic.azure.com/…', show: (s) => s.integrations.teams_enabled },
        { path: 'integrations.teams_message', type: 'textarea', tags: 'plain', label: __( 'Teams message', 'formglut' ), tip: __( 'Empty sends the form name and all fields.', 'formglut' ), show: (s) => s.integrations.teams_enabled },
      ],
    },
    {
      key: 'mailchimp', title: __( 'Mailchimp', 'formglut' ), fields: [
        { path: 'mailchimp.enabled', type: 'switch', label: __( 'Add people to a Mailchimp audience', 'formglut' ), tip: __( 'Uses the Mailchimp API key from FormGlut › Settings › Integrations. People who are already in the audience are updated, not added twice.', 'formglut' ) },
        { path: 'mailchimp.list_id', type: 'component', label: __( 'Audience', 'formglut' ), render: ({ value, onChange }) => <MailchimpAudience value={value} onChange={onChange} />, show: (s) => s.mailchimp.enabled },
        { path: 'mailchimp.email_field', type: 'select', label: __( 'Email field', 'formglut' ), options: emailOptions, show: (s) => s.mailchimp.enabled, note: (s) => s.mailchimp.enabled && !s.mailchimp.email_field ? __( 'Choose the Email field, or nobody is added.', 'formglut' ) : '' },
        { path: 'mailchimp.first_name_field', type: 'select', label: __( 'First name field', 'formglut' ), tip: __( 'A Name field works too: it is split into first and last name.', 'formglut' ), options: fieldOptions, show: (s) => s.mailchimp.enabled },
        { path: 'mailchimp.last_name_field', type: 'select', label: __( 'Last name field', 'formglut' ), options: fieldOptions, show: (s) => s.mailchimp.enabled },
        { path: 'mailchimp.tags', type: 'text', label: __( 'Tags', 'formglut' ), tip: __( 'Comma-separated, e.g. website, newsletter.', 'formglut' ), show: (s) => s.mailchimp.enabled },
        { path: 'mailchimp.double_optin', type: 'switch', label: __( 'Double opt-in', 'formglut' ), tip: __( 'Mailchimp emails new people a link to confirm before they are subscribed.', 'formglut' ), show: (s) => s.mailchimp.enabled },
        { path: 'mailchimp.consent_field', type: 'select', label: __( 'Only when this field is filled', 'formglut' ), tip: __( 'For example a GDPR or “Subscribe me” checkbox. Leave empty to add everyone.', 'formglut' ), options: fieldOptions, show: (s) => s.mailchimp.enabled },
      ],
    },
    {
      key: 'polls', title: __( 'Poll results', 'formglut' ), fields: [
        { path: 'polls.show_results', type: 'switch', label: __( 'Show results after voting', 'formglut' ), tip: __( 'After a successful submit, the message shows a bar for each answer with its share of the votes. Results come from saved entries (spam and trash are left out).', 'formglut' ) },
        { path: 'polls.fields', type: 'component', label: __( 'Questions', 'formglut' ), tip: __( 'Radio, Checkbox and Dropdown fields. Leave empty to show all of them.', 'formglut' ), show: (s) => s.polls.show_results, render: ({ value, onChange }) => (
          <Select mode="multiple" allowClear value={Array.isArray(value) ? value : []} onChange={onChange} placeholder={__( 'All choice fields', 'formglut' )} style={{ width: '100%' }}
            options={(extra.fields || []).filter((f) => ['radio', 'checkbox', 'select', 'multiselect'].includes(f.type)).map((f) => ({ value: f.id, label: f.admin_label || f.label || f.id }))} />
        ) },
        { path: 'polls.show_counts', type: 'switch', label: __( 'Show the number of votes', 'formglut' ), show: (s) => s.polls.show_results },
      ],
    },
    {
      key: 'registration', title: __( 'User registration', 'formglut' ), fields: [
        { path: 'registration.enabled', type: 'switch', label: __( 'Create a WordPress account', 'formglut' ), tip: __( 'For visitors who are not logged in. New users get the role set in Settings › General › New User Default Role (Subscriber if that role could manage the site).', 'formglut' ) },
        { path: 'registration.email_field', type: 'select', label: __( 'Email field', 'formglut' ), options: emailOptions, show: (s) => s.registration.enabled, note: (s) => s.registration.enabled && !s.registration.email_field ? __( 'Choose the Email field, or no account is created.', 'formglut' ) : '' },
        { path: 'registration.username_field', type: 'select', label: __( 'Username field', 'formglut' ), tip: __( 'Empty makes the username from the email address.', 'formglut' ), options: fieldOptions, show: (s) => s.registration.enabled },
        { path: 'registration.password_field', type: 'select', label: __( 'Password field', 'formglut' ), tip: __( 'Empty: WordPress emails a link to set a password. FormGlut never stores passwords in entries.', 'formglut' ), options: [{ value: '', label: __( '— None —', 'formglut' ) }, ...(extra.fields || []).filter((f) => f.type === 'password').map((f) => ({ value: f.id, label: f.admin_label || f.label || f.id }))], show: (s) => s.registration.enabled },
        { path: 'registration.first_name_field', type: 'select', label: __( 'First name field', 'formglut' ), tip: __( 'A Name field works too: it is split into first and last name.', 'formglut' ), options: fieldOptions, show: (s) => s.registration.enabled },
        { path: 'registration.last_name_field', type: 'select', label: __( 'Last name field', 'formglut' ), options: fieldOptions, show: (s) => s.registration.enabled },
        { path: 'registration.auto_login', type: 'switch', label: __( 'Log the new user in', 'formglut' ), tip: __( 'Works when the form has a Password field.', 'formglut' ), show: (s) => s.registration.enabled },
      ],
    },
    {
      key: 'save_progress', title: __( 'Save progress', 'formglut' ), fields: [
        { path: 'save_progress.enabled', type: 'switch', label: __( 'Remember answers on the visitor’s device', 'formglut' ), tip: __( 'Answers are kept in the visitor’s browser while they type and filled back in when they return (up to 30 days). Passwords, files, card details and signatures are never kept. Cleared after a successful submit.', 'formglut' ) },
        { path: 'save_progress.message', type: 'text', label: __( 'Welcome-back message', 'formglut' ), placeholder: __( 'Welcome back! We filled in the answers you saved on this device.', 'formglut' ), show: (s) => s.save_progress.enabled },
      ],
    },
    {
      key: 'share', title: __( 'Share & gate', 'formglut' ), fields: [
        { path: 'share.enabled', type: 'switch', label: __( 'Turn on the share page', 'formglut' ), tip: __( 'A clean page with only this form, for links in emails and social posts. It is hidden from search engines.', 'formglut' ) },
        { path: 'share.link', type: 'component', label: __( 'Link', 'formglut' ), render: ({ settings }) => <ShareLink formId={extra.formId} enabled={!!(settings.share && settings.share.enabled)} /> },
        { path: 'share.description', type: 'textarea', label: __( 'Text under the title', 'formglut' ), show: (s) => s.share.enabled },
        { path: 'share.gate', type: 'component', label: __( 'Gated content', 'formglut' ), divider: true, tip: __( 'Hide part of a page until the visitor submits this form, e.g. a download or a video. Paste this shortcode in the page and put the hidden content between the two tags. After a successful submit the page reloads and shows it for the number of days you set (on that browser).', 'formglut' ), render: () => <GateCode formId={extra.formId} /> },
      ],
    },
    {
      key: 'entries', title: __( 'Entries & analytics', 'formglut' ), fields: [
        { path: 'entries.count_views', type: 'switch', label: __( 'Count form views', 'formglut' ) },
      ],
    },
  ].filter((section) => !HIDDEN_SECTIONS.includes(section.key)), { emailFields, inputFields, hasUploads, ...extra });
}

export const getIn = (obj, path) => path.split('.').reduce((o, k) => (o ? o[k] : undefined), obj);
export const setIn = (obj, path, value) => {
  const keys = path.split('.');
  const next = { ...obj };
  let cur = next;
  keys.slice(0, -1).forEach((k) => { cur[k] = { ...cur[k] }; cur = cur[k]; });
  cur[keys[keys.length - 1]] = value;
  return next;
};

/** Classic WordPress editor (TinyMCE + Text tab). Falls back to a plain textarea if wp.editor is missing. */
function WpEditor({ id, value, onChange }) {
  const current = useRef(value || '');
  const cb = useRef(onChange);
  cb.current = onChange;

  useEffect(() => {
    const wpEditor = window.wp && window.wp.editor;
    const ta = document.getElementById(id);
    const emit = (v) => { if (v !== current.current) { current.current = v; cb.current(v); } };
    const onText = () => emit(ta.value);
    ta.addEventListener('input', onText);
    if (wpEditor) {
      wpEditor.initialize(id, {
        tinymce: {
          wpautop: true, height: 220,
          toolbar1: 'formatselect,bold,italic,underline,bullist,numlist,blockquote,alignleft,aligncenter,alignright,link,forecolor,undo,redo',
          setup: (ed) => ed.on('change keyup input undo redo ExecCommand', () => emit(ed.getContent())),
        },
        quicktags: true,
        mediaButtons: true,
      });
    }
    return () => { ta.removeEventListener('input', onText); if (wpEditor) wpEditor.remove(id); };
  }, [id]);

  // Outside changes (e.g. a smart tag inserted) are pushed into the editor.
  useEffect(() => {
    const v = value || '';
    if (v === current.current) return;
    current.current = v;
    const ed = window.tinymce && window.tinymce.get(id);
    if (ed) ed.setContent(v);
    const ta = document.getElementById(id);
    if (ta) ta.value = v;
  }, [value, id]);

  return <textarea id={id} className="wp-editor-area" defaultValue={value || ''} rows={8} style={{ width: '100%' }} />;
}

/** The input for one setting, without its label. */
export function FieldInput({ f, value, onChange, settings }) {
  switch (f.type) {
    case 'component':
      return f.render ? f.render({ value, onChange, settings }) : null;
    case 'switch':
      return <Switch checked={!!value} onChange={onChange} />;
    case 'select':
      return <Select value={value} onChange={onChange} options={f.options} style={{ width: '100%' }} />;
    case 'search-select':
      return <Select showSearch allowClear optionFilterProp="label" value={value || undefined} placeholder={f.placeholder} onChange={(v) => onChange(v || 0)} options={f.options} notFoundContent={__( 'Nothing published yet', 'formglut' )} style={{ width: '100%' }} />;
    case 'editor':
      return <WpEditor id={'fg-editor-' + f.path.replace(/\W/g, '-')} value={value} onChange={onChange} />;
    case 'number':
      return <InputNumber min={0} value={value} onChange={(v) => onChange(v || 0)} style={{ width: '100%' }} />;
    case 'textarea':
      return <Input.TextArea rows={f.rows || 3} value={value} onChange={(e) => onChange(e.target.value)} />;
    case 'code':
      return <Input.TextArea rows={f.rows || 6} value={value} onChange={(e) => onChange(e.target.value)} spellCheck={false} style={{ fontFamily: 'ui-monospace, Menlo, monospace', fontSize: 12 }} />;
    case 'datetime':
      return <Input type="datetime-local" value={value} onChange={(e) => onChange(e.target.value)} />;
    default:
      return <Input value={value} placeholder={f.placeholder} onChange={(e) => onChange(e.target.value)} />;
  }
}
