import { memo, useCallback, useState } from 'react';

import type { ArtistShow } from '~/lib/songwhipApi/types';
import type { Geolocation } from '~/lib/songwhipLookup/types';
import type { FC } from 'react';
import type { PageSectionComponent } from '../../types';
import type { MappedShow, ShowsSectionItem, ShowsSectionProps } from '../types';

import { AddressTypes } from '~/src/components/AddressInput/types';
import Box from '~/src/components/Box';
import Clickable from '~/src/components/Clickable';
import DateInput from '~/src/components/DateInput';
import DialogBox from '~/src/components/DialogBox';
import { DialogBoxHeader } from '~/src/components/DialogBox/DialogBoxHeader';
import Form from '~/src/components/Form';
import InputLabel from '~/src/components/InputLabel';
import { useEditActions } from '~/src/components/ItemPage/ItemPageEdit/useEditActions';
import Sticky from '~/src/components/Sticky';
import Text from '~/src/components/Text';
import TextInput from '~/src/components/TextInput';
import useHash from '~/src/hooks/useHash';
import { useI18n } from '~/src/lib/i18n';
import AddressInput from '../../../../AddressInput';
import { EditWrapper } from '../../lib/EditWrapper';
import RemoveButton from '../../lib/RemoveButton';
import SectionTitle from '../../lib/SectionTitle';
import ShowListItem from '../ShowListItem';
import { useResolveShows } from '../utils';
import ShowsSettings from './ShowsSettings';

const HASH_PARAM = 'shows';

const ShowsSectionEdit: PageSectionComponent<ShowsSectionProps> = ({
  title,
  items = [],
  sectionPath,
}) => {
  const shows = useResolveShows(items);
  const { hashParams, backToBeforeFirstHash, setHashParam } = useHash();
  const editItemHashParam = `${HASH_PARAM}:${sectionPath}:edit`;
  const editHashValue = hashParams[editItemHashParam];
  const editItemIndex = editHashValue ? Number(editHashValue) : undefined;
  const itemToEdit = editItemIndex !== undefined && shows[editItemIndex];

  const [editGeolocation, setEditGeolocation] = useState<
    Geolocation | undefined
  >();

  const { updateLayoutSection } = useEditActions();
  const { t } = useI18n('itemEdit');

  const onItemClick = useCallback(
    ({ data: { index } }) => {
      setHashParam({ [editItemHashParam]: index });
    },
    [editItemHashParam]
  );

  return (
    <div data-testid="showsEdit">
      <EditWrapper
        padding="1.6rem 1rem 2rem"
        sectionPath={sectionPath}
        renderSettingsContent={useCallback(
          ({ close }) => (
            <ShowsSettings
              title={title}
              sectionPath={sectionPath}
              onSubmit={close}
            />
          ),
          [title]
        )}
      >
        <ShowsSectionEditContent
          title={title}
          items={shows}
          onItemClick={onItemClick}
          sectionPath={sectionPath}
        />
      </EditWrapper>
      {itemToEdit && (
        <DialogBox
          onClose={backToBeforeFirstHash}
          fillViewportOnSmallScreen
          renderContent={({ close, paddingX, paddingY }) => {
            return (
              <Form<{ venueName: string; url: string; localDate: string }>
                testId="editShowForm"
                onSubmit={({ values }) => {
                  const itemsNext = [...shows];

                  itemsNext[editItemIndex] = {
                    ...itemToEdit,
                    venueName: values.venueName,
                    url: values.url,
                    localDate: values.localDate,
                    ...(editGeolocation
                      ? { geolocation: editGeolocation }
                      : {}),
                  };

                  updateLayoutSection({
                    sectionPath,

                    changedProps: {
                      items: itemsNext,
                    },
                  });

                  close();
                }}
              >
                <DialogBoxHeader
                  onCloseClick={close}
                  title={t('shows.edit.title')}
                  renderRight={({ textProps }) => (
                    <Clickable isSubmit>
                      <Text {...textProps}>{t('save')}</Text>
                    </Clickable>
                  )}
                />
                <Box padding={`0 ${paddingX} ${paddingY}`}>
                  <InputLabel value={t('shows.edit.labels.name')}>
                    <TextInput
                      defaultValue={itemToEdit.venueName}
                      name="venueName"
                      placeholder={t('shows.edit.placeholders.name')}
                      required
                    />
                  </InputLabel>
                  <InputLabel
                    value={t('shows.edit.labels.link')}
                    margin="2rem 0 0 0"
                  >
                    <TextInput
                      type={'url'}
                      defaultValue={itemToEdit.url}
                      name="url"
                      placeholder={t('shows.edit.placeholders.link')}
                      required
                    />
                  </InputLabel>
                  <InputLabel
                    value={t('shows.edit.labels.date')}
                    margin="2rem 0 0 0"
                  >
                    <DateInput
                      defaultValue={itemToEdit.localDate}
                      name="localDate"
                      required
                    />
                  </InputLabel>
                  <InputLabel
                    value={t('shows.edit.labels.address')}
                    margin="2rem 0 0 0"
                  >
                    <AddressInput
                      addressType={AddressTypes.ESTABLISHMENT}
                      defaultValue={itemToEdit.geolocation}
                      onChange={(geolocation) => {
                        setEditGeolocation(geolocation);
                      }}
                      required
                    />
                  </InputLabel>
                  <RemoveButton
                    margin={`${paddingX} 0 0`}
                    text={t('shows.edit.remove')}
                    testId="removeShow"
                    onClick={async () => {
                      const itemsNext = [...shows];

                      itemsNext.splice(editItemIndex, 1);

                      await close();

                      updateLayoutSection({
                        sectionPath,

                        changedProps: {
                          items: itemsNext,
                        },
                      });
                    }}
                  />
                </Box>
              </Form>
            );
          }}
        />
      )}
    </div>
  );
};

