'use client';

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

import { Icon } from '@iconify/react';
import Button from '@/components/Button';
import DateInput from '@/components/input/DateInput';
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
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 PurchaseInlineFilterProps {
  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;
  };
  searchValue?: string;
  onSearchChange?: ChangeEventHandler<HTMLInputElement>;
  onSubmit?: (values: PurchaseFilter) => void;
  onReset?: () => void;
}

const PurchaseInlineFilter = ({
  initialValues,
  searchValue,
  onSearchChange,
  onSubmit,
  onReset,
}: PurchaseInlineFilterProps) => {
  const [hasDateError, setHasDateError] = useState(false);
  const [dateErrorShown, setDateErrorShown] = useState(false);

  useEffect(() => {
    return () => {
      if (dateErrorShown) {
        toast.dismiss();
      }
    };
  }, [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;
  }>({
    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);
    },
  });

  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?.();
  }, [resetForm, onReset, 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 (
    <form
      onSubmit={formik.handleSubmit}
      onReset={formikResetHandler}
      className='w-full p-4 border-b border-base-content/10'
    >
      <div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-x-4 gap-y-1'>
        {/* Row 1: Tanggal Awal, Tanggal Akhir, Filter Berdasarkan, PO Date */}
        <DateInput
          label='Tanggal Awal'
          name='start_date'
          placeholder='Pilih tanggal'
          value={formik.values.start_date}
          onChange={handleStartDateChange}
        />

        <DateInput
          label='Tanggal Akhir'
          name='end_date'
          placeholder='Pilih tanggal'
          value={formik.values.end_date}
          onChange={handleEndDateChange}
          isError={hasDateError}
        />

        <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}
        />

        {/* Row 2: Area, Lokasi, Project Flock, Kandang */}
        <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}
        />

        {/* Row 3: Kategori, Status, Vendor, Search */}
        <SelectInputCheckbox
          label='Kategori Produk'
          placeholder='Pilih Kategori'
          value={formik.values.category}
          onChange={productCategoryChangeHandler}
          options={productCategoryOptions}
          isLoading={isLoadingProductCategoryOptions}
          onInputChange={setProductCategoryInputValue}
          onMenuScrollToBottom={loadMoreProductCategory}
        />

        <SelectInputCheckbox
          label='Status'
          placeholder='Pilih 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
        />

        <div className='flex flex-col'>
          <label className='block text-xs font-semibold text-base-content py-2'>
            Search
          </label>
          <DebouncedTextInput
            name='search'
            placeholder='Cari...'
            value={searchValue ?? ''}
            onChange={onSearchChange}
            startAdornment={
              <Icon icon='heroicons:magnifying-glass' width={20} height={20} />
            }
            className={{
              inputWrapper: 'rounded-xl! shadow-button-soft',
              input:
                'placeholder:font-semibold placeholder:text-base-content/50',
            }}
          />
          <p className='text-xs text-base-content/50 mt-1'>
            Bisa cari PR/PO, vendor, produk, atau PO ekspedisi (biaya
            pengiriman).
          </p>
        </div>
      </div>

      <div className='flex justify-end gap-3 mt-4'>
        <Button
          type='reset'
          variant='outline'
          color='none'
          className='px-4 py-2.5 rounded-xl text-sm text-base-content/65'
        >
          Reset
        </Button>

        <Button
          type='button'
          onClick={formikSubmitHandler}
          disabled={hasDateError}
          className='px-4 py-2.5 rounded-xl text-sm text-base-100'
        >
          Cari
        </Button>
      </div>
    </form>
  );
};

export default PurchaseInlineFilter;
