import { useCallback } from 'react';
import { useFieldArray, useFormContext } from 'react-hook-form';

import {
  IconBed,
  IconCopy,
  IconInfoCircle,
  IconPlus,
} from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import SortableList from '@material-hu/components/composed-components/SortableList';
import type { ItemComponentProps } from '@material-hu/components/composed-components/SortableList/types';
import Button from '@material-hu/components/design-system/Buttons/Button';
import CardContainer from '@material-hu/components/design-system/CardContainer';
import { useDialogLayer } from '@material-hu/components/layers/Dialogs';

import { type Shift } from 'src/types/shifts';
import { useLokaliseTranslation } from 'src/utils/i18n';

import EmptyState from 'src/components/HuEmptyState';

import {
  type RotationDay,
  type ShiftRotationFormData,
  shiftRotationFormFields,
} from '../../../../form';

import RotationDayCard from './RotationDayCard';
import { useAddShiftDrawer } from './useAddShiftDrawer';

const MAX_ROTATION_DAYS = 28;

const generateId = () =>
  `day-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;

const RotationDaysSection = () => {
  const { t } = useLokaliseTranslation('shifts');
  const { openDialog, closeDialog } = useDialogLayer();
  const { control } = useFormContext<ShiftRotationFormData>();
  const { fields, append, remove, replace, update } = useFieldArray({
    control,
    name: shiftRotationFormFields.days,
    keyName: '_fieldId',
  });

  const days = fields as unknown as RotationDay[];

  const canAddMoreDays = days.length < MAX_ROTATION_DAYS;

  const handleAddRest = () => {
    if (!canAddMoreDays) return;
    append({ id: generateId(), type: 'rest' });
  };

  const handleAddShift = (shift: Shift) => {
    if (!canAddMoreDays) return;
    append({
      id: generateId(),
      type: 'shift',
      shifts: [
        {
          id: shift.id,
          name: shift.name,
          color: shift.color,
          description: shift.description,
          timeSlots: shift.timeSlots.map(({ startTime, endTime }) => ({
            startTime,
            endTime,
          })),
        },
      ],
    });
  };

  const { AddShiftDrawer, showAddShiftDrawer } = useAddShiftDrawer({
    onConfirm: handleAddShift,
  });

  const handleRemove = useCallback(
    (id: string) => {
      const index = days.findIndex(day => day.id === id);
      if (index >= 0) remove(index);
    },
    [days, remove],
  );

  const handleRemoveShift = useCallback(
    (dayId: string, shiftId: number) => {
      const index = days.findIndex(day => day.id === dayId);
      if (index < 0) return;
      const day = days[index];
      const nextShifts = (day.shifts ?? []).filter(s => s.id !== shiftId);
      if (nextShifts.length === 0) {
        remove(index);
        return;
      }
      update(index, { ...day, shifts: nextShifts });
    },
    [days, remove, update],
  );

  const handleSort = (next: RotationDay[]) => {
    replace(next);
  };

  const runReplicateFirstDay = () => {
    if (days.length === 0) return;
    const [firstDay] = days;
    const copies = Array.from({ length: MAX_ROTATION_DAYS - 1 }, () => ({
      ...firstDay,
      id: generateId(),
    }));
    replace([firstDay, ...copies]);
  };

  const handleReplicateFirstDay = () => {
    if (days.length === 0) return;
    // Single day → no existing content to overwrite, skip the dialog.
    if (days.length === 1) {
      runReplicateFirstDay();
      return;
    }
    openDialog({
      title: t('templates.replicate_title'),
      textBody: t('templates.replicate_description'),
      onClose: () => closeDialog(),
      primaryButtonProps: {
        children: t('templates.replicate_confirmation'),
        onClick: () => {
          closeDialog();
          runReplicateFirstDay();
        },
      },
      secondaryButtonProps: {
        children: t('general:cancel'),
        onClick: () => closeDialog(),
      },
      dialogProps: { fullWidth: true, maxWidth: 'sm' },
    });
  };

  const canReplicateFirstDay = days.length >= 1;

  const renderItem = useCallback(
    (props: ItemComponentProps<RotationDay>) => {
      // SortableList passes index=-1 to the DragOverlay copy; derive the real
      // position from the item id so the day number stays correct while dragging.
      const realIndex = days.findIndex(d => d.id === props.item.id);
      return (
        <RotationDayCard
          {...props}
          index={realIndex >= 0 ? realIndex : props.index}
          onRemove={handleRemove}
          onRemoveShift={handleRemoveShift}
        />
      );
    },
    [days, handleRemove, handleRemoveShift],
  );

  const hasDays = days.length > 0;

  return (
    <CardContainer fullWidth>
      <Stack sx={{ gap: 2 }}>
        <Stack
          sx={{
            flexDirection: 'row',
            justifyContent: 'space-between',
            alignItems: 'center',
            gap: 1,
          }}
        >
          <Typography
            variant="globalM"
            sx={{ fontWeight: 'fontWeightSemiBold' }}
          >
            {t('templates.form.days')}
          </Typography>
          <Button
            variant="tertiary"
            color="primary"
            size="small"
            startIcon={<IconCopy size={16} />}
            disabled={!canReplicateFirstDay}
            onClick={handleReplicateFirstDay}
          >
            {t('templates.replicate')}
          </Button>
        </Stack>

        {!hasDays && (
          <EmptyState
            titleProps={{
              title: t('templates.form.empty_days'),
              description: t('templates.form.empty_days_description'),
              variant: 'S',
            }}
            avatarProps={{
              Icon: IconInfoCircle,
              color: 'highlight',
            }}
            sx={{ backgroundColor: 'transparent' }}
          />
        )}

        {hasDays && (
          <SortableList<RotationDay>
            items={days}
            onSort={handleSort}
            ItemComponent={renderItem}
            dragByHandler
            hasDragOverlay
            sx={{
              gap: 1,
              overflow: 'visible',
              // SortableItem fades the original to opacity 0.4 while dragging
              // with the overlay enabled. Hide it instead so only the floating
              // overlay (with correct height) is visible.
              '& li[style*="opacity"]': {
                opacity: '0 !important',
              },
            }}
          />
        )}

        <Stack sx={{ flexDirection: 'row', gap: 1 }}>
          <Button
            variant="secondary"
            color="primary"
            fullWidth
            startIcon={<IconBed size={16} />}
            disabled={!canAddMoreDays}
            onClick={handleAddRest}
          >
            {t('templates.form.add_rest_day')}
          </Button>
          <Button
            variant="secondary"
            color="primary"
            fullWidth
            startIcon={<IconPlus size={16} />}
            disabled={!canAddMoreDays}
            onClick={() => showAddShiftDrawer()}
          >
            {t('templates.form.add_shift')}
          </Button>
        </Stack>
      </Stack>
      {AddShiftDrawer}
    </CardContainer>
  );
};

export default RotationDaysSection;
