'use client';

import { RefObject, useState, useEffect, useMemo, useCallback } from 'react';
import { useFormik } from 'formik';
import toast from 'react-hot-toast';

import { Icon } from '@iconify/react';
import Modal from '@/components/Modal';
import Button from '@/components/Button';
import DateInput from '@/components/input/DateInput';
import SelectInputCheckbox from '@/components/input/SelectInputCheckbox';
import SelectInput from '@/components/input/SelectInput';
import SelectInputRadio from '@/components/input/SelectInputRadio';

import { OptionType, useSelect } from '@/components/input/SelectInput';
import { PurchaseFilter } from '@/types/api/purchase/purchase';
import { AreaApi, LocationApi, SupplierApi } from '@/services/api/master-data';
import { ProductCategory } from '@/types/api/master-data/product-category';
import { ProductCategoryApi } from '@/services/api/master-data';
import { Area } from '@/types/api/master-data/area';
import { Location } from '@/types/api/master-data/location';
import { Supplier } from '@/types/api/master-data/supplier';
import { PURCHASE_ORDER_APPROVAL_LINE } from '@/config/approval-line';
import { ProjectFlockApi } from '@/services/api/production';
import { ProjectFlock } from '@/types/api/production/project-flock';
import { isResponseSuccess } from '@/lib/api-helper';

const filterByOptions: OptionType<string>[] = [
  { value: 'po_date', label: 'Tanggal PO' },
  { value: 'received_date', label: 'Tanggal Terima' },
  { value: 'due_date', label: 'Tanggal Jatuh Tempo' },
  { value: 'created_at', label: 'Tanggal Dibuat' },
];

interface PurchaseFilterModalProps {
  ref: RefObject<HTMLDialogElement | null>;
  initialValues?: {
    poDate: string;
    start_date: string;
    end_date: string;
    filterBy: OptionType<string> | undefined;
    category: OptionType<number>[];
    status: OptionType<string>[];
    supplier: OptionType<number> | null;
    area: OptionType<number> | null;
    location: OptionType<number> | null;
    project_flock: OptionType<number> | null;
    project_flock_kandang: OptionType<number> | null;
  };
  onSubmit?: (values: PurchaseFilter) => void;
  onReset?: () => void;
}

