'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useFormik } from 'formik';
import { Icon } from '@iconify/react';
import { toast } from 'react-hot-toast';
import { useSearchParams } from 'next/navigation';
import Button from '@/components/Button';
import TextInput from '@/components/input/TextInput';
import NumberInput from '@/components/input/NumberInput';
import FileInput from '@/components/input/FileInput';
import SelectInput, {
  OptionType,
  useSelect,
} from '@/components/input/SelectInput';
import { useRouter } from 'next/navigation';
import AlertErrorList from '@/components/helper/form/FormErrors';

import {
  PurchaseRequestAcceptApprovalFormDefaultValues,
  PurchaseRequestAcceptApprovalFormInitialValues,
  PurchaseRequestAcceptApprovalFormSchema,
} from '@/components/pages/purchase/form/order/PurchaseOrderForm.schema';
import { isResponseError } from '@/lib/api-helper';
import { PurchaseApi } from '@/services/api/purchase';
import {
  CreateAcceptApprovalRequestPayload,
  Purchase,
} from '@/types/api/purchase/purchase';
import DateInput from '@/components/input/DateInput';
import { formatNumber } from '@/lib/helper';
import { getUniqueFormikErrors } from '@/lib/formik-helper';
import { Supplier } from '@/types/api/master-data/supplier';
import { SupplierApi } from '@/services/api/master-data';

interface PurchaseOrderAcceptApprovalFormProps {
  type?: 'add' | 'edit';
  initialValues?: Purchase;
  onCancel?: () => void;
  refreshApprovals?: () => void;
  onModalClose?: () => void;
  onRefetchData?: () => void;
}