const ShowsSectionEditContent = memo<{
  items: MappedShow[];
  title: ShowsSectionProps['title'];
  sectionPath: string;
  onItemClick: (params: { data: { index: number } }) => void;
}>(({ items = [], title, sectionPath, onItemClick }) => {
  const { updateLayoutSection } = useEditActions();

  return (
    <>
      <SectionTitle text={title} minHeight="3.5rem" isSticky={false} />
      <Box>
        {items.map((item, index) => {
          return (
            <Clickable
              key={item.url}
              data={{ index }}
              onClick={onItemClick as any}
            >
              <ShowListItem
                item={item}
                margin={`${index ? '1rem' : '0'} 0 0`}
              />
            </Clickable>
          );
        })}
      </Box>
      <AddShowButton
        sectionPath={sectionPath}
        onSubmit={({ item }) => {
          updateLayoutSection({
            sectionPath,

            changedProps: {
              items: [item, ...items],
            },
          });
        }}
      />
    </>
  );
});

export const toAddShowDialogHashParam = (sectionPath: string) =>
  `${HASH_PARAM}:${sectionPath}:add`;

const AddShowButton: FC<{
  sectionPath: string;
  onSubmit: (params: { item: ShowsSectionItem }) => void;
}> = ({ sectionPath, onSubmit }) => {
  const { backToBeforeFirstHash, setHashParam, hashParams } = useHash();
  const hashParam = toAddShowDialogHashParam(sectionPath);
  const dialogOpen = hashParam in hashParams;
  const [geolocation, setGeolocation] = useState<Geolocation | undefined>();
  const { t } = useI18n('itemEdit');

  return (
    <>
      <Clickable
        testId="addShow"
        onClick={() => setHashParam({ [hashParam]: '' })}
        margin="1.6rem 0 0 0"
      >
        <Text size="1.7rem" isBold centered>
          {t('shows.addShow')}
        </Text>
      </Clickable>
      {dialogOpen && (
        <DialogBox
          testId="addShowDialog"
          onClose={() => backToBeforeFirstHash()}
          fillViewportOnSmallScreen
          renderContent={({ paddingX, paddingY, close }) => {
            return (
              <Form<{ venueName: string; url: string; localDate: string }>
                testId="addShowForm"
                onSubmit={async ({ values }) => {
                  const item: ArtistShow = {
                    name: values.venueName,
                    venueName: values.venueName,
                    url: values.url,
                    localDate: values.localDate,
                    geolocation,
                  };

                  await close();

                  onSubmit({ item });
                }}
              >
                <Sticky top={0} zIndex={1}>
                  <DialogBoxHeader
                    title={t('shows.addShow')}
                    onCloseClick={close}
                    renderRight={({ textProps }) => (
                      <Clickable isSubmit testId="submit">
                        <Text {...textProps}>Add</Text>
                      </Clickable>
                    )}
                  />
                </Sticky>
                <Box padding={`0 ${paddingX} ${paddingY}`}>
                  <InputLabel value={t('shows.edit.labels.name')}>
                    <TextInput
                      name="venueName"
                      placeholder={t('shows.edit.placeholders.name')}
                      required
                    />
                  </InputLabel>
                  <InputLabel
                    value={t('shows.edit.labels.link')}
                    margin="2rem 0 0 0"
                  >
                    <TextInput
                      type={'url'}
                      name="url"
                      placeholder={t('shows.edit.placeholders.link')}
                      required
                    />
                  </InputLabel>
                  <InputLabel
                    value={t('shows.edit.labels.date')}
                    margin="2rem 0 0 0"
                  >
                    <DateInput
                      name="localDate"
                      placeholder={t('shows.edit.placeholders.date')}
                      required
                    />
                  </InputLabel>
                  <InputLabel
                    value={t('shows.edit.labels.address')}
                    margin="2rem 0 0 0"
                  >
                    <AddressInput
                      addressType={AddressTypes.ESTABLISHMENT}
                      placeholder={t('shows.edit.placeholders.address')}
                      onChange={(geolocation) => {
                        setGeolocation(geolocation);
                      }}
                      required
                    />
                  </InputLabel>
                </Box>
              </Form>
            );
          }}
        />
      )}
    </>
  );
};

export default ShowsSectionEdit;
