import type { ReactElement } from 'react';
import { format } from 'date-fns';
import { ListPlus, Trash2 } from 'lucide-react';
import {
  Controller,
  type ArrayPath,
  type FieldValues,
  type Path,
  type UseFormReturn,
} from 'react-hook-form';
import { NumberInput } from '@mantine/core';
import { YearPickerInput } from '@mantine/dates';
import {
  useControlledFieldArray,
  type FieldArrayItem,
} from '../../../hooks/use-controlled-field-array.js';
import { Button } from '../../ui/button.js';

type Props<T extends FieldValues> = {
  formManager: UseFormReturn<T, unknown>;
  chargeSpreadPath: ArrayPath<T>;
};

export function ChargeSpreadInput<T extends FieldValues>({
  formManager,
  chargeSpreadPath,
}: Props<T>): ReactElement {
  const { control, trigger } = formManager;
  const { controlledFields, append, remove, watchFieldArray } = useControlledFieldArray(
    formManager,
    chargeSpreadPath,
  );

  return (
    <div>
      <span className="mantine-InputWrapper-label mantine-Select-label">Charge Spread</span>
      <div className="h-full flex flex-col overflow-hidden">
        {controlledFields?.map((record, index) => (
          <div key={record.id} className="flex items-end gap-2 text-gray-600 mb-2">
            <div className="w-full mt-1 relative rounded-md shadow-xs">
              <Controller
                name={`${chargeSpreadPath}.${index}.year` as Path<T>}
                control={control}
                rules={{
                  required: 'Required',
                  validate: (value: string): boolean | string => {
                    const years = watchFieldArray.map(record => (record as { year?: string }).year);
                    if (years.filter(year => year === value).length > 1) {
                      return 'Years must be unique';
                    }
                    return true;
                  },
                }}
                render={({ field: { value, ...field }, fieldState }): ReactElement => {
                  return (
                    <YearPickerInput
                      {...field}
                      label="Year of relevance"
                      value={value ? new Date(value) : null}
                      error={fieldState.error?.message}
                      popoverProps={{ withinPortal: true, zIndex: 1002 }}
                      required
                      onChange={date => {
                        trigger(chargeSpreadPath as Path<T>);
                        field.onChange(date ? format(date, 'yyyy-MM-dd') : undefined);
                      }}
                    />
                  );
                }}
              />
            </div>
            <div className="w-full mt-1 relative rounded-md shadow-xs">
              <Controller
                control={control}
                name={`${chargeSpreadPath}.${index}.amount` as Path<T>}
                render={({ field, fieldState }): ReactElement => (
                  <NumberInput
                    className="w-full"
                    {...field}
                    min={0}
                    label="Amount"
                    value={field.value ?? undefined}
                    hideControls
                    precision={2}
                    error={fieldState.error?.message}
                    onChange={amount =>
                      field.onChange(amount && typeof amount === 'number' ? amount : undefined)
                    }
                  />
                )}
              />
            </div>
            <Button
              variant="ghost"
              size="icon"
              className="size-7.5 mb-2"
              onClick={(): void => {
                remove(index);
                trigger(chargeSpreadPath as Path<T>);
              }}
            >
              <Trash2 className="size-5" />
            </Button>
          </div>
        ))}
        <Button
          type="button"
          variant="ghost"
          size="icon"
          className="size-7.5"
          onClick={(): void => {
            append({ year: `${new Date().getFullYear()}-01-01` } as FieldArrayItem<T>);
            trigger(chargeSpreadPath as Path<T>);
          }}
        >
          <ListPlus className="size-5" />
        </Button>
      </div>
    </div>
  );
}
