import React, { CSSProperties } from 'react';
import { useNode, UserComponent } from '@craftjs/core';
import { cssPropsToString } from '../../utils/style-helpers';
import { relayFormWiring } from '../../utils/form-relay-wiring';
import { escapeHtml, escapeAttr, slugId, cssValue, sanitizeInputType } from '../../utils/escape';

// The allowlist enforced at export time lives in `sanitizeInputType`
// (utils/escape.ts) -- this union is a superset (it also covers 'textarea'
// and 'select', which take their own render branches instead of an
// `<input type>`), kept in sync by hand since TS unions can't import a
// runtime array.
export type ContactFormFieldType =
  | 'text' | 'email' | 'tel' | 'number' | 'password' | 'url' | 'search' | 'date'
  | 'checkbox' | 'radio' | 'textarea' | 'select';

interface ContactFormField {
  type: ContactFormFieldType;
  label: string;
  name: string;
  placeholder: string;
  required: boolean;
  options?: string[];
}

interface ContactFormProps {
  fields?: ContactFormField[];
  submitText?: string;
  submitColor?: string;
  formAction?: string;
  successMessage?: string;
  style?: CSSProperties;
  labelColor?: string;
  inputBg?: string;
  inputBorder?: string;
  recipientEmail?: string;
  thankYouUrl?: string;
  /* ---- Submission destination (see utils/form-relay-wiring.ts) ----
     'email' (default) reproduces the legacy marker exactly. 'webhook' widens it
     with the url / secret id / auth mode below.
     There is deliberately NO raw-secret prop: craft props are serialised into
     the saved project and into published output, so the secret is POSTed to
     /api/form-webhook-secret.php and only the returned opaque id is kept. */
  destinationType?: 'email' | 'webhook';
  webhookUrl?: string;
  webhookSecretId?: string;
  webhookAuthMode?: 'signature' | 'bearer';
  animation?: string;
  animationDelay?: string;
  hideOnDesktop?: boolean;
  hideOnTablet?: boolean;
  hideOnMobile?: boolean;
}

const defaultFields: ContactFormField[] = [
  { type: 'text', label: 'Name', name: 'name', placeholder: 'Your name', required: true },
  { type: 'email', label: 'Email', name: 'email', placeholder: 'your@email.com', required: true },
  { type: 'tel', label: 'Phone', name: 'phone', placeholder: '(555) 123-4567', required: false },
  { type: 'textarea', label: 'Message', name: 'message', placeholder: 'How can we help you?', required: true },
];

export const ContactForm: UserComponent<ContactFormProps> = ({
  fields = defaultFields,
  submitText = 'Send Message',
  submitColor = '#3b82f6',
  formAction = '#',
  successMessage = 'Thank you! We\'ll get back to you soon.',
  style = {},
  labelColor = '#374151',
  inputBg = '#ffffff',
  inputBorder = '#d1d5db',
}) => {
  const {
    connectors: { connect, drag },
    selected,
  } = useNode((node) => ({
    selected: node.events.selected,
  }));

  const inputBaseStyle: CSSProperties = {
    width: '100%',
    padding: '10px 14px',
    fontSize: '14px',
    fontFamily: 'Inter, sans-serif',
    border: `1px solid ${inputBorder}`,
    borderRadius: '6px',
    backgroundColor: inputBg,
    color: '#1f2937',
    boxSizing: 'border-box',
    outline: 'none',
  };

  return (
    <form
      ref={(ref: HTMLFormElement | null): void => { if (ref) connect(drag(ref)); }}
      action={formAction}
      method="POST"
      onSubmit={(e) => e.preventDefault()}
      style={{
        padding: '32px',
        display: 'flex',
        flexDirection: 'column',
        gap: '20px',
        outline: selected ? '2px solid #3b82f6' : 'none',
        ...style,
      }}
    >
      {fields.map((field, i) => (
        <div key={i} style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>
          <label style={{ fontSize: '14px', fontWeight: '500', color: labelColor }}>
            {field.label}
            {field.required && <span style={{ color: '#ef4444', marginLeft: '2px' }}>*</span>}
          </label>
          {field.type === 'textarea' ? (
            <textarea
              name={field.name}
              placeholder={field.placeholder}
              required={field.required}
              rows={4}
              style={{ ...inputBaseStyle, resize: 'vertical' }}
            />
          ) : field.type === 'select' ? (
            <select
              name={field.name}
              required={field.required}
              style={{ ...inputBaseStyle, cursor: 'pointer' }}
            >
              <option value="">{field.placeholder || 'Select...'}</option>
              {(field.options || []).map((opt, j) => (
                <option key={j} value={opt}>{opt}</option>
              ))}
            </select>
          ) : (
            <input
              type={field.type}
              name={field.name}
              placeholder={field.placeholder}
              required={field.required}
              style={inputBaseStyle}
            />
          )}
        </div>
      ))}
      <button
        type="submit"
        style={{
          padding: '12px 32px',
          fontSize: '16px',
          fontWeight: '600',
          fontFamily: 'Inter, sans-serif',
          color: '#ffffff',
          backgroundColor: submitColor,
          border: 'none',
          borderRadius: '8px',
          cursor: 'pointer',
          alignSelf: 'flex-start',
        }}
      >
        {submitText}
      </button>
    </form>
  );
};

/* ---------- Craft config ---------- */

