import {Trans} from '@common/i18n/trans';
import React, {Fragment, ReactNode, useRef, useState} from 'react';
import {DragPreviewRenderer} from '@common/ui/interactions/dnd/use-draggable';
import {useFormContext} from 'react-hook-form';
import {AdminSettingsWithFiles} from '@common/admin/settings/requests/update-admin-settings';
import {moveItemInNewArray} from '@common/utils/array/move-item-in-new-array';
import {IconButton} from '@common/ui/buttons/icon-button';
import {DragHandleIcon} from '@common/icons/material/DragHandle';
import {Checkbox} from '@common/ui/forms/toggle/checkbox';
import {DragPreview} from '@common/ui/interactions/dnd/drag-preview';
import clsx from 'clsx';
import {TitlePageSections} from '@app/titles/pages/title-page/sections/title-page-sections';
import {MessageDescriptor} from '@common/i18n/message-descriptor';
import {AdminSettings} from '@common/admin/settings/admin-settings';
import {useSortable} from '@common/ui/interactions/dnd/sortable/use-sortable';

interface SectionItem {
  name: (typeof TitlePageSections)[number];
  title: MessageDescriptor;
}

const defaultItems: SectionItem[] = [
  {name: 'episodes', title: {message: 'Episode grid'}},
  {name: 'seasons', title: {message: 'Season grid'}},
  {name: 'videos', title: {message: 'Video grid'}},
  {name: 'images', title: {message: 'Image grid'}},
  {name: 'reviews', title: {message: 'Reviews'}},
  {name: 'cast', title: {message: 'Cast grid'}},
  {name: 'related', title: {message: 'Related titles'}},
];

export function ContentSettingsTitlePagePanel() {
  const {getValues, setValue} = useFormContext<AdminSettings>();
  const getSavedValue = (): string[] => {
    return getValues('client.title_page.sections') || [];
  };

  const [items, setItems] = useState(() => {
    const savedValue = getSavedValue();
    const sortFn = (x: string) =>
      savedValue.includes(x) ? savedValue.indexOf(x) : savedValue.length;
    return [...defaultItems].sort((a, b) => sortFn(a.name) - sortFn(b.name));
  });

  return (
    <div>
      <div className="mb-14 text-sm">
        <Trans message="Title page sections" />
        <div className="text-xs text-muted">
          <Trans message="Select which sections should appear on title page and in which order." />
        </div>
      </div>
      {items.map((section, index) => (
        <ListItemLayout
          items={items}
          isFirst={index === 0}
          key={section.name}
          section={section}
          title={<Trans {...section.title} />}
          onToggle={(section, checked) => {
            const savedValue = getSavedValue();
            const newValue = checked
              ? [...savedValue, section.name]
              : savedValue.filter(x => x !== section.name);
            setValue('client.title_page.sections', newValue as any);
          }}
          onSortEnd={(oldIndex, newIndex) => {
            const sortedItems = moveItemInNewArray(items, oldIndex, newIndex);
            setItems(sortedItems);
            const savedValue = getSavedValue();
            const newValue = sortedItems
              .filter(x => savedValue.includes(x.name))
              .map(x => x.name);
            setValue('client.title_page.sections', newValue);
          }}
        />
      ))}
    </div>
  );
}

interface ListItemLayoutProps {
  isFirst: boolean;
  items: SectionItem[];
  section: SectionItem;
  title: ReactNode;
  onSortEnd: (oldIndex: number, newIndex: number) => void;
  onToggle: (section: SectionItem, checked: boolean) => void;
}
function ListItemLayout({
  isFirst,
  title,
  items,
  section,
  onSortEnd,
  onToggle,
}: ListItemLayoutProps) {
  const ref = useRef<HTMLDivElement>(null);
  const previewRef = useRef<DragPreviewRenderer>(null);
  const {watch} = useFormContext<AdminSettingsWithFiles>();

  const savedValue = watch('client.title_page.sections') || [];
  const isChecked = savedValue.includes(section.name);

  const {sortableProps, dragHandleRef} = useSortable({
    ref,
    item: section,
    items,
    type: 'titlePageSections',
    preview: previewRef,
    strategy: 'line',
    onSortEnd,
  });

  return (
    <Fragment>
      <div
        className={clsx(
          'flex w-full items-center gap-8 border-b py-6',
          isFirst && 'border-t border-t-transparent',
        )}
        ref={ref}
        {...sortableProps}
      >
        <IconButton ref={dragHandleRef}>
          <DragHandleIcon />
        </IconButton>
        <div className="flex-auto">
          <div className="text-sm">{title}</div>
        </div>
        <Checkbox
          checked={isChecked}
          onChange={() => {
            onToggle(section, !isChecked);
          }}
        />
      </div>
      <TabDragPreview title={title} ref={previewRef} />
    </Fragment>
  );
}

interface DragPreviewProps {
  title: ReactNode;
}
const TabDragPreview = React.forwardRef<DragPreviewRenderer, DragPreviewProps>(
  ({title}, ref) => {
    return (
      <DragPreview ref={ref}>
        {() => (
          <div className="rounded bg-chip p-8 text-sm shadow">{title}</div>
        )}
      </DragPreview>
    );
  },
);