const PurchaseOrderAcceptApprovalForm = ({
  type = 'add',
  initialValues,
  onCancel,
  refreshApprovals,
  onModalClose,
  onRefetchData,
}: PurchaseOrderAcceptApprovalFormProps) => {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [purchaseOrderFormErrorMessage, setPurchaseOrderFormErrorMessage] =
    useState('');
  const [formErrorList, setFormErrorList] = useState<string[]>([]);
  const [key, setKey] = useState(0);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const isRejected = initialValues?.latest_approval?.action === 'REJECTED';

  useEffect(() => {
    setKey((prev) => prev + 1);
  }, [initialValues?.id]);

  // ===== UTILITY FUNCTIONS =====
  const isRepeaterInputError = (
    idx: number,
    field:
      | 'purchase_item_id'
      | 'received_date'
      | 'travel_number'
      | 'vehicle_number'
      | 'expedition_vendor_id'
      | 'received_qty'
      | 'transport_per_item'
      | 'travel_documents'
  ): { isError: boolean; errorMessage: string } => {
    const touchedItem = formik.touched.items?.[idx];
    const errorItem = formik.errors.items?.[idx] as
      | Record<string, string>
      | undefined;

    if (!touchedItem) {
      return { isError: false, errorMessage: '' };
    }

    const isTouched = (touchedItem as Record<string, boolean>)?.[field];
    const errorMessage = errorItem?.[field] || '';

    return {
      isError: Boolean(isTouched && errorMessage),
      errorMessage: isTouched && errorMessage ? errorMessage : '',
    };
  };

  // ===== SELECT INPUT DATA =====
  const {
    options: expeditionVendors,
    isLoadingOptions: isLoadingExpeditions,
    loadMore: loadMoreExpeditions,
  } = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name', 'search', {
    category: 'BOP',
    flag: 'EKSPEDISI',
  });

  // ===== FORM CONFIGURATION =====
  const formikInitialValues = useMemo(() => {
    return initialValues
      ? PurchaseRequestAcceptApprovalFormDefaultValues(initialValues)
      : PurchaseRequestAcceptApprovalFormInitialValues;
  }, [initialValues]);

  const formik = useFormik({
    initialValues: formikInitialValues,
    validationSchema: PurchaseRequestAcceptApprovalFormSchema,
    validateOnChange: true,
    validateOnBlur: true,
    enableReinitialize: false,
    onSubmit: async (values) => {
      type ItemPayload = {
        purchase_item_id: number;
        received_date: string;
        travel_number: string;
        received_qty: number;
        vehicle_number?: string;
        expedition_vendor_id?: number;
        transport_per_item?: number;
      };

      const payload: CreateAcceptApprovalRequestPayload = {
        action: 'APPROVED',
        notes: values.notes || '',
        items:
          values.items?.map((formItem) => {
            const item: ItemPayload = {
              purchase_item_id: formItem.purchase_item_id || 0,
              received_date: formItem.received_date || '',
              travel_number: formItem.travel_number || '',
              received_qty:
                typeof formItem.received_qty === 'string'
                  ? parseFloat(formItem.received_qty) || 0
                  : formItem.received_qty || 0,
            };

            if (
              formItem.vehicle_number &&
              formItem.vehicle_number.trim() !== ''
            ) {
              item.vehicle_number = formItem.vehicle_number;
            }

            if (
              formItem.expedition_vendor_id &&
              formItem.expedition_vendor_id !== 0
            ) {
              item.expedition_vendor_id = formItem.expedition_vendor_id;
            }

            const transportValue =
              typeof formItem.transport_per_item === 'string'
                ? parseFloat(formItem.transport_per_item) || 0
                : formItem.transport_per_item || 0;
            if (transportValue > 0) {
              item.transport_per_item = transportValue;
            }

            return item;
          }) || [],
        travel_documents:
          values.travel_documents
            ?.filter((file): file is File => file instanceof File)
            .filter(Boolean) || undefined,
      };

      switch (type) {
        case 'add':
          await createAcceptApprovalHandler(payload);
          break;
        case 'edit':
          await updateAcceptApprovalHandler(
            initialValues?.id as number,
            payload
          );
          break;
      }
    },
  });

  const { resetForm, setFieldValue } = formik;

  // ===== SUBMISSION HANDLERS =====
  const createAcceptApprovalHandler = useCallback(
    async (payload: CreateAcceptApprovalRequestPayload) => {
      const purchaseRequestId = searchParams.get('purchaseId')
        ? parseInt(searchParams.get('purchaseId')!)
        : initialValues?.id || 1;

      if (!purchaseRequestId) {
        setPurchaseOrderFormErrorMessage('Purchase Request ID is required');
        return;
      }

      const res = await PurchaseApi.acceptApproval.create(
        purchaseRequestId,
        payload
      );

      if (isResponseError(res)) {
        setPurchaseOrderFormErrorMessage(res.message);
        return;
      }
      toast.success(res?.message as string);
      refreshApprovals?.();
      onRefetchData?.();
      resetForm();
      onCancel?.();
      onModalClose?.();
      router.refresh();
    },
    [
      initialValues?.id,
      searchParams,
      refreshApprovals,
      onModalClose,
      onRefetchData,
      onCancel,
      router,
      resetForm,
    ]
  );

  const updateAcceptApprovalHandler = useCallback(
    async (purchaseId: number, payload: CreateAcceptApprovalRequestPayload) => {
      const res = await PurchaseApi.acceptApproval.create(purchaseId, payload);
      if (isResponseError(res)) {
        setPurchaseOrderFormErrorMessage(res.message);
        return;
      }
      toast.success(res?.message as string);
      refreshApprovals?.();
      onRefetchData?.();
      resetForm();
      onCancel?.();
      onModalClose?.();
      router.refresh();
    },
    [refreshApprovals, onModalClose, onRefetchData, onCancel, router, resetForm]
  );

  const handleValidateForm = async () => {
    const errors = await formik.validateForm();

    if (Object.keys(errors).length > 0) {
      const errorMessages = getUniqueFormikErrors(errors);
      setFormErrorList(errorMessages);
      return;
    }
  };

  const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    handleValidateForm();
    formik.handleSubmit(e);
  };

  // ===== API DATA FETCHING =====
  const purchaseItems = useMemo(() => {
    if (initialValues?.items) {
      return initialValues.items.map((item) => ({
        value: item.id,
        label: item.product.name,
        id: item.id,
        quantity: item.sub_qty,
        product: {
          name: item.product.name,
          product_category: item.product.product_category || '',
          uom: item.product.uom || { name: '' },
        },
        warehouse: {
          name: item.warehouse?.name || '',
        },
      }));
    }

    return [];
  }, [initialValues?.items]);

  useEffect(() => {
    if (purchaseItems.length > 0 && initialValues?.items) {
      const updatedItems = initialValues.items.map((item) => {
        const expeditionVendorId =
          item.expedition_vendor_id || item.expedition_vendor?.id || null;

        return {
          purchase_item_id: item.id,
          received_date: item.received_date
            ? new Date(item.received_date).toISOString().split('T')[0]
            : '',
          travel_number: item.travel_number || '',
          vehicle_number: item.vehicle_number || '',
          expedition_vendor: item.expedition_vendor
            ? {
                value: item.expedition_vendor.id,
                label: item.expedition_vendor.name,
              }
            : null,
          expedition_vendor_id: expeditionVendorId,
          received_qty: item.sub_qty || '',
          transport_per_item: item.transport_per_item || '',
        };
      });
      setFieldValue('items', updatedItems);
    }
  }, [purchaseItems, initialValues, key, setFieldValue]);

  // ===== HELPER FUNCTIONS =====
  const getQuantityExceededError = useCallback(
    (idx: number, receivedQty: number) => {
      if (!receivedQty) return null;

      const originalQty = purchaseItems[idx]?.quantity || 0;
      if (receivedQty > originalQty) {
        return `Tidak boleh melebihi ${formatNumber(originalQty)}`;
      }

      return null;
    },
    [purchaseItems]
  );

  const hasQuantityExceededErrors = useMemo(() => {
    if (!formik.values.items || purchaseItems.length === 0) return false;

    return formik.values.items.some((item, idx) => {
      if (!item.received_qty) return false;

      const receivedQty =
        typeof item.received_qty === 'string'
          ? parseFloat(item.received_qty) || 0
          : item.received_qty;

      const originalQty = purchaseItems[idx]?.quantity || 0;
      return receivedQty > originalQty;
    });
  }, [formik.values.items, purchaseItems]);

  const getExpeditionVendorOptions = useCallback(() => {
    return expeditionVendors;
  }, [expeditionVendors]);

  // ===== FIELD CHANGE HANDLERS =====
  const expeditionVendorChangeHandler = (
    idx: number,
    val: OptionType | OptionType[] | null
  ) => {
    const expeditionVendor = val as OptionType | null;
    formik.setFieldTouched(`items.${idx}.expedition_vendor`, true);
    formik.setFieldValue(`items.${idx}.expedition_vendor`, expeditionVendor);
    formik.setFieldTouched(`items.${idx}.expedition_vendor_id`, true);
    if (expeditionVendor?.value) {
      formik.setFieldValue(
        `items.${idx}.expedition_vendor_id`,
        expeditionVendor.value
      );
    } else {
      formik.setFieldValue(`items.${idx}.expedition_vendor_id`, null);

      formik.setFieldValue(`items.${idx}.transport_per_item`, null);
      formik.setFieldValue(`items.${idx}.vehicle_number`, null);
    }
  };

  // ===== PURCHASE ITEM OPERATIONS =====
  const handlePurchaseItemChange = (
    idx: number,
    field: 'received_qty' | 'transport_per_item',
    value: string | number
  ) => {
    const numValue = typeof value === 'string' ? parseFloat(value) || 0 : value;
    formik.setFieldValue(`items.${idx}.${field}`, numValue);
  };

  return (
    <form
      key={key}
      onSubmit={handleFormSubmit}
      className='w-full flex flex-col gap-6'
    >
      <div className='w-full'>
        <h2 className='text-lg font-semibold mb-4'>
          {type === 'add'
            ? 'Konfirmasi Penerimaan Produk'
            : 'Edit Penerimaan Produk'}
        </h2>
        <div className='overflow-x-auto'>
          <table className='table'>
            <thead>
              <tr>
                <th>Produk</th>
                <th>Gudang</th>
                <th>Jumlah</th>
                <th>Satuan</th>
                <th>
                  Tanggal Diterima
                  <span className='text-error'>*</span>
                </th>
                <th>
                  No. Surat Jalan
                  <span className='text-error'>*</span>
                </th>
                <th className='hidden'>
                  Dokumen Surat Jalan
                  <span className='text-error'>*</span>
                </th>
                <th>Nomor Kendaraan</th>
                <th>Vendor Ekspedisi</th>
                <th>
                  Jumlah Diterima
                  <span className='text-error'>*</span>
                </th>
                <th>Transport/Item</th>
              </tr>
            </thead>
            <tbody>
              {purchaseItems?.map((purchaseItem, idx) => {
                const formItem = formik.values.items?.[idx];

                const originalPurchaseItem = initialValues?.items?.find(
                  (item) => item.id === purchaseItem.id
                );
                const isReceivedQtyDisabled =
                  originalPurchaseItem?.has_chickin === true;

                return (
                  <tr key={`purchase-item-${idx}`}>
                    <td>
                      <TextInput
                        name={`items.${idx}.product_name`}
                        type='text'
                        value={purchaseItem?.product?.name || ''}
                        readOnly={true}
                        className={{
                          wrapper: 'min-w-52 md:min-w-72 lg:min-w-80',
                        }}
                        disabled={true}
                      />
                      <input
                        type='hidden'
                        name={`items.${idx}.purchase_item_id`}
                        value={purchaseItem?.value || 0}
                      />
                    </td>
                    <td>
                      <TextInput
                        name={`items.${idx}.warehouse`}
                        type='text'
                        value={purchaseItem?.warehouse?.name || ''}
                        readOnly={true}
                        className={{
                          wrapper: 'min-w-40 md:min-w-52 lg:min-w-64',
                        }}
                        disabled={true}
                      />
                    </td>
                    <td>
                      <TextInput
                        name={`items.${idx}.quantity`}
                        type='text'
                        value={
                          purchaseItem?.quantity
                            ? formatNumber(purchaseItem.quantity)
                            : ''
                        }
                        readOnly={true}
                        className={{
                          wrapper: 'min-w-32',
                        }}
                        disabled={true}
                      />
                    </td>
                    <td>
                      <TextInput
                        name={`items.${idx}.uom`}
                        type='text'
                        value={purchaseItem?.product?.uom?.name || ''}
                        readOnly={true}
                        className={{
                          wrapper: 'min-w-24',
                        }}
                        disabled={true}
                      />
                    </td>
                    <td>
                      <DateInput
                        required
                        isNestedModal={true}
                        name={`items.${idx}.received_date`}
                        value={formItem?.received_date || ''}
                        onChange={(e) =>
                          formik.setFieldValue(
                            `items.${idx}.received_date`,
                            e.target.value
                          )
                        }
                        onBlur={formik.handleBlur}
                        isError={
                          isRepeaterInputError(idx, 'received_date').isError
                        }
                        errorMessage={
                          isRepeaterInputError(idx, 'received_date')
                            .errorMessage
                        }
                        className={{
                          wrapper: 'min-w-40 md:min-w-52 lg:min-w-64',
                        }}
                      />
                    </td>
                    <td>
                      <TextInput
                        required
                        name={`items.${idx}.travel_number`}
                        type='text'
                        value={formItem?.travel_number || ''}
                        onChange={(e) =>
                          formik.setFieldValue(
                            `items.${idx}.travel_number`,
                            e.target.value
                          )
                        }
                        onBlur={formik.handleBlur}
                        isError={
                          isRepeaterInputError(idx, 'travel_number').isError
                        }
                        errorMessage={
                          isRepeaterInputError(idx, 'travel_number')
                            .errorMessage
                        }
                        placeholder='Masukkan no. surat jalan'
                        className={{
                          wrapper: 'min-w-40 md:min-w-52 lg:min-w-64',
                        }}
                      />
                    </td>
                    <td>
                      <TextInput
                        name={`items.${idx}.vehicle_number`}
                        type='text'
                        value={formItem?.vehicle_number || ''}
                        onChange={(e) =>
                          formik.setFieldValue(
                            `items.${idx}.vehicle_number`,
                            e.target.value
                          )
                        }
                        onBlur={formik.handleBlur}
                        disabled={!Boolean(formItem?.expedition_vendor)}
                        isError={
                          isRepeaterInputError(idx, 'vehicle_number').isError
                        }
                        errorMessage={
                          isRepeaterInputError(idx, 'vehicle_number')
                            .errorMessage
                        }
                        placeholder='Masukkan nomor kendaraan'
                        className={{
                          wrapper: 'min-w-40 md:min-w-52 lg:min-w-64',
                        }}
                      />
                    </td>
                    <td>
                      <SelectInput
                        isClearable={true}
                        value={formItem?.expedition_vendor ?? null}
                        key={`expedition-vendor-${idx}`}
                        onChange={(val) =>
                          expeditionVendorChangeHandler(idx, val)
                        }
                        options={getExpeditionVendorOptions()}
                        isLoading={isLoadingExpeditions}
                        onMenuScrollToBottom={loadMoreExpeditions}
                        isError={
                          isRepeaterInputError(idx, 'expedition_vendor_id')
                            .isError
                        }
                        errorMessage={
                          isRepeaterInputError(idx, 'expedition_vendor_id')
                            .errorMessage
                        }
                        placeholder='Pilih Vendor...'
                        className={{
                          wrapper: 'min-w-48 md:min-w-64 lg:min-w-72',
                        }}
                      />
                    </td>
                    <td>
                      <NumberInput
                        required
                        name={`items.${idx}.received_qty`}
                        value={formItem?.received_qty || ''}
                        onChange={(e) =>
                          handlePurchaseItemChange(
                            idx,
                            'received_qty',
                            e.target.value
                          )
                        }
                        onBlur={formik.handleBlur}
                        placeholder='Masukkan jumlah diterima'
                        allowNegative={false}
                        decimalScale={0}
                        thousandSeparator=','
                        decimalSeparator='.'
                        disabled={isReceivedQtyDisabled}
                        bottomLabel={
                          isReceivedQtyDisabled
                            ? 'Sudah chickin, tidak bisa diubah'
                            : `Total: ${purchaseItems[idx]?.quantity ? formatNumber(purchaseItems[idx].quantity) : 0}`
                        }
                        isError={
                          isRepeaterInputError(idx, 'received_qty').isError ||
                          (formItem?.received_qty
                            ? getQuantityExceededError(
                                idx,
                                Number(formItem.received_qty)
                              ) !== null
                            : false)
                        }
                        errorMessage={
                          isRepeaterInputError(idx, 'received_qty')
                            .errorMessage ||
                          (formItem?.received_qty
                            ? getQuantityExceededError(
                                idx,
                                Number(formItem.received_qty)
                              ) || undefined
                            : undefined)
                        }
                        className={{
                          wrapper: 'min-w-40 md:min-w-52 lg:min-w-64',
                        }}
                      />
                    </td>
                    <td>
                      <NumberInput
                        name={`items.${idx}.transport_per_item`}
                        value={formItem?.transport_per_item || ''}
                        onChange={(e) =>
                          handlePurchaseItemChange(
                            idx,
                            'transport_per_item',
                            e.target.value
                          )
                        }
                        onBlur={formik.handleBlur}
                        placeholder='Masukkan transport/item'
                        allowNegative={false}
                        decimalScale={2}
                        thousandSeparator=','
                        decimalSeparator='.'
                        inputPrefix={'Rp'}
                        disabled={!Boolean(formItem?.expedition_vendor)}
                        isError={
                          isRepeaterInputError(idx, 'transport_per_item')
                            .isError
                        }
                        errorMessage={
                          isRepeaterInputError(idx, 'transport_per_item')
                            .errorMessage
                        }
                        className={{
                          wrapper: 'min-w-40 md:min-w-52 lg:min-w-64',
                        }}
                      />
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        <div className={'col-span-2 my-2'}>
          <TextInput
            label='Notes'
            name='notes'
            value={formik.values.notes || ''}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            isError={formik.touched.notes && Boolean(formik.errors.notes)}
            errorMessage={formik.errors.notes as string}
            placeholder='Masukkan catatan'
          />
        </div>

        <div className={'col-span-2 my-2'}>
          <FileInput
            name='travel_documents'
            label='Dokumen Surat Jalan'
            accept='.pdf,.jpg,.jpeg,.png'
            ref={fileInputRef}
            onChange={(e) => {
              const files = Array.from(e.target.files || []);
              const invalidFiles = files.filter(
                (file) => file.size > 5 * 1024 * 1024
              );

              if (invalidFiles.length > 0) {
                toast.error('Ukuran dokumen maksimal 5 MB!');
                e.target.value = '';
                return;
              }

              formik.setFieldValue('travel_documents', files);
            }}
            onBlur={formik.handleBlur}
            bottomLabel={
              formik.values.travel_documents &&
              formik.values.travel_documents.length > 0
                ? `${formik.values.travel_documents.length} file(s) dipilih`
                : undefined
            }
            isError={
              formik.touched.travel_documents &&
              Boolean(formik.errors.travel_documents)
            }
            errorMessage={formik.errors.travel_documents as string}
          />
        </div>

        <div className='w-full mt-4'>
          {purchaseOrderFormErrorMessage && (
            <div role='alert' className='alert alert-error'>
              <Icon
                icon='material-symbols:error-outline'
                width={24}
                height={24}
              />
              <span>{purchaseOrderFormErrorMessage}</span>
            </div>
          )}

          {/* Error List Alert */}
          {formErrorList.length > 0 && (
            <AlertErrorList
              formErrorList={formErrorList}
              onClose={() => setFormErrorList([])}
            />
          )}
        </div>

        {/* Action buttons */}
        <div className='flex flex-row justify-between gap-2 flex-wrap mt-5'>
          <div className='flex flex-row justify-end gap-2 w-full'>
            <Button
              type='button'
              color='warning'
              className='px-4'
              onClick={() => {
                if (type === 'add') {
                  formik.resetForm();
                  formik.setFieldValue('travel_documents', []);
                  if (fileInputRef.current) {
                    fileInputRef.current.value = '';
                  }
                }
                setPurchaseOrderFormErrorMessage('');
                onCancel?.();
                onModalClose?.();
              }}
            >
              Cancel
            </Button>

            <Button
              type='submit'
              color='primary'
              className='px-4'
              isLoading={formik.isSubmitting}
              disabled={
                formik.isSubmitting || hasQuantityExceededErrors || isRejected
              }
            >
              Submit
            </Button>
          </div>
        </div>
      </div>
    </form>
  );
};

export default PurchaseOrderAcceptApprovalForm;