const PurchaseFilterModal = ({
  ref,
  initialValues,
  onSubmit,
  onReset,
}: PurchaseFilterModalProps) => {
  const closeModalHandler = useCallback(() => {
    ref.current?.close();
  }, [ref]);

  // ===== DATE ERROR STATE =====
  const [hasDateError, setHasDateError] = useState(false);
  const [dateErrorShown, setDateErrorShown] = useState(false);

  // ===== CLEANUP TOAST ON UNMOUNT =====
  useEffect(() => {
    return () => {
      if (dateErrorShown) {
        toast.dismiss();
      }
    };
  }, [dateErrorShown]);

  // ===== CLEANUP TOAST WHEN MODAL CLOSES =====
  useEffect(() => {
    const dialogElement = ref.current;
    const handleModalClose = () => {
      if (dateErrorShown) {
        toast.dismiss();
        setDateErrorShown(false);
      }
    };

    dialogElement?.addEventListener('close', handleModalClose);

    return () => {
      dialogElement?.removeEventListener('close', handleModalClose);
    };
  }, [ref, dateErrorShown]);

  const {
    setInputValue: setProductCategoryInputValue,
    options: productCategoryOptions,
    isLoadingOptions: isLoadingProductCategoryOptions,
    loadMore: loadMoreProductCategory,
  } = useSelect<ProductCategory>(
    ProductCategoryApi.basePath,
    'id',
    'name',
    'search'
  );

  const [selectedAreaId, setSelectedAreaId] = useState(
    initialValues?.area?.value ? String(initialValues.area.value) : ''
  );
  const [selectedLocationId, setSelectedLocationId] = useState(
    initialValues?.location?.value ? String(initialValues.location.value) : ''
  );

  const {
    setInputValue: setSupplierInputValue,
    options: supplierOptions,
    isLoadingOptions: isLoadingSupplierOptions,
    loadMore: loadMoreSuppliers,
  } = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name', 'search');

  const {
    setInputValue: setAreaInputValue,
    options: areaOptions,
    isLoadingOptions: isLoadingAreaOptions,
    loadMore: loadMoreAreas,
  } = useSelect<Area>(AreaApi.basePath, 'id', 'name', 'search');

  const {
    setInputValue: setLocationInputValue,
    options: locationOptions,
    isLoadingOptions: isLoadingLocationOptions,
    loadMore: loadMoreLocations,
  } = useSelect<Location>(LocationApi.basePath, 'id', 'name', 'search', {
    area_id: selectedAreaId || '',
  });

  const {
    setInputValue: setProjectFlockInputValue,
    options: projectFlockOptions,
    rawData: projectFlocksRawData,
    isLoadingOptions: isLoadingProjectFlockOptions,
    loadMore: loadMoreProjectFlocks,
  } = useSelect<ProjectFlock>(
    ProjectFlockApi.basePath,
    'id',
    'flock_name',
    'search',
    {
      location_id: selectedLocationId || '',
    }
  );

  const formik = useFormik<{
    poDate: string;
    start_date: string;
    end_date: string;
    filterBy: OptionType<string> | undefined;
    category: { label: string; value: number }[];
    status: { label: string; value: string }[];
    supplier: OptionType<number> | null;
    area: OptionType<number> | null;
    location: OptionType<number> | null;
    project_flock: OptionType<number> | null;
    project_flock_kandang: OptionType<number> | null;
  }>({
    // enableReinitialize: true,
    initialValues: initialValues || {
      poDate: '',
      start_date: '',
      end_date: '',
      filterBy: undefined,
      category: [],
      status: [],
      supplier: null,
      area: null,
      location: null,
      project_flock: null,
      project_flock_kandang: null,
    },
    onSubmit: async (values) => {
      const formattedValues = {
        ...values,
        category: values.category.map((item) => String(item.value)),
        category_labels: values.category,
        status: values.status.map((item) => String(item.value)),
        supplier_id: values.supplier?.value,
        supplier_label: values.supplier?.label,
        area_id: values.area?.value,
        area_label: values.area?.label,
        location_id: values.location?.value,
        location_label: values.location?.label,
        project_flock_id: values.project_flock?.value,
        project_flock_label: values.project_flock?.label,
        project_flock_kandang_id: values.project_flock_kandang?.value,
        project_flock_kandang_label: values.project_flock_kandang?.label,
      };

      onSubmit?.(formattedValues);
      closeModalHandler();
    },
    onReset: () => {
      setSelectedAreaId('');
      setSelectedLocationId('');
      onReset?.();
      closeModalHandler();
    },
  });

  const { resetForm, submitForm } = formik;

  useEffect(() => {
    setSelectedAreaId(
      initialValues?.area?.value ? String(initialValues.area.value) : ''
    );
    setSelectedLocationId(
      initialValues?.location?.value ? String(initialValues.location.value) : ''
    );
  }, [initialValues?.area, initialValues?.location]);

  const projectFlockKandangOptions = useMemo(() => {
    if (
      !formik.values.project_flock ||
      !projectFlocksRawData ||
      !isResponseSuccess(projectFlocksRawData)
    ) {
      return [];
    }

    const selectedProjectFlock = projectFlocksRawData.data.find(
      (item) => item.id === formik.values.project_flock?.value
    );

    return (
      selectedProjectFlock?.kandangs?.map((item) => ({
        value: item.project_flock_kandang_id,
        label: item.name,
      })) || []
    );
  }, [formik.values.project_flock, projectFlocksRawData]);

  const productCategoryChangeHandler = (
    val: OptionType | OptionType[] | null
  ) => {
    formik.setFieldValue('category', val);
  };

  const statusChangeHandler = (val: OptionType | OptionType[] | null) => {
    formik.setFieldValue('status', val);
  };

  const formikResetHandler = useCallback(() => {
    setHasDateError(false);
    if (dateErrorShown) {
      toast.dismiss();
      setDateErrorShown(false);
    }
    resetForm({
      values: {
        poDate: '',
        start_date: '',
        end_date: '',
        filterBy: undefined,
        category: [],
        status: [],
        supplier: null,
        area: null,
        location: null,
        project_flock: null,
        project_flock_kandang: null,
      },
    });
    setSelectedAreaId('');
    setSelectedLocationId('');
    onReset?.();
    closeModalHandler();
  }, [resetForm, onReset, closeModalHandler, dateErrorShown]);

  const handleStartDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    formik.setFieldValue('start_date', value);

    if (value && formik.values.end_date) {
      if (new Date(formik.values.end_date) < new Date(value)) {
        setHasDateError(true);
        if (!dateErrorShown) {
          toast.error('Tanggal akhir tidak boleh sebelum tanggal mulai', {
            duration: Infinity,
          });
          setDateErrorShown(true);
        }
      } else {
        setHasDateError(false);
        if (dateErrorShown) {
          toast.dismiss();
          setDateErrorShown(false);
        }
      }
    } else {
      setHasDateError(false);
    }
  };

  const handleEndDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    formik.setFieldValue('end_date', value);

    if (value && formik.values.start_date) {
      if (new Date(value) < new Date(formik.values.start_date)) {
        setHasDateError(true);
        if (!dateErrorShown) {
          toast.error('Tanggal akhir tidak boleh sebelum tanggal mulai', {
            duration: Infinity,
          });
          setDateErrorShown(true);
        }
        return;
      }
    }

    setHasDateError(false);
    if (dateErrorShown) {
      toast.dismiss();
      setDateErrorShown(false);
    }
  };

  const formikSubmitHandler = useCallback(async () => {
    await submitForm();
  }, [submitForm]);

  return (
    <Modal
      ref={ref}
      className={{
        modalBox: 'p-0 rounded-xl',
      }}
    >
      <form
        onSubmit={formik.handleSubmit}
        onReset={formikResetHandler}
        className='w-full flex flex-col'
      >
        {/* Modal Header */}
        <div className='p-4 flex items-center justify-between gap-2 border-b border-gray-300'>
          <div className='flex items-center gap-2 text-primary'>
            <Icon icon='heroicons:funnel' width={20} height={20} />
            <h3 className='text-sm font-medium'>Filter Data</h3>
          </div>

          <Button
            type='button'
            variant='ghost'
            color='none'
            onClick={() => {
              closeModalHandler();
            }}
            className='p-0 text-base-content/50 hover:text-base-content'
          >
            <Icon icon='heroicons:x-mark' width={20} height={20} />
          </Button>
        </div>

        {/* Modal Body */}
        <div className='p-4 flex flex-col gap-1.5'>
          <div className='flex flex-col'>
            <div>
              <label className='block text-xs font-semibold text-base-content py-2'>
                Tanggal
              </label>
              <div className='flex flex-row gap-1.5 items-center justify-between'>
                <DateInput
                  name='start_date'
                  value={formik.values.start_date}
                  onChange={handleStartDateChange}
                  className={{ wrapper: 'w-full' }}
                  isNestedModal
                />
                <hr className='w-full max-w-3 h-px border-base-content/10' />
                <DateInput
                  name='end_date'
                  value={formik.values.end_date}
                  onChange={handleEndDateChange}
                  className={{ wrapper: 'w-full' }}
                  isNestedModal
                  isError={hasDateError}
                />
              </div>
            </div>

            <SelectInputRadio
              label='Filter Berdasarkan'
              placeholder='Pilih Filter Berdasarkan'
              options={filterByOptions}
              value={formik.values.filterBy ?? null}
              onChange={(val) =>
                formik.setFieldValue(
                  'filterBy',
                  !Array.isArray(val) ? (val ?? undefined) : undefined
                )
              }
              isClearable
            />

            <DateInput
              label='PO Date'
              name='poDate'
              placeholder='Pilih Tanggal'
              value={formik.values.poDate}
              onChange={formik.handleChange}
              isNestedModal
            />

            <SelectInputCheckbox
              label='Kategori'
              placeholder='Pilih Kategori'
              value={formik.values.category}
              onChange={productCategoryChangeHandler}
              options={productCategoryOptions}
              isLoading={isLoadingProductCategoryOptions}
              onInputChange={setProductCategoryInputValue}
              onMenuScrollToBottom={loadMoreProductCategory}
            />

            <SelectInputCheckbox
              label='Status'
              placeholder='Status'
              value={formik.values.status}
              onChange={statusChangeHandler}
              options={PURCHASE_ORDER_APPROVAL_LINE.map((item) => ({
                label: item.step_name,
                value: item.step_name,
              }))}
            />

            <SelectInput
              label='Vendor'
              placeholder='Pilih Vendor'
              value={formik.values.supplier}
              onChange={(val) =>
                formik.setFieldValue(
                  'supplier',
                  !Array.isArray(val)
                    ? (val as OptionType<number> | null)
                    : null
                )
              }
              options={supplierOptions}
              isLoading={isLoadingSupplierOptions}
              onInputChange={setSupplierInputValue}
              onMenuScrollToBottom={loadMoreSuppliers}
              isClearable
            />

            <SelectInput
              label='Area'
              placeholder='Pilih Area'
              value={formik.values.area}
              onChange={(val) => {
                const nextValue = !Array.isArray(val)
                  ? (val as OptionType<number> | null)
                  : null;
                formik.setFieldValue('area', nextValue);
                formik.setFieldValue('location', null);
                formik.setFieldValue('project_flock', null);
                formik.setFieldValue('project_flock_kandang', null);
                setSelectedAreaId(
                  nextValue?.value ? String(nextValue.value) : ''
                );
                setSelectedLocationId('');
              }}
              options={areaOptions}
              isLoading={isLoadingAreaOptions}
              onInputChange={setAreaInputValue}
              onMenuScrollToBottom={loadMoreAreas}
              isClearable
            />

            <SelectInput
              label='Lokasi'
              placeholder='Pilih Lokasi'
              value={formik.values.location}
              onChange={(val) => {
                const nextValue = !Array.isArray(val)
                  ? (val as OptionType<number> | null)
                  : null;
                formik.setFieldValue('location', nextValue);
                formik.setFieldValue('project_flock', null);
                formik.setFieldValue('project_flock_kandang', null);
                setSelectedLocationId(
                  nextValue?.value ? String(nextValue.value) : ''
                );
              }}
              options={locationOptions}
              isLoading={isLoadingLocationOptions}
              onInputChange={setLocationInputValue}
              onMenuScrollToBottom={loadMoreLocations}
              isClearable
              isDisabled={!formik.values.area}
            />

            <SelectInput
              label='Project Flock'
              placeholder='Pilih Project Flock'
              value={formik.values.project_flock}
              onChange={(val) => {
                const nextValue = !Array.isArray(val)
                  ? (val as OptionType<number> | null)
                  : null;
                formik.setFieldValue('project_flock', nextValue);
                formik.setFieldValue('project_flock_kandang', null);
              }}
              options={projectFlockOptions}
              isLoading={isLoadingProjectFlockOptions}
              onInputChange={setProjectFlockInputValue}
              onMenuScrollToBottom={loadMoreProjectFlocks}
              isClearable
              isDisabled={!formik.values.location}
            />

            <SelectInput
              label='Kandang'
              placeholder='Pilih Kandang'
              value={formik.values.project_flock_kandang}
              onChange={(val) =>
                formik.setFieldValue(
                  'project_flock_kandang',
                  !Array.isArray(val)
                    ? (val as OptionType<number> | null)
                    : null
                )
              }
              options={projectFlockKandangOptions}
              isClearable
              isDisabled={!formik.values.project_flock}
            />
          </div>
        </div>

        {/* Modal Footer */}
        <div className='p-4 flex justify-between gap-4 border-t border-gray-300 bg-gray-100'>
          <Button
            type='reset'
            variant='ghost'
            color='none'
            className='p-3 rounded-lg text-base-content/65'
          >
            Reset Filter
          </Button>

          <Button
            type='button'
            onClick={formikSubmitHandler}
            disabled={hasDateError}
            className='p-3 rounded-lg w-fit sm:w-full max-w-40 text-base-100 text-sm'
          >
            Apply Filter
          </Button>
        </div>
      </form>
    </Modal>
  );
};

export default PurchaseFilterModal;
