'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import { useRouter } from 'next/navigation';
import { useFormik } from 'formik';
import { toast } from 'react-hot-toast';

import { Icon } from '@iconify/react';
import Button from '@/components/Button';
import TextInput from '@/components/input/TextInput';
import SelectInput, {
  OptionType,
  useSelect,
} from '@/components/input/SelectInput';
import { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
import RequirePermission from '@/components/helper/RequirePermission';

import {
  WarehouseFormSchema,
  WarehouseFormValues,
  UpdateWarehouseFormSchema,
} from '@/components/pages/master-data/warehouse/form/WarehouseForm.schema';
import { isResponseError } from '@/lib/api-helper';
import {
  Warehouse,
  CreateWarehousePayload,
  UpdateWarehousePayload,
} from '@/types/api/master-data/warehouse';
import {
  AreaApi,
  KandangApi,
  LocationApi,
  WarehouseApi,
} from '@/services/api/master-data';
import { cn } from '@/lib/helper';
import { WAREHOUSE_TYPE_OPTIONS } from '@/config/constant';
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
import AlertErrorList from '@/components/helper/form/FormErrors';
import { Area } from '@/types/api/master-data/area';
import { Kandang } from '@/types/api/master-data/kandang';

interface WarehouseFormProps {
  type?: 'add' | 'edit' | 'detail';
  initialValues?: Warehouse;
}

const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => {
  const router = useRouter();
  const deleteModal = useModal();

  const [warehouseFormErrorMessage, setWarehouseFormErrorMessage] =
    useState('');
  const [isDeleteLoading, setIsDeleteLoading] = useState(false);

  const createWarehouseHandler = useCallback(
    async (payload: CreateWarehousePayload) => {
      const createWarehouseRes = await WarehouseApi.create(payload);

      if (isResponseError(createWarehouseRes)) {
        setWarehouseFormErrorMessage(createWarehouseRes.message);
        return;
      }

      toast.success(createWarehouseRes?.message as string);
      router.push('/master-data/warehouse');
    },
    [router]
  );

  const updateWarehouseHandler = useCallback(
    async (warehouseId: number, payload: UpdateWarehousePayload) => {
      const updateWarehouseRes = await WarehouseApi.update(
        warehouseId,
        payload
      );

      if (updateWarehouseRes?.status === 'error') {
        setWarehouseFormErrorMessage(updateWarehouseRes.message);
        return;
      }

      toast.success(updateWarehouseRes?.message as string);
      router.refresh();
      router.push('/master-data/warehouse');
    },
    [router]
  );

  const formikInitialValues = useMemo<WarehouseFormValues>(() => {
    switch (initialValues?.type) {
      case 'AREA':
        return {
          name: initialValues?.name ?? '',
          type: initialValues?.type ?? 'AREA',
          areaId: initialValues?.area?.id ?? 0,
          area: initialValues?.area
            ? {
                value: initialValues.area.id,
                label: initialValues.area.name,
              }
            : null,
          locationId: 0,
          location: null,
          kandangId: 0,
          kandang: null,
        };

      case 'LOKASI':
        return {
          name: initialValues?.name ?? '',
          type: initialValues?.type ?? 'LOKASI',
          areaId: initialValues?.area?.id ?? 0,
          area: initialValues?.area
            ? {
                value: initialValues.area.id,
                label: initialValues.area.name,
              }
            : null,
          locationId: initialValues?.location?.id ?? 0,
          location: initialValues?.location
            ? {
                value: initialValues.location.id,
                label: initialValues.location.name,
              }
            : null,
          kandangId: 0,
          kandang: null,
        };

      case 'KANDANG':
        return {
          name: initialValues?.name ?? '',
          type: initialValues?.type ?? 'KANDANG',
          areaId: initialValues?.area?.id ?? 0,
          area: initialValues?.area
            ? {
                value: initialValues.area.id,
                label: initialValues.area.name,
              }
            : null,
          locationId: initialValues?.location?.id ?? 0,
          location: initialValues?.location
            ? {
                value: initialValues.location.id,
                label: initialValues.location.name,
              }
            : null,
          kandangId: initialValues?.kandang?.id ?? 0,
          kandang: initialValues?.kandang
            ? {
                value: initialValues.kandang.id,
                label: initialValues.kandang.name,
              }
            : null,
        };

      default:
        return {
          name: '',
          type: 'AREA',
          areaId: 0,
          area: null,
          locationId: 0,
          location: null,
          kandangId: 0,
          kandang: null,
        };
    }
  }, [initialValues]);

  const formik = useFormik<WarehouseFormValues>({
    initialValues: formikInitialValues,
    validationSchema:
      type === 'edit' ? UpdateWarehouseFormSchema : WarehouseFormSchema,
    onSubmit: async (values) => {
      setWarehouseFormErrorMessage('');

      let warehousePayload: CreateWarehousePayload | undefined = undefined;

      switch (values.type) {
        case 'AREA':
          warehousePayload = {
            name: values.name,
            type: values.type,
            area_id: values.areaId as number,
          };
          break;

        case 'LOKASI':
          warehousePayload = {
            name: values.name,
            type: values.type,
            area_id: values.areaId as number,
            location_id: values.locationId as number,
          };
          break;

        case 'KANDANG':
          warehousePayload = {
            name: values.name,
            type: values.type,
            area_id: values.areaId as number,
            location_id: values.locationId as number,
            kandang_id: values.kandangId as number,
          };
          break;
      }

      switch (type) {
        case 'add':
          await createWarehouseHandler(warehousePayload);
          break;

        case 'edit':
          await updateWarehouseHandler(
            initialValues?.id as number,
            warehousePayload
          );
          break;
      }
    },
  });

  const { setValues: formikSetValues } = formik;

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

  // Location
  const {
    setInputValue: setLocationSelectInputValue,
    options: locationOptions,
    isLoadingOptions: isLoadingLocationOptions,
    loadMore: loadMoreLocations,
  } = useSelect<Location>(LocationApi.basePath, 'id', 'name');

  // Kandang
  const {
    setInputValue: setKandangSelectInputValue,
    options: kandangOptions,
    isLoadingOptions: isLoadingKandangOptions,
    loadMore: loadMoreKandangs,
  } = useSelect<Kandang>(KandangApi.basePath, 'id', 'name');

  const typeChangeHandler = (val: OptionType | OptionType[] | null) => {
    formik.setFieldTouched('type', true);
    formik.setFieldValue('type', (val as OptionType)?.value);
  };

  const areaChangeHandler = (val: OptionType | OptionType[] | null) => {
    formik.setFieldTouched('area', true);
    formik.setFieldValue('area', val);

    formik.setFieldTouched('areaId', true);
    formik.setFieldValue('areaId', (val as OptionType)?.value);
  };

  const locationChangeHandler = (val: OptionType | OptionType[] | null) => {
    formik.setFieldTouched('location', true);
    formik.setFieldValue('location', val);

    formik.setFieldTouched('locationId', true);
    formik.setFieldValue('locationId', (val as OptionType)?.value);
  };

  const kandangChangeHandler = (val: OptionType | OptionType[] | null) => {
    formik.setFieldTouched('kandang', true);
    formik.setFieldValue('kandang', val);

    formik.setFieldTouched('kandangId', true);
    formik.setFieldValue('kandangId', (val as OptionType)?.value);
  };

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

  const confirmationModalDeleteClickHandler = async () => {
    setIsDeleteLoading(true);

    await WarehouseApi.delete(initialValues?.id as number);

    deleteModal.closeModal();
    toast.success('Successfully delete Warehouse!');
    setIsDeleteLoading(false);
    router.push('/master-data/warehouse');
  };

  useEffect(() => {
    formikSetValues(formikInitialValues);
  }, [formikSetValues, formikInitialValues]);

  // ===== Formik Error List =====
  const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);

  return (
    <>
      <section className='w-full max-w-xl'>
        <header className='flex flex-col gap-4'>
          <Button
            href='/master-data/warehouse'
            variant='link'
            className='w-fit p-0 text-primary'
          >
            <Icon icon='uil:arrow-left' width={24} height={24} />
            Kembali
          </Button>

          <h1 className='text-2xl font-bold text-center'>
            {type === 'add' && 'Tambah Warehouse'}
            {type === 'edit' && 'Edit Warehouse'}
            {type === 'detail' && 'Detail Warehouse'}
          </h1>
        </header>

        <form
          onSubmit={handleFormSubmit}
          onReset={formik.handleReset}
          className='w-full mt-8 flex flex-col gap-6'
        >
          <div className='flex flex-col gap-4'>
            <TextInput
              required
              label='Nama'
              name='name'
              placeholder='Masukkan nama warehouse'
              value={formik.values.name}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={formik.touched.name && Boolean(formik.errors.name)}
              errorMessage={formik.errors.name}
              readOnly={type === 'detail'}
            />

            <SelectInput
              required
              label='Tipe'
              value={
                formik.values.type
                  ? {
                      value: formik.values.type,
                      label: formik.values.type,
                    }
                  : undefined
              }
              onChange={typeChangeHandler}
              options={WAREHOUSE_TYPE_OPTIONS}
              isError={formik.touched.type && Boolean(formik.errors.type)}
              errorMessage={formik.errors.type as string}
              isDisabled={type === 'detail'}
              isClearable
            />

            <SelectInput
              required
              label='Area'
              value={formik.values.area ?? undefined}
              onChange={areaChangeHandler}
              options={areaOptions}
              onInputChange={setAreaSelectInputValue}
              onMenuScrollToBottom={loadMoreAreas}
              isLoading={isLoadingAreaOptions}
              isError={formik.touched.areaId && Boolean(formik.errors.areaId)}
              errorMessage={formik.errors.areaId as string}
              isDisabled={type === 'detail'}
              isClearable
            />

            {(formik.values.type === 'LOKASI' ||
              formik.values.type === 'KANDANG') && (
              <SelectInput
                required
                label='Lokasi'
                value={formik.values.location ?? undefined}
                onChange={locationChangeHandler}
                options={locationOptions}
                onInputChange={setLocationSelectInputValue}
                onMenuScrollToBottom={loadMoreLocations}
                isLoading={isLoadingLocationOptions}
                isError={
                  formik.touched.locationId && Boolean(formik.errors.locationId)
                }
                errorMessage={formik.errors.locationId as string}
                isDisabled={type === 'detail'}
                isClearable
              />
            )}

            {formik.values.type === 'KANDANG' && (
              <SelectInput
                required
                label='Kandang'
                value={formik.values.kandang ?? undefined}
                onChange={kandangChangeHandler}
                options={kandangOptions}
                onInputChange={setKandangSelectInputValue}
                onMenuScrollToBottom={loadMoreKandangs}
                isLoading={isLoadingKandangOptions}
                isError={
                  formik.touched.kandangId && Boolean(formik.errors.kandangId)
                }
                errorMessage={formik.errors.kandangId as string}
                isDisabled={type === 'detail'}
                isClearable
              />
            )}
          </div>

          <div className='flex flex-row justify-between gap-2 flex-wrap'>
            {type !== 'add' && (
              <div className='flex flex-row justify-start gap-2'>
                <RequirePermission permissions='lti.master.warehouses.delete'>
                  <Button
                    type='button'
                    color='error'
                    onClick={deleteWarehouseClickHandler}
                    className='px-4'
                  >
                    <Icon
                      icon='material-symbols:delete-outline-rounded'
                      width={24}
                      height={24}
                      className='justify-start text-sm'
                    />
                    Delete
                  </Button>
                </RequirePermission>

                {type !== 'edit' && (
                  <RequirePermission permissions='lti.master.warehouses.update'>
                    <Button
                      type='button'
                      color='warning'
                      href={`/master-data/warehouse/detail/edit/?warehouseId=${initialValues?.id}`}
                      className='px-4'
                    >
                      <Icon
                        icon='material-symbols:edit-outline'
                        width={24}
                        height={24}
                        className='justify-start text-sm'
                      />
                      Edit
                    </Button>
                  </RequirePermission>
                )}
              </div>
            )}

            <AlertErrorList formErrorList={formErrorList} onClose={close} />

            {type !== 'detail' && (
              <div
                className={cn('flex flex-row justify-end gap-2', {
                  'w-full': type === 'add',
                })}
              >
                <Button type='reset' color='warning' className='px-4'>
                  Reset
                </Button>

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

          {warehouseFormErrorMessage && (
            <div role='alert' className='alert alert-error'>
              <Icon
                icon='material-symbols:error-outline'
                width={24}
                height={24}
              />
              <span>{warehouseFormErrorMessage}</span>
            </div>
          )}
        </form>
      </section>

      {type !== 'add' && (
        <ConfirmationModal
          ref={deleteModal.ref}
          type='error'
          text={`Apakah anda yakin ingin menghapus data Warehouse ini (${initialValues?.name})?`}
          secondaryButton={{
            text: 'Tidak',
          }}
          primaryButton={{
            text: 'Ya',
            color: 'error',
            isLoading: isDeleteLoading,
            onClick: confirmationModalDeleteClickHandler,
          }}
        />
      )}
    </>
  );
};

export default WarehouseForm;
