import {
  Button,
  Loader,
  ModalSize,
  VariantType,
  useToastProvider,
} from '@gouvfr-lasuite/cunningham-react';
import { standardSchemaResolver } from '@hookform/resolvers/standard-schema';
import React, { useState } from 'react';
import { Controller, FormProvider, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { z } from 'zod';

import { parseAPIError } from '@/api/parseAPIError';
import {
  Box,
  HorizontalSeparator,
  Input,
  Text,
  TextErrors,
} from '@/components';
import { CustomModal } from '@/components/modal/CustomModal';
import { useCunninghamTheme } from '@/cunningham';

import { MailDomain } from '../../domains/types';
import { CreateMailboxParams, useCreateMailbox } from '../api';

const FORM_ID = 'form-create-mailbox';

type LocalPartInputProps = React.InputHTMLAttributes<HTMLInputElement> & {
  label: string;
  domain: string;
  error?: string;
  required?: boolean;
};

const LocalPartInput = ({
  label,
  domain,
  error,
  required,
  ...inputProps
}: LocalPartInputProps) => {
  const { colorsTokens } = useCunninghamTheme();
  const borderColor = error
    ? colorsTokens()['error-500']
    : 'var(--c--contextuals--border--semantic--neutral--tertiary)';

  return (
    <Box>
      <Box $margin={{ bottom: 'sm' }}>
        <label
          htmlFor="local_part"
          style={{ fontWeight: 500, color: colorsTokens()['gray-900'] }}
        >
          {label} {required && '*'}
        </label>
      </Box>
      <div
        style={{
          display: 'flex',
          flexDirection: 'row',
          flexWrap: 'nowrap',
          alignItems: 'stretch',
          border: `1px solid ${borderColor}`,
          borderRadius: 4,
          overflow: 'hidden',
          background: colorsTokens()['gray-000'],
        }}
      >
        <input
          id="local_part"
          aria-required={required}
          required={required}
          style={{
            flex: '1 1 0',
            minWidth: 0,
            padding: '12px',
            border: 'none',
            borderRadius: 0,
            fontSize: 14,
            background: 'transparent',
            color: colorsTokens()['gray-550'],
            outline: 'none',
          }}
          {...inputProps}
        />
        <span
          style={{
            display: 'inline-flex',
            alignItems: 'center',
            flexShrink: 0,
            padding: '12px 12px 12px 0',
            fontSize: 14,
            color: colorsTokens()['gray-550'],
            fontWeight: 500,
            background: 'transparent',
          }}
        >
          @{domain}
        </span>
      </div>
      {error && (
        <Text
          $size="xs"
          $theme="error"
          $variation="secondary"
          $margin={{ top: '2xs' }}
        >
          {error}
        </Text>
      )}
    </Box>
  );
};

export const ModalCreateMailbox = ({
  mailDomain,
  closeModal,
}: {
  mailDomain: MailDomain;
  closeModal: () => void;
}) => {
  const { t } = useTranslation();
  const { toast } = useToastProvider();
  const [errorCauses, setErrorCauses] = useState<string[]>([]);
  const [step] = useState(0);

  const createMailboxValidationSchema = z.object({
    first_name: z.string().min(1, t('Please enter your first name')),
    last_name: z.string().min(1, t('Please enter your last name')),
    local_part: z
      .string()
      .regex(/^((?!@|\s)([a-zA-Z0-9.\-]))*$/, t('Invalid format'))
      .min(1, t('You must have minimum 1 character')),
    secondary_email: z.string().email(t('Please enter a valid email address')),
  });

  const methods = useForm<CreateMailboxParams>({
    resolver: standardSchemaResolver(createMailboxValidationSchema),
    defaultValues: {
      first_name: '',
      last_name: '',
      local_part: '',
      secondary_email: '',
    },
    mode: 'onChange',
  });

  const { mutate: createMailbox, isPending } = useCreateMailbox({
    mailDomainSlug: mailDomain.slug,
    onSuccess: () => {
      toast(t('Mailbox created!'), VariantType.SUCCESS, { duration: 4000 });
      closeModal();
    },
    onError: (error) => {
      const causes =
        parseAPIError({
          error,
          errorParams: [
            [
              ['Mailbox with this Local_part and Domain already exists'],
              t('This email prefix is already used.'),
              undefined,
            ],
            [
              ['Invalid format'],
              t('Invalid format for the email prefix.'),
              undefined,
            ],
          ],
          serverErrorParams: [
            t(
              'An error occurred while creating the mailbox. Please try again.',
            ),
            undefined,
          ],
        }) || [];
      if (causes.length > 0) {
        causes.forEach((cause) => {
          toast(cause, VariantType.ERROR, { duration: 4000 });
        });
      } else {
        toast(t('Mailbox create failed!'), VariantType.ERROR, {
          duration: 4000,
        });
      }
      setErrorCauses(causes);
    },
  });

  const onSubmitCallback = (event: React.FormEvent) => {
    event.preventDefault();
    void methods.handleSubmit((data) =>
      createMailbox({ ...data, mailDomainSlug: mailDomain.slug }),
    )();
  };

  const steps = [
    {
      title: t('New email account'),
      content: (
        <FormProvider {...methods}>
          {!!errorCauses.length && <TextErrors causes={errorCauses} />}
          <form id={FORM_ID} onSubmit={onSubmitCallback}>
            <Box $padding={{ top: 'sm', horizontal: 'md' }} $gap="4px">
              <Text $size="md" $weight="bold">
                {t('Personal informations')}
              </Text>
              <Text $theme="gray" $variation="600">
                {t('Configure the new user.')}
              </Text>
            </Box>
            <Box $padding={{ horizontal: 'md' }}>
              <Box $margin={{ top: 'base' }}>
                <Controller
                  name="first_name"
                  control={methods.control}
                  render={({ field, fieldState }) => (
                    <Input
                      {...field}
                      label={t('First name')}
                      placeholder={t('First name')}
                      required
                      error={fieldState.error?.message}
                    />
                  )}
                />
              </Box>
              <Box>
                <Controller
                  name="last_name"
                  control={methods.control}
                  render={({ field, fieldState }) => (
                    <Input
                      {...field}
                      label={t('Last name')}
                      placeholder={t('Last name')}
                      required
                      error={fieldState.error?.message}
                    />
                  )}
                />
              </Box>
              <Box>
                <Controller
                  name="secondary_email"
                  control={methods.control}
                  render={({ field, fieldState }) => (
                    <Input
                      {...field}
                      label={t('Personal email address')}
                      placeholder={t('john.appleseed@free.fr')}
                      required
                      error={fieldState.error?.message}
                    />
                  )}
                />
                <Text $theme="neutral" $variation="tertiary">
                  {t(
                    'The person will receive an email at this address to set up their account.',
                  )}
                </Text>
              </Box>
            </Box>

            <HorizontalSeparator $withPadding={true} />

            <Box $padding={{ top: 'base', horizontal: 'md' }}>
              <Text $size="md" $weight="bold">
                {t('New address')}
              </Text>
            </Box>
            <Box $padding="md">
              <Controller
                name="local_part"
                control={methods.control}
                render={({ field, fieldState }) => (
                  <LocalPartInput
                    label={t('Name of the new address')}
                    domain={mailDomain.name}
                    error={fieldState.error?.message}
                    required
                    {...field}
                  />
                )}
              />
            </Box>
          </form>
        </FormProvider>
      ),
      leftAction: (
        <Button color="neutral" variant="secondary" onClick={closeModal}>
          {t('Cancel')}
        </Button>
      ),
      rightAction: (
        <Button
          type="submit"
          form={FORM_ID}
          disabled={!methods.formState.isValid || isPending}
        >
          {t('Create')}
        </Button>
      ),
    },
  ];

  return (
    <div id="modal-new-mailbox">
      <CustomModal
        isOpen
        hideCloseButton
        step={step}
        totalSteps={steps.length}
        leftActions={steps[step].leftAction}
        rightActions={steps[step].rightAction}
        size={ModalSize.MEDIUM}
        title={steps[step].title}
        onClose={closeModal}
        closeOnEsc
        closeOnClickOutside
      >
        {steps[step].content}
        {isPending && (
          <Box $align="center">
            <Loader />
          </Box>
        )}
      </CustomModal>
    </div>
  );
};