ContactForm.craft = {
  displayName: 'Contact Form',
  props: {
    fields: defaultFields,
    submitText: 'Send Message',
    submitColor: '#3b82f6',
    formAction: '#',
    successMessage: 'Thank you! We\'ll get back to you soon.',
    style: {
      backgroundColor: '#ffffff',
      borderRadius: '12px',
      border: '1px solid #e5e7eb',
    },
    labelColor: '#374151',
    inputBg: '#ffffff',
    inputBorder: '#d1d5db',
    recipientEmail: '',
    thankYouUrl: '',
    // Present (not omitted) so FormStylePanel's `nodeProps.X !== undefined`
    // gates actually render the destination controls.
    destinationType: 'email',
    webhookUrl: '',
    webhookSecretId: '',
    webhookAuthMode: 'signature',
    animation: '',
    animationDelay: '',
    hideOnDesktop: false,
    hideOnTablet: false,
    hideOnMobile: false,
  },
  rules: {
    canDrag: () => true,
    canMoveIn: () => false,
    canMoveOut: () => true,
  },
};

/* ---------- HTML export ---------- */

(ContactForm as any).toHtml = (props: ContactFormProps, _childrenHtml: string, nodeId?: string) => {
  const formStyle = cssPropsToString({
    padding: '32px',
    display: 'flex',
    flexDirection: 'column',
    gap: '20px',
    ...props.style,
  });
  // Sanitized -- raw string-interpolation sinks in inputStyleStr/labelHtml
  // below.
  const labelColor = cssValue(props.labelColor) || '#374151';
  const inputBg = cssValue(props.inputBg) || '#ffffff';
  const inputBorder = cssValue(props.inputBorder) || '#d1d5db';
  const inputStyleStr = `width:100%;padding:10px 14px;font-size:14px;font-family:Inter,sans-serif;border:1px solid ${inputBorder};border-radius:6px;background-color:${inputBg};color:#1f2937;box-sizing:border-box;outline:none`;

  const fieldsHtml = (props.fields || defaultFields).map((field, i) => {
    const reqStar = field.required ? '<span style="color:#ef4444;margin-left:2px">*</span>' : '';
    // Deterministic id: index + slugified name, so repeated fields with the
    // same name (or no name) still get unique, stable ids -- no Math.random.
    const fieldId = `field-${i}-${slugId(field.name)}`;
    const labelHtml = `<label for="${escapeAttr(fieldId)}" style="font-size:14px;font-weight:500;color:${labelColor}">${escapeHtml(field.label)}${reqStar}</label>`;
    const reqAttr = field.required ? ' required' : '';
    let inputHtml = '';
    if (field.type === 'textarea') {
      inputHtml = `<textarea id="${escapeAttr(fieldId)}" name="${escapeAttr(field.name)}" placeholder="${escapeAttr(field.placeholder)}" rows="4" style="${inputStyleStr};resize:vertical"${reqAttr}></textarea>`;
    } else if (field.type === 'select') {
      const opts = (field.options || []).map((o) => `<option value="${escapeAttr(o)}">${escapeHtml(o)}</option>`).join('');
      inputHtml = `<select id="${escapeAttr(fieldId)}" name="${escapeAttr(field.name)}" style="${inputStyleStr};cursor:pointer"${reqAttr}><option value="">${escapeHtml(field.placeholder || 'Select...')}</option>${opts}</select>`;
    } else {
      inputHtml = `<input id="${escapeAttr(fieldId)}" type="${sanitizeInputType(field.type)}" name="${escapeAttr(field.name)}" placeholder="${escapeAttr(field.placeholder)}" style="${inputStyleStr}"${reqAttr} />`;
    }
    return `<div style="display:flex;flex-direction:column;gap:6px">${labelHtml}${inputHtml}</div>`;
  }).join('\n  ');

  const btnStyle = cssPropsToString({
    padding: '12px 32px',
    fontSize: '16px',
    fontWeight: '600',
    fontFamily: 'Inter, sans-serif',
    color: '#ffffff',
    backgroundColor: props.submitColor || '#3b82f6',
    border: 'none',
    borderRadius: '8px',
    cursor: 'pointer',
    alignSelf: 'flex-start',
  });

  // Only the webhook SECRET ID travels here -- there is no prop holding the raw
  // secret, by construction (see ContactFormProps).
  const { marker, actionAttr, honeypot } = relayFormWiring(
    props.recipientEmail, props.thankYouUrl, props.formAction, nodeId,
    {
      type: props.destinationType,
      url: props.webhookUrl,
      secretId: props.webhookSecretId,
      authMode: props.webhookAuthMode,
    },
  );

  // The form-sender relay delivers success via a full-page 303 redirect
  // (to thankYouUrl or a hosted thanks.php page) -- there is no in-page JS
  // that reveals an inline success element today. Emit successMessage as a
  // forward-compatible data attribute so a future AJAX/JS submission mode
  // can read it, without implying a live mechanism that doesn't exist yet.
  const successAttr = props.successMessage ? ` data-whp-success-message="${escapeAttr(props.successMessage)}"` : '';

  return {
    html: `${marker}<form action="${actionAttr}" method="POST"${successAttr}${formStyle ? ` style="${formStyle}"` : ''}>
${honeypot ? `  ${honeypot}\n` : ''}${fieldsHtml ? `  ${fieldsHtml}\n` : ''}  <button type="submit"${btnStyle ? ` style="${btnStyle}"` : ''}>${escapeHtml(props.submitText || 'Send Message')}</button>
</form>`,
  };
};
