'use client';

import Button from '@/components/Button';
import AlertErrorList from '@/components/helper/form/FormErrors';
import RequirePermission from '@/components/helper/RequirePermission';
import DateInput from '@/components/input/DateInput';
import DebouncedTextArea from '@/components/input/DebouncedTextArea';
import NumberInput from '@/components/input/NumberInput';
import { OptionType, useSelect } from '@/components/input/SelectInput';
import SelectInputRadio from '@/components/input/SelectInputRadio';
import Modal, { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
import {
  DeliveryProductToFieldValues,
  mergeSOwithDO,
  SalesProductToFieldValues,
  DeliveryOrderFormValues,
  DeliveryOrderSchema,
  getFilledMarketingFormInitialValues,
  SalesOrderFormValues,
  SalesOrderSchema,
} from '@/components/pages/marketing/form/MarketingForm.schema';
import { DeliveryOrderProductFormValues } from '@/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct.schema';
import { SalesOrderProductFormValues } from '@/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema';
import SalesOrderProductForm from '@/components/pages/marketing/form/repeater/sales-order/SalesOrderProductForm';
import SalesOrderProductTable from '@/components/pages/marketing/form/table-view/SalesOrderProductTable';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { formatDate } from '@/lib/helper';
import {
  MarketingApi,
  SalesOrderApi,
} from '@/services/api/marketing/marketing';
import { CustomerApi } from '@/services/api/master-data';
import { UserApi } from '@/services/api/user';
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
import { CreatedUser } from '@/types/api/api-general';
import {
  CreateSalesOrderPayload,
  CreateSalesOrderProductPayload,
  Marketing,
  UpdateDeliveryOrderPayload,
  UpdateSalesOrderPayload,
} from '@/types/api/marketing/marketing';
import { Customer } from '@/types/api/master-data/customer';
import { Icon } from '@iconify/react';
import { useFormik } from 'formik';
import { useRouter, useSearchParams } from 'next/navigation';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import toast from 'react-hot-toast';
import useSWR, { useSWRConfig } from 'swr';

const MemoizedSalesOrderProductTable = memo(SalesOrderProductTable);
const MemoizedSalesOrderProductForm = memo(SalesOrderProductForm);

const SalesOrderFormModal = ({
  initialValues,
}: {
  initialValues?: Marketing;
}) => {
  const router = useRouter();
  const searchParams = useSearchParams();

  const modalAction = searchParams.get('action');
  const marketingId = searchParams.get('id');

  const isModalActionForForm =
    modalAction === 'add' ||
    modalAction === 'edit' ||
    modalAction === 'add_delivery' ||
    modalAction === 'edit_delivery';

  const { mutate } = useSWRConfig();

  const refreshMarketing = () => {
    mutate(
      (key) => typeof key === 'string' && key.includes(MarketingApi.basePath)
    );
  };

  const { data: marketing, isLoading: isLoadingMarketing } = useSWR(
    isModalActionForForm && marketingId
      ? `detail-marketing-${marketingId}`
      : undefined,
    () => MarketingApi.getSingle(Number(marketingId))
  );

  // ================== FETCH OPTIONS ==================
  const {
    options: customerOptions,
    isLoadingOptions: isLoadingCustomerOptions,
    setInputValue: setInputCustomerValue,
    loadMore: loadMoreCustomer,
  } = useSelect<Customer>(CustomerApi.basePath, 'id', 'name');
  const {
    options: salesOptions,
    isLoadingOptions: isLoadingSalesOptions,
    setInputValue: setInputSalesValue,
    loadMore: loadMoreSales,
  } = useSelect<CreatedUser>(UserApi.basePath, 'id', 'name');

  /**
   * Step 1: General Information
   * Step 2: Repeater Add Product
   * Step 3: Submit
   */
  const [step, setStep] = useState(1);

  const formModal = useModal();
  const successModal = useModal();
  const deleteModal = useModal();
  const formRef = useRef<HTMLFormElement>(null);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  const [formikLastValues, setFormikLastValues] = useState<
    SalesOrderFormValues | undefined
  >(undefined);
  const [formErrorMessage, setFormErrorMessage] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [selectedMarketingProduct, setSelectedMarketingProduct] =
    useState<SalesOrderProductFormValues | null>(null);
  const [selectedDeliveryProduct, setSelectedDeliveryProduct] =
    useState<DeliveryOrderProductFormValues | null>(null);
  const [deliveryFormState, setDeliveryFormState] = useState<'add' | 'edit'>(
    'add'
  );
  const [deliveryOrderValues, setDeliveryOrderValues] = useState<
    DeliveryOrderProductFormValues[]
  >(
    mergeSOwithDO(
      initialValues?.sales_order?.map(SalesProductToFieldValues) ?? [],
      initialValues?.delivery_order?.flatMap((delivery) =>
        DeliveryProductToFieldValues(initialValues.sales_order, delivery)
      ) ?? []
    )
  );

  // ================== SETUP FORMIK ==================
  const formikInitialValues = useMemo<
    SalesOrderFormValues & DeliveryOrderFormValues
  >(() => {
    return {
      so_date: initialValues?.so_date || undefined,
      notes: initialValues?.notes || undefined,
      customer_id: initialValues?.customer?.id || undefined,
      sales_person_id: initialValues?.sales_person?.id || undefined,
      sales_person: initialValues?.sales_person
        ? {
            value: initialValues.sales_person.id,
            label: initialValues.sales_person.name,
          }
        : null,
      customer: initialValues?.customer
        ? {
            value: initialValues.customer.id,
            label: initialValues.customer.name,
          }
        : null,
      sales_order:
        initialValues?.sales_order?.map((product) =>
          SalesProductToFieldValues(product)
        ) ?? [],
      delivery_order: mergeSOwithDO(
        initialValues?.sales_order?.map(SalesProductToFieldValues) ?? [],
        initialValues?.delivery_order?.flatMap((delivery) =>
          DeliveryProductToFieldValues(initialValues.sales_order, delivery)
        ) ?? []
      ),
    };
  }, [initialValues]);
  const formik = useFormik<SalesOrderFormValues & DeliveryOrderFormValues>({
    enableReinitialize: true,
    initialValues: formikInitialValues,
    validationSchema:
      modalAction == 'add_deliver' || modalAction == 'edit_deliver'
        ? DeliveryOrderSchema
        : SalesOrderSchema,
    validateOnMount: true,
    onSubmit: async (values) => {
      const payload =
        modalAction != 'add_deliver' && modalAction != 'edit_deliver'
          ? ({
              customer_id: values.customer_id as number,
              sales_person_id: values.sales_person_id as number,
              date: formatDate(values.so_date as string, 'yyyy-MM-DD'),
              notes: values.notes as string,
              marketing_products: values.sales_order.map((product) => {
                // Workaround untuk TELUR + QTY: kirim "KG" karena BE tidak support "QTY"
                const convertionUnitValue =
                  product.convertion_unit?.value?.toUpperCase();
                const normalizedConvertionUnit =
                  product.marketing_type?.value?.toLowerCase() === 'telur'
                    ? convertionUnitValue === 'PETI'
                      ? 'PETI'
                      : 'KG' // termasuk "QTY" dan "KG"
                    : undefined;

                return {
                  vehicle_number: product.vehicle_number as string,
                  kandang_id: product.kandang_id as number,
                  product_warehouse_id: product.product_warehouse_id as number,
                  unit_price: parseFloat(String(product.unit_price || 0)),
                  total_weight: parseFloat(String(product.total_weight || 0)),
                  qty: parseFloat(String(product.qty || 0)),
                  avg_weight: parseFloat(String(product.avg_weight || 0)),
                  total_price: parseFloat(String(product.total_price || 0)),
                  marketing_type:
                    product.marketing_type?.value?.toUpperCase() || '',
                  convertion_unit: normalizedConvertionUnit,
                  weight_per_convertion:
                    product.weight_per_convertion ?? undefined,
                } as CreateSalesOrderProductPayload;
              }),
            } as CreateSalesOrderPayload)
          : ({
              marketing_id: initialValues?.id as number,
              delivery_products: values.delivery_order
                .map((product) => {
                  if (Boolean(product.delivery_date)) {
                    return {
                      marketing_product_id:
                        product.marketing_product_id as number,
                      unit_price: parseFloat(product.unit_price as string),
                      total_weight: parseFloat(product.total_weight as string),
                      qty: parseFloat(product.qty as string),
                      avg_weight: parseFloat(product.avg_weight as string),
                      total_price: parseFloat(product.total_price as string),
                      delivery_date: formatDate(
                        product.delivery_date as string,
                        'yyyy-MM-DD'
                      ),
                      vehicle_number: product.vehicle_number,
                    };
                  }
                })
                .filter((item) => Boolean(item)),
            } as UpdateDeliveryOrderPayload);
      switch (modalAction) {
        case 'add':
          await createMarketingHandler(payload as CreateSalesOrderPayload);
          break;
        case 'edit':
          await updateMarketingHandler(payload as UpdateSalesOrderPayload);
          break;
        default:
          break;
      }
    },
  });

  // ===== Formik Error List =====
  const { formErrorList, setFormErrorList, close, handleFormSubmit } =
    useFormikErrorList(formik, {
      onAfterSubmit: () => {
        router.push('/marketing');
      },
    });

  // ================== FORM REPEATER HANDLER ==================
  const createMarketingHandler = async (values: CreateSalesOrderPayload) => {
    setIsLoading(true);
    const createMarketingRes = await SalesOrderApi.create(values);
    if (isResponseSuccess(createMarketingRes)) {
      closeModalHandler(false);
      successModal.openModal();
      refreshMarketing();
    }
    if (isResponseError(createMarketingRes)) {
      toast.error(createMarketingRes?.message as string);
    }
    setIsLoading(false);
  };
  const updateMarketingHandler = async (values: UpdateSalesOrderPayload) => {
    setIsLoading(true);
    if (!marketingId) {
      toast.error('Marketing ID is required');
      setIsLoading(false);
      return;
    }
    const updateMarketingRes = await SalesOrderApi.update(
      Number(marketingId),
      values
    );
    if (isResponseSuccess(updateMarketingRes)) {
      closeModalHandler(false);
      successModal.openModal();
      refreshMarketing();
    }
    if (isResponseError(updateMarketingRes)) {
      toast.error(updateMarketingRes?.message as string);
    }
    setIsLoading(false);
  };

  const memoSalesOrder = formik.values.sales_order;

  // ================== HANDLER ==================
  const nextButtonHandler = () => {
    setStep(step + 1);
  };
  const prevButtonHandler = () => {
    setStep(step - 1);
  };
  const handleChangeCustomer = useCallback(
    (val: OptionType | OptionType[] | null) => {
      formik.setFieldValue('customer_id', (val as OptionType)?.value);
      formik.setFieldValue('customer', val as OptionType);
    },
    []
  );
  const handleChangeSalesPerson = useCallback(
    (val: OptionType | OptionType[] | null) => {
      formik.setFieldValue('sales_person_id', (val as OptionType)?.value);
      formik.setFieldValue('sales_person', val as OptionType);
    },
    []
  );

  const deleteClickHandler = () => {
    deleteModal.openModal();
  };

  const confirmationModalDeleteClickHandler = async () => {
    if (!marketingId) {
      toast.error(`Tidak ada data yang valid untuk di hapus.`);
      deleteModal.closeModal();
      return;
    }
    setIsLoading(true);
    const res = await MarketingApi.delete(Number(marketingId));
    deleteModal.closeModal();
    toast.success(res?.message as string);
    setIsLoading(false);
    refreshMarketing();
    closeModalHandler();
    router.replace('/marketing');
  };

  // ================== SALES ORDER HANDLER ==================
  const handleDeleteSO = useCallback(
    (id: number) => {
      const currentProducts = formik.values.sales_order;
      formik.setFieldValue(
        'sales_order',
        currentProducts.filter((p) => p.id != id)
      );
    },
    [memoSalesOrder]
  );
  const handleDeleteAllSO = useCallback(() => {
    formik.setFieldValue('sales_order', []);
  }, [memoSalesOrder]);
  const handleEditSO = useCallback(
    (id: number) => {
      const currentProducts = formik.values.sales_order;
      const selectedProduct = currentProducts.find((p) => p.id == id);
      setSelectedMarketingProduct(selectedProduct ?? null);
      setStep(2);
    },
    [memoSalesOrder]
  );
  const handleAddSOClick = useCallback(() => {
    setSelectedMarketingProduct(null);
    if (step === 3) {
      setStep(2);
    } else {
      prevButtonHandler();
    }
  }, [step]);
  const handleAddSubmitSO = useCallback(
    async (values: SalesOrderProductFormValues, id?: number) => {
      const currentProducts = formik.values.sales_order;

      const newValues = {
        ...values,
        id: values.id ?? Date.now(),
      };

      let updatedProducts = [];

      if (id) {
        // Overwrite
        updatedProducts = currentProducts.map((item) =>
          item.id === id ? newValues : item
        );
      } else {
        // Add new item
        updatedProducts = [...currentProducts, newValues];
      }

      formik.setFieldValue('sales_order', updatedProducts);
      console.log(formik.values);
      nextButtonHandler();
    },
    [memoSalesOrder, nextButtonHandler]
  );

  const isNextButtonDisabled = useMemo(() => {
    if (step === 1) {
      return Boolean(
        !formik.values.customer_id ||
          !formik.values.sales_person_id ||
          !formik.values.so_date ||
          !formik.values.notes
      );
    }

    return true;
  }, [step, formik.values]);

  // ================== EFFECT ==================
  useEffect(() => {
    if (modalAction === 'add' || modalAction === 'edit') {
      formModal.openModal();
    }
  }, [modalAction]);

  const closeModalHandler = (shouldPushToRoute: boolean = true) => {
    refreshMarketing();
    if (shouldPushToRoute) {
      formik.resetForm();
      textareaRef.current?.setAttribute('value', '');
      successModal.closeModal();
      router.push('/marketing');
    }

    setStep(1);
    setFormErrorMessage('');
    formModal.closeModal();
  };

  const grandTotal = useMemo(() => {
    return memoSalesOrder.reduce(
      (total, product) =>
        total + parseFloat((product.total_price as string) || '0'),
      0
    );
  }, [memoSalesOrder]);

  useEffect(() => {
    const getFilledInitialValues = async () => {
      if (marketingId && isResponseSuccess(marketing)) {
        const filledInitialValues = await getFilledMarketingFormInitialValues(
          marketing.data
        );

        formik.setValues(filledInitialValues);
        setStep(3);
      }

      if (isResponseError(marketing)) {
        router.push('/marketing');
        closeModalHandler();
        toast.error(marketing.message);
      }
    };

    getFilledInitialValues();
  }, [marketingId, marketing]);

  // Reset error message when step changes
  useEffect(() => {
    setFormErrorList([]);
    setFormErrorMessage('');
  }, [step]);

  useEffect(() => {
    if (memoSalesOrder.length === 0) {
      setStep(1);
    }
  }, [memoSalesOrder]);

  return (
    <>
      <Modal
        ref={formModal.ref}
        position='end'
        className={{
          modalBox: 'w-full sm:w-fit p-3 rounded-xl bg-transparent shadow-none',
        }}
      >
        <div
          onSubmit={(e) => {
            e.preventDefault();
          }}
          className='w-full min-h-full flex flex-col sm:flex-row items-stretch bg-base-100 rounded-xl overflow-y-auto'
        >
          {step <= 3 && (
            <div className='w-full sm:w-[446px]'>
              <div className='w-full p-4 flex flex-row items-stretch gap-3 border-b border-base-content/10'>
                <Button
                  type='button'
                  variant='ghost'
                  color='none'
                  onClick={() => closeModalHandler()}
                  className='p-0 text-black hover:text-base-content'
                >
                  <Icon icon='heroicons:x-mark' width={20} height={20} />
                </Button>

                <div className='w-px border-none bg-base-content/10' />

                <h4 className='text-sm font-medium text-base-content/50'>
                  {modalAction === 'add' ? 'Add' : 'Edit'} Sales Order
                </h4>
              </div>
              <form
                className='w-full p-4 flex flex-col border-b border-base-content/10'
                ref={formRef}
                onSubmit={handleFormSubmit}
              >
                <h4 className='text-base font-medium text-base-content/50 font-roboto'>
                  Informasi Order
                </h4>

                <SelectInputRadio
                  required
                  label='Pelanggan'
                  options={customerOptions}
                  isLoading={isLoadingCustomerOptions}
                  value={formik.values.customer}
                  onChange={handleChangeCustomer}
                  onInputChange={setInputCustomerValue}
                  onMenuScrollToBottom={loadMoreCustomer}
                  isError={
                    formik.touched.customer_id &&
                    Boolean(formik.errors.customer_id)
                  }
                  errorMessage={formik.errors.customer_id}
                  isClearable
                  placeholder='Pilih Pelanggan'
                  isDisabled={
                    modalAction === 'add_deliver' ||
                    modalAction === 'edit_deliver' ||
                    modalAction === 'edit'
                  }
                />
                <DateInput
                  required
                  name='so_date'
                  label='Tanggal'
                  value={formik.values.so_date}
                  onChange={formik.handleChange}
                  isError={
                    formik.touched.so_date && Boolean(formik.errors.so_date)
                  }
                  errorMessage={formik.errors.so_date}
                  placeholder='Pilih Tanggal'
                  readOnly={
                    modalAction == 'add_deliver' ||
                    modalAction == 'edit_deliver'
                  }
                />
                <SelectInputRadio
                  required
                  label='Sales'
                  options={salesOptions}
                  isLoading={isLoadingSalesOptions}
                  value={formik.values.sales_person}
                  onChange={handleChangeSalesPerson}
                  onInputChange={setInputSalesValue}
                  onMenuScrollToBottom={loadMoreSales}
                  isError={
                    formik.touched.sales_person_id &&
                    Boolean(formik.errors.sales_person_id)
                  }
                  errorMessage={formik.errors.sales_person_id}
                  isClearable
                  placeholder='Pilih Sales'
                  isDisabled={
                    modalAction === 'add_deliver' ||
                    modalAction === 'edit_deliver'
                  }
                />
                <DebouncedTextArea
                  ref={textareaRef}
                  required
                  name='notes'
                  label='Catatan'
                  rows={3}
                  placeholder='Masukan catatan penjualan'
                  value={formik.values.notes || ''}
                  onChange={formik.handleChange}
                  isError={formik.touched.notes && Boolean(formik.errors.notes)}
                  errorMessage={formik.errors.notes}
                  disabled={
                    modalAction === 'add_deliver' ||
                    modalAction === 'edit_deliver'
                  }
                />
                <NumberInput
                  name='total_price'
                  label='Total Penjualan'
                  value={grandTotal}
                  disabled={
                    grandTotal === 0 && formik.values.sales_order.length === 0
                  }
                  readOnly
                  startAdornment={
                    <span className='font-semibold py-1 text-xs'>Rp</span>
                  }
                />
                <AlertErrorList
                  className={{
                    alert: 'w-full mt-4',
                  }}
                  formErrorList={formErrorList}
                  onClose={close}
                />
              </form>

              <div className='w-full p-4'>
                {step === 1 && (
                  <Button
                    type='button'
                    onClick={nextButtonHandler}
                    disabled={isNextButtonDisabled}
                    className='w-full rounded-lg text-sm text-base-100'
                  >
                    Tambah Produk
                  </Button>
                )}
              </div>
            </div>
          )}
          {step === 2 && (
            <div className='w-full min-h-full flex flex-col sm:w-[446px] border-l border-base-content/10'>
              <div className='w-full p-4 flex flex-row items-center justify-between gap-3 border-b border-base-content/10'>
                <div className='w-full flex flex-row items-stretch gap-3'>
                  {memoSalesOrder.length > 0 && (
                    <>
                      <Button
                        type='button'
                        variant='ghost'
                        color='none'
                        onClick={() => {
                          setStep(3);
                        }}
                        className='p-0 text-black hover:text-base-content'
                      >
                        <Icon
                          icon='heroicons:chevron-left'
                          width={20}
                          height={20}
                        />
                      </Button>

                      <div className='w-px border-none bg-base-content/10' />
                    </>
                  )}

                  <h4 className='text-sm font-medium text-base-content/50'>
                    {selectedMarketingProduct?.id ? 'Ubah' : 'Tambah'} Produk
                  </h4>
                </div>
                <RequirePermission permissions='lti.marketing.sales_order.delete'>
                  <Button
                    type='button'
                    variant='ghost'
                    color='none'
                    onClick={deleteClickHandler}
                    className='p-0 text-error hover:text-base-content'
                  >
                    <Icon icon='heroicons:trash' width={20} height={20} />
                  </Button>
                </RequirePermission>
              </div>
              <div className='flex flex-1 flex-col'>
                <MemoizedSalesOrderProductForm
                  onSubmitForm={handleAddSubmitSO}
                  initialValues={selectedMarketingProduct ?? undefined}
                  exisitingValues={memoSalesOrder}
                />
              </div>
            </div>
          )}
          {step === 3 && (
            <div className='w-full min-h-full flex flex-col sm:w-[446px] border-l border-base-content/10 relative'>
              <div className='w-full p-4 flex flex-row items-center justify-between gap-3 border-b border-base-content/10'>
                <h4 className='text-sm font-medium text-base-content/50'>
                  Informasi Produk
                </h4>
                <RequirePermission permissions='lti.marketing.sales_order.delete'>
                  <Button
                    type='button'
                    variant='ghost'
                    color='none'
                    onClick={deleteClickHandler}
                    className='p-0 text-error hover:text-base-content'
                  >
                    <Icon icon='heroicons:trash' width={20} height={20} />
                  </Button>
                </RequirePermission>
              </div>
              <div className='flex flex-1 flex-col'>
                {memoSalesOrder.length > 0 && (
                  <div className='px-4 pt-4'>
                    <MemoizedSalesOrderProductTable
                      formType={(modalAction || 'add') as 'add' | 'edit'}
                      data={memoSalesOrder}
                      onDelete={handleDeleteSO}
                      onEdit={handleEditSO}
                      onAddProductClick={handleAddSOClick}
                    />
                  </div>
                )}
                <div className='p-4 w-full'>
                  <Button
                    type='button'
                    className='justify-center w-full p-3 rounded-lg text-center text-sm text-base-100'
                    onClick={() => formRef.current?.requestSubmit()}
                  >
                    Submit
                  </Button>
                </div>
              </div>
            </div>
          )}
        </div>
      </Modal>
      <ConfirmationModal
        ref={successModal.ref}
        iconPosition='left'
        type='success'
        text={`${modalAction === 'add' ? 'Data Berhasil Ditambahkan' : 'Data Berhasil Diubah'}`}
        subtitleText={`${modalAction === 'add' ? 'Data sales order telah berhasil disimpan.' : 'Data sales order telah berhasil diubah.'}`}
        primaryButton={{
          text: 'Oke',
          color: 'primary',
          className: 'rounded-lg',
          onClick: (e) => {
            closeModalHandler();
          },
        }}
      >
        <MemoizedSalesOrderProductTable
          formType={'success'}
          data={memoSalesOrder}
          onDelete={handleDeleteSO}
          onEdit={handleEditSO}
          onAddProductClick={handleAddSOClick}
        />
      </ConfirmationModal>

      <ConfirmationModal
        ref={deleteModal.ref}
        type='error'
        text={`Apakah anda yakin ingin menghapus data penjualan ini?`}
        secondaryButton={{
          text: 'Tidak',
        }}
        primaryButton={{
          text: 'Ya',
          color: 'error',
          isLoading: isLoading,
          onClick: confirmationModalDeleteClickHandler,
        }}
      />
    </>
  );
};

export default SalesOrderFormModal;
