import type { ReactElement } from 'react';
import { Controller, type UseFormReturn } from 'react-hook-form';
import { type InsertMiscExpenseInput, type UpdateMiscExpenseInput } from '../../../gql/graphql.js';
import { TIMELESS_DATE_REGEX } from '../../../helpers/consts.js';
import { useGetFinancialEntities } from '../../../hooks/use-get-financial-entities.js';
import { FormControl, FormField, FormItem, FormLabel, FormMessage } from '../../ui/form.js';
import { Input } from '../../ui/input.js';
import { ComboBox, CurrencyInput, DatePickerInput, DateTimePickerInput } from '../index.js';

interface Props<T extends boolean> {
  isInsert: T;
  formManager: UseFormReturn<
    InsertMiscExpenseInput | UpdateMiscExpenseInput,
    unknown,
    InsertMiscExpenseInput | UpdateMiscExpenseInput
  >;
}

export const ModifyMiscExpenseFields = ({
  formManager,
  isInsert,
}: Props<boolean>): ReactElement => {
  const { control, setValue } = formManager;

  const { selectableFinancialEntities: financialEntities, fetching: fetchingFinancialEntities } =
    useGetFinancialEntities();

  return (
    <>
      <FormField
        name="creditorId"
        control={control}
        rules={{
          required: isInsert ? 'Required' : undefined,
        }}
        render={({ field }) => (
          <FormItem>
            <FormLabel>Creditor</FormLabel>
            <ComboBox
              {...field}
              data={financialEntities}
              value={field.value ?? undefined}
              disabled={fetchingFinancialEntities}
              placeholder="Select creditor"
              formPart
            />
            <FormMessage />
          </FormItem>
        )}
      />
      <FormField
        name="debtorId"
        control={control}
        rules={{
          required: isInsert ? 'Required' : undefined,
        }}
        render={({ field }) => (
          <FormItem>
            <FormLabel>Debtor</FormLabel>
            <ComboBox
              {...field}
              data={financialEntities}
              value={field.value ?? undefined}
              disabled={fetchingFinancialEntities}
              placeholder="Select debtor"
              formPart
            />
            <FormMessage />
          </FormItem>
        )}
      />
      <Controller
        name="amount"
        control={control}
        rules={{
          required: isInsert ? 'Required' : undefined,
        }}
        render={({ field: amountField, fieldState: amountFieldState }): ReactElement => (
          <Controller
            name="currency"
            control={control}
            rules={{
              required: isInsert ? 'Required' : undefined,
            }}
            render={({
              field: currencyCodeField,
              fieldState: currencyCodeFieldState,
            }): ReactElement => (
              <CurrencyInput
                {...amountField}
                required={isInsert}
                value={amountField.value ?? undefined}
                error={amountFieldState.error?.message || currencyCodeFieldState.error?.message}
                label="Amount"
                currencyCodeProps={{
                  ...currencyCodeField,
                  required: isInsert,
                  label: 'Currency',
                }}
              />
            )}
          />
        )}
      />
      <FormField
        name="invoiceDate"
        control={control}
        rules={{
          ...(isInsert ? { required: 'Required' } : {}),
          pattern: {
            value: TIMELESS_DATE_REGEX,
            message: 'Date must be in format yyyy-mm-dd',
          },
        }}
        render={({ field, fieldState }) => (
          <FormItem>
            <FormLabel htmlFor="misc-expense-invoice-date">Invoice Date</FormLabel>
            <FormControl>
              <DatePickerInput
                id="misc-expense-invoice-date"
                required={isInsert}
                onChange={date => {
                  if (date !== field.value) field.onChange(date);
                }}
                value={field.value ?? undefined}
                aria-invalid={!!fieldState.error}
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />
      <FormField
        name="valueDate"
        control={control}
        rules={{
          ...(isInsert ? { required: 'Required' } : {}),
          validate: (value?: Date | null) => {
            if (!value) return true;
            return !Number.isNaN(value.getTime()) || 'Invalid date and time format';
          },
        }}
        render={({ field, fieldState }) => (
          <FormItem>
            <FormLabel htmlFor="misc-expense-value-date">Value Date</FormLabel>
            <FormControl>
              <DateTimePickerInput
                id="misc-expense-value-date"
                value={field.value ?? null}
                onChange={(date?: Date | null): void => {
                  setValue('valueDate', date);
                  field.onChange(date);
                }}
                required={isInsert}
                aria-invalid={!!fieldState.error}
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />
      <FormField
        name="description"
        control={control}
        rules={{
          required: isInsert ? 'Required' : undefined,
        }}
        render={({ field }) => (
          <FormItem>
            <FormLabel>Description</FormLabel>
            <FormControl>
              <Input {...field} required={isInsert} value={field.value ?? undefined} />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />
    </>
  );
};
