import { useCallback } from 'react';

import type { FormApi, FormOnSubmit } from '~/src/components/Form';
import type { WithSpacingProps } from '~/src/lib/hocs/withSpacing';
import type {
  MarketingConsentCountry,
  MarketingConsent as MarketingConsentType,
} from '~/src/lib/privacy';
import type { ReactNode, RefObject } from 'react';
import type { CheckboxApi } from '../Checkbox';
import type { CheckboxesConfig, FormValues } from './types';

import Box from '~/src/components/Box';
import Divider from '~/src/components/Divider';
import ErrorText from '~/src/components/ErrorText';
import Form from '~/src/components/Form';
import { useAppAlert } from '~/src/components/NextApp/lib/CoreUi';
import Text from '~/src/components/Text';
import { getMarketingConsentCountry } from '~/src/lib/privacy';
import { MarketingConsentFooter, MarketingConsentForm } from './components';
import { useMarketingConsent } from './useMarketingConsent';
import { mapFormValuesToMarketingConsent } from './utils';

export interface MarketingConsentFooterProps {
  country: MarketingConsentCountry;
  checkboxesRefs: RefObject<Record<string, RefObject<CheckboxApi | null>>>;
  hasOptInAll: boolean;

  render(children: ReactNode): ReactNode;
}

export interface MarketingConsentProps extends WithSpacingProps {
  formApiRef?: RefObject<FormApi | null>;
  artistName: string;
  title: string;
  email?: string;
  country: string;
  checkboxesConfig?: CheckboxesConfig;

  onSubmit(params: {
    formValues: FormValues;
    marketingConsentCountry: MarketingConsentCountry;
    userMarketingConsent: Partial<MarketingConsentType>;
  }): void;

  renderFooter(props: MarketingConsentFooterProps): ReactNode;
}

export const MarketingConsent = ({
  formApiRef,
  artistName,
  title,
  email,
  country: userCountry,
  checkboxesConfig,
  onSubmit,
  renderFooter,
  ...spacingProps
}: MarketingConsentProps) => {
  const country = getMarketingConsentCountry(userCountry);
  const appAlert = useAppAlert();

  const {
    optInCheckboxApiRefs,
    optInCheckboxes,
    optOutCheckboxes,
    optInConfig,
    optOutConfig,
  } = useMarketingConsent({
    country,
    artistName,
    checkboxesConfig,
  });

  const hasCheckboxes = Boolean(optInConfig.length || optOutConfig.length);
  const hasMultipleCheckboxes = optInConfig.length > 1 && !optOutConfig.length;

  const handleSubmit = useCallback<FormOnSubmit<FormValues>>(
    ({ values }) => {
      const emailValue = values.email || email;

      try {
        const userMarketingConsent = mapFormValuesToMarketingConsent(values);

        // TODO: Once we fully migrate to PresaveButtons2 we need to update PutReleaseTaskParams
        // to make email non optional
        if (emailValue) {
          onSubmit({
            formValues: { ...values, email: emailValue },
            userMarketingConsent,
            marketingConsentCountry: country,
          });
        } else {
          throw new Error('Missing email');
        }
      } catch (error) {
        appAlert({
          content: <ErrorText error={error} />,
        });
      }
    },
    [email, country]
  );

  return (
    <Form<FormValues>
      {...spacingProps}
      testId="marketingConsent"
      apiRef={formApiRef}
      onSubmit={handleSubmit}
    >
      {title && (
        <Box
          flexColumn
          centerContent
          style={{ padding: '0 3rem', marginBottom: '2.2rem' }}
        >
          <Text
            size="1.95rem"
            weight="bold"
            lineHeight="1.3em"
            centered
            balance
          >
            {title}
          </Text>
        </Box>
      )}
      <Box flexColumn style={{ gap: hasCheckboxes ? '2.2rem' : '' }}>
        <MarketingConsentForm email={email} country={country} />
        <Box flexColumn style={{ gap: '0.9rem', alignItems: 'flex-start' }}>
          {optInConfig.map((key) => optInCheckboxes[key])}
        </Box>
        {optOutConfig.length > 0 && (
          <>
            <Divider color="#444" />
            <Box flexColumn style={{ gap: '0.9rem' }}>
              {optOutConfig.map((key) => optOutCheckboxes[key])}
            </Box>
          </>
        )}
      </Box>
      {renderFooter({
        country,
        checkboxesRefs: optInCheckboxApiRefs,
        hasOptInAll: hasMultipleCheckboxes,
        render: (children) => (
          <Box flexColumn padding="2.4rem 0" gap="1.6rem">
            {children}
            <MarketingConsentFooter country={country} />
          </Box>
        ),
      })}
    </Form>
  );
};
