import { useRef, useState } from 'react';

import type {
  FormConfigField,
  FormConfigSubmit,
  FormCustomField,
  FormFieldConfig,
  FormPresetField,
} from '~/src/ui/components/form';
import type { FormBuilderConfig } from './types';

import PlusIconWrapper from '~/src/components/Icon/PlusIcon';
import useIsLargeScreen from '~/src/hooks/useIsLargeScreen';
import { useI18n } from '~/src/lib/i18n';
import { DraggableContainer } from '~/src/ui/components/draggable';
import { Drawer } from '~/src/ui/components/drawer';
import { isPrivacyField } from '~/src/ui/components/form';
import { Layout } from '~/src/ui/layouts/layout';
import { LayoutGrid } from '~/src/ui/layouts/layoutGrid';
import { Button } from '~/src/ui/primitives/button';
import { Text } from '~/src/ui/primitives/text';
import { CustomFields } from './CustomFields';
import { FieldPresets } from './FieldPresets';
import { FormFieldEdit } from './FormFieldEdit';
import { FormSubmitEdit } from './FormSubmitEdit';
import { formBuilderStyles } from './styles';
import { cleanFieldConfig } from './utils';

export interface FormBuilderProps {
  defaultConfig?: FormBuilderConfig;
  onConfigChange?: (config: FormBuilderConfig) => void;
}

export const FormBuilder = ({
  defaultConfig = {},
  onConfigChange,
}: FormBuilderProps) => {
  const { t } = useI18n('formBuilder');

  const isLargeScreen = useIsLargeScreen();
  const [isPresetsOpen, setIsPresetsOpen] = useState(false);

  // Consent checkbox fields are configured in the dedicated privacy stage, not
  // here. Keep them out of the editable list/palette but preserve them so they
  // survive a round-trip through the builder (e.g. navigating back a step).
  const consentFields = useRef<FormConfigField[]>(
    (defaultConfig.fields ?? []).filter(isPrivacyField)
  );

  const config = useRef<FormBuilderConfig>({
    ...defaultConfig,
    fields: (defaultConfig.fields ?? []).filter((f) => !isPrivacyField(f)),
  });

  const [selectedFields, setSelectedFields] = useState<FormConfigField[]>(
    config.current.fields ?? []
  );

  const persist = () => {
    onConfigChange?.({
      ...config.current,
      fields: [...(config.current.fields ?? []), ...consentFields.current],
    });
  };

  const handleFieldChange = (fieldName: string, updates: FormFieldConfig) => {
    config.current.fields = config.current.fields?.map((field) =>
      field.name === fieldName ? cleanFieldConfig(field, updates) : field
    );

    persist();
  };

  const handleFieldDelete = (field: FormConfigField) => {
    config.current.fields = config.current.fields?.filter(
      (f) => f.name !== field.name
    );
    setSelectedFields((prev) => prev.filter((f) => f.name !== field.name));
    persist();
  };

  const handleSubmitChange = (data: FormConfigSubmit) => {
    config.current = {
      ...config.current,
      submit: data.label
        ? {
            label: data.label,
          }
        : {},
    };

    persist();
  };

  const updateCurrentFields = (fields: FormConfigField[]) => {
    config.current.fields = fields.map((field) => {
      const existing = config.current.fields?.find(
        (existingField) => existingField.name === field.name
      );

      return existing ?? field;
    });

    persist();
  };

  const togglePreset = (preset: FormPresetField) => {
    setSelectedFields((prev) => {
      let updated = prev;

      if (prev.some((f) => f.name === preset.name)) {
        updated = prev.filter((f) => f.name !== preset.name);
      } else {
        updated = [...prev, preset];
      }

      updateCurrentFields(updated);

      return updated;
    });
  };

  const addCustomField = (field: FormCustomField) => {
    setSelectedFields((prev) => {
      const updated = [...prev, field];

      updateCurrentFields(updated);

      return updated;
    });
  };

  const handleReorder = (fields: FormConfigField[]) => {
    setSelectedFields(fields);
    updateCurrentFields(fields);
  };

  const currentFields = config.current.fields ?? [];

  const presetsBody = (
    <Layout column gap="6">
      <FieldPresets selectedFields={selectedFields} onSelected={togglePreset} />
      <Layout column gap="4">
        <Text variant="title-4">{t('customFields')}</Text>
        <CustomFields onSelected={addCustomField} />
      </Layout>
    </Layout>
  );

  return (
    <LayoutGrid rowGap="4">
      {isLargeScreen ? (
        <>
          <Layout span="12">
            <Text variant="title-4">{t('fieldPresets')}</Text>
          </Layout>
          <Layout column gap="6" span="4">
            {presetsBody}
          </Layout>
        </>
      ) : (
        <Layout column span="12">
          <Button
            variant="default"
            style={formBuilderStyles.presetsTrigger}
            onClick={() => setIsPresetsOpen(true)}
          >
            <Layout align="center" justify="center" gap="2">
              <PlusIconWrapper size={24} />
              {t('fieldPresets')}
            </Layout>
          </Button>
          <Drawer
            open={isPresetsOpen}
            onClose={() => setIsPresetsOpen(false)}
            title={t('fieldPresets')}
          >
            {presetsBody}
          </Drawer>
        </Layout>
      )}
      <Layout column gap="6" span={isLargeScreen ? '8' : '12'}>
        {currentFields.length > 0 && (
          <Layout column gap="3" shrink>
            <DraggableContainer items={currentFields} onChange={handleReorder}>
              {(item) => (
                <FormFieldEdit
                  field={item}
                  onChange={(fieldConfig) =>
                    handleFieldChange(item.name, fieldConfig)
                  }
                  onDelete={() => {
                    handleFieldDelete(item);
                  }}
                />
              )}
            </DraggableContainer>
          </Layout>
        )}

        <FormSubmitEdit
          label={config.current.submit?.label}
          onChange={handleSubmitChange}
        />
      </Layout>
    </LayoutGrid>
  );
};
