import { useEffect, useState, type ReactElement } from 'react';
import { format } from 'date-fns';
import { Controller, type UseFormReturn } from 'react-hook-form';
import { MonthPickerInput } from '@mantine/dates';
import {
  Currency,
  DocumentType,
  type EditDocumentQuery,
  type InsertDocumentInput,
  type UpdateDocumentFieldsInput,
} from '../../../gql/graphql.js';
import { TIMELESS_DATE_REGEX } from '../../../helpers/consts.js';
import {
  isDocumentCreditInvoice,
  isDocumentInvoice,
  isDocumentInvoiceReceipt,
  isDocumentProforma,
  isDocumentReceipt,
} from '../../../helpers/documents.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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select.js';
import { ComboBox, CurrencyInput, DatePickerInput, NumberInput } from '../index.js';

export interface ModifyDocumentFieldsProps {
  formManager: UseFormReturn<
    UpdateDocumentFieldsInput | InsertDocumentInput,
    unknown,
    UpdateDocumentFieldsInput | InsertDocumentInput
  >;
  document?: EditDocumentQuery['documentById'];
  defaultCurrency?: Currency;
}

export const ModifyDocumentFields = ({
  formManager,
  document,
  defaultCurrency,
}: ModifyDocumentFieldsProps): ReactElement => {
  const { control, watch, trigger } = formManager;
  const [showExtendedFields, setShowExtendedFields] = useState<boolean>(false);

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

  const isDocumentProcessed =
    isDocumentInvoice(document) ||
    isDocumentReceipt(document) ||
    isDocumentInvoiceReceipt(document) ||
    isDocumentProforma(document) ||
    isDocumentCreditInvoice(document);

  const processedDoc = isDocumentProcessed
    ? (document as Extract<NonNullable<EditDocumentQuery['documentById']>, { date: unknown }>)
    : undefined;

  const type = watch('documentType');

  // auto update vat currency according to amount currency
  useEffect(() => {
    setShowExtendedFields(
      !!type &&
        (type === DocumentType.Invoice ||
          type === DocumentType.Receipt ||
          type === DocumentType.InvoiceReceipt ||
          type === DocumentType.Proforma ||
          type === DocumentType.CreditInvoice),
    );
  }, [type]);

  return (
    <>
      <FormField
        name="documentType"
        control={control}
        rules={{ required: 'Required' }}
        defaultValue={document?.documentType ?? DocumentType.Unprocessed}
        render={({ field }): ReactElement => (
          <FormItem>
            <FormLabel>Type</FormLabel>
            <Select onValueChange={field.onChange} value={field.value ?? undefined}>
              <FormControl>
                <SelectTrigger className="w-full truncate">
                  <SelectValue placeholder="Select type" />
                </SelectTrigger>
              </FormControl>
              <SelectContent onClick={event => event.stopPropagation()}>
                {Object.entries(DocumentType).map(([label, value]) => (
                  <SelectItem key={value} value={value}>
                    {label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <FormMessage />
          </FormItem>
        )}
      />
      {showExtendedFields && (
        <>
          <FormField
            name="date"
            control={control}
            defaultValue={processedDoc?.date}
            rules={{
              pattern: {
                value: TIMELESS_DATE_REGEX,
                message: 'Date must be in format yyyy-mm-dd',
              },
            }}
            render={({ field, fieldState }): ReactElement => (
              <FormItem>
                <FormLabel>Date</FormLabel>
                <FormControl>
                  <DatePickerInput
                    value={field.value ?? undefined}
                    onChange={date => {
                      if (date !== field.value) field.onChange(date);
                    }}
                    aria-invalid={!!fieldState.error}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            name="serialNumber"
            control={control}
            defaultValue={processedDoc?.serialNumber}
            render={({ field }) => (
              <FormItem>
                <FormLabel>Serial Number</FormLabel>
                <FormControl>
                  <Input
                    {...field}
                    value={!field || field.value === 'Missing' ? '' : field.value!}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            name="allocationNumber"
            control={control}
            defaultValue={processedDoc?.allocationNumber}
            rules={{
              pattern: {
                value: /^\d{9}$/,
                message: 'Allocation number must be 9 characters long',
              },
            }}
            render={({ field }) => (
              <FormItem>
                <FormLabel>Allocation Number</FormLabel>
                <FormControl>
                  <Input {...field} value={field.value ?? undefined} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          <FormField
            name="debtorId"
            control={control}
            defaultValue={processedDoc?.debtor?.id}
            render={({ field }) => (
              <FormItem className="flex flex-col">
                <FormLabel>Debtor</FormLabel>
                <ComboBox
                  {...field}
                  data={financialEntities}
                  value={field.value ?? undefined}
                  disabled={fetchingFinancialEntities}
                  placeholder="Scroll to see all options"
                  formPart
                />
                <FormMessage />
              </FormItem>
            )}
          />
          <FormField
            name="creditorId"
            control={control}
            defaultValue={processedDoc?.creditor?.id}
            render={({ field }) => (
              <FormItem className="flex flex-col">
                <FormLabel>Creditor</FormLabel>
                <ComboBox
                  {...field}
                  data={financialEntities}
                  value={field.value ?? undefined}
                  disabled={fetchingFinancialEntities}
                  placeholder="Scroll to see all options"
                  formPart
                />
                <FormMessage />
              </FormItem>
            )}
          />
          <Controller
            name="vat.raw"
            control={control}
            defaultValue={processedDoc?.vat?.raw}
            render={({ field: vatField, fieldState: vatFieldState }): ReactElement => (
              <Controller
                name="vat.currency"
                control={control}
                defaultValue={processedDoc?.amount?.currency ?? defaultCurrency ?? Currency.Ils}
                render={({
                  field: currencyCodeField,
                  fieldState: currencyCodeFieldState,
                }): ReactElement => (
                  <CurrencyInput
                    {...vatField}
                    error={vatFieldState.error?.message || currencyCodeFieldState.error?.message}
                    label="VAT"
                    currencyCodeProps={{ ...currencyCodeField, label: 'Currency', disabled: true }}
                  />
                )}
              />
            )}
          />
          <Controller
            name="amount.raw"
            control={control}
            defaultValue={processedDoc?.amount?.raw}
            render={({ field: amountField, fieldState: amountFieldState }): ReactElement => (
              <Controller
                name="amount.currency"
                control={control}
                defaultValue={processedDoc?.amount?.currency ?? defaultCurrency ?? Currency.Ils}
                render={({
                  field: currencyCodeField,
                  fieldState: currencyCodeFieldState,
                }): ReactElement => (
                  <CurrencyInput
                    {...amountField}
                    error={amountFieldState.error?.message || currencyCodeFieldState.error?.message}
                    label="Amount"
                    currencyCodeProps={{ ...currencyCodeField, label: 'Currency' }}
                  />
                )}
              />
            )}
          />
          <Controller
            name="vatReportDateOverride"
            control={control}
            defaultValue={processedDoc?.vatReportDateOverride}
            rules={{
              pattern: {
                value: TIMELESS_DATE_REGEX,
                message: 'Date must be in format yyyy-mm-dd',
              },
            }}
            render={({ field, fieldState }): ReactElement => (
              <MonthPickerInput
                {...field}
                label="VAT report date"
                value={field.value ? new Date(field.value) : undefined}
                onChange={date => {
                  trigger('vatReportDateOverride');
                  field.onChange(date ? `${format(date, 'yyyy-MM')}-15` : undefined);
                }}
                error={fieldState.error?.message}
                popoverProps={{ withinPortal: true }}
              />
            )}
          />
          <Controller
            name="noVatAmount"
            control={control}
            defaultValue={processedDoc?.noVatAmount ?? undefined}
            render={({ field: noVatField, fieldState: noVatFieldState }): ReactElement => (
              <Controller
                name="amount.currency"
                control={control}
                defaultValue={processedDoc?.amount?.currency ?? defaultCurrency ?? Currency.Ils}
                render={({ field: currencyCodeField }): ReactElement => (
                  <CurrencyInput
                    {...noVatField}
                    value={noVatField.value ?? undefined}
                    error={noVatFieldState.error?.message}
                    label="no VAT amount"
                    currencyCodeProps={{ ...currencyCodeField, label: 'Currency', disabled: true }}
                  />
                )}
              />
            )}
          />
        </>
      )}

      <FormField
        name="image"
        control={control}
        defaultValue={document?.image}
        render={({ field }) => (
          <FormItem>
            <FormLabel>Image URL</FormLabel>
            <FormControl>
              <Input {...field} value={field.value?.toString()} />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />

      <FormField
        name="file"
        control={control}
        defaultValue={document?.file}
        render={({ field }) => (
          <div className="flex flex-row">
            <FormItem>
              <FormLabel>File URL</FormLabel>
              <FormControl>
                <Input className="grow" {...field} value={field.value?.toString()} />
              </FormControl>
              <FormMessage />
            </FormItem>
          </div>
        )}
      />

      <FormField
        name="description"
        control={control}
        defaultValue={document?.description}
        render={({ field }) => (
          <FormItem>
            <FormLabel>Description</FormLabel>
            <FormControl>
              <Input {...field} value={field.value ?? ''} />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />

      <FormField
        name="remarks"
        control={control}
        defaultValue={document?.remarks}
        render={({ field }) => (
          <FormItem>
            <FormLabel>Remarks</FormLabel>
            <FormControl>
              <Input {...field} value={field.value ?? ''} />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />

      <FormField
        name="exchangeRateOverride"
        control={control}
        defaultValue={processedDoc?.exchangeRateOverride}
        render={({ field }): ReactElement => (
          <FormItem>
            <FormLabel>
              Exchange Rate Override
              <span className="text-xs text-muted-foreground">
                {`(${
                  processedDoc?.amount?.currency ?? defaultCurrency ?? Currency.Ils
                } => ${Currency.Ils})`}
              </span>
            </FormLabel>
            <FormControl>
              <NumberInput
                onValueChange={value => field.onChange(Number(value))}
                value={field.value ?? undefined}
                hideControls
                decimalScale={5}
                thousandSeparator=","
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />
    </>
  );
};
