'use client';

import { useModal } from '@/components/Modal';
import { CATEGORY_OPTIONS, TYPE_OPTIONS } from '@/config/constant';
import { isResponseError } from '@/lib/api-helper';
import { SupplierApi } from '@/services/api/master-data';
import {
  CreateSupplierPayload,
  Supplier,
} from '@/types/api/master-data/supplier';
import { useRouter } from 'next/navigation';
import { useCallback, useEffect, useMemo, useState } from 'react';
import toast from 'react-hot-toast';
import {
  SupplierFormSchema,
  SupplierFormValues,
  UpdateSupplierFormSchema,
} from '@/components/pages/master-data/supplier/form/SupplierForm.schema';
import { useFormik } from 'formik';
import SelectInput, { OptionType } from '@/components/input/SelectInput';
import { Icon } from '@iconify/react';
import Button from '@/components/Button';
import TextInput from '@/components/input/TextInput';
import TextArea from '@/components/input/TextArea';
import { cn } from '@/lib/helper';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
import RequirePermission from '@/components/helper/RequirePermission';
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
import AlertErrorList from '@/components/helper/form/FormErrors';

interface SupplierCustomProps {
  formType?: 'add' | 'edit' | 'detail';
  initialValues?: Supplier;
}

const SupplierForm = ({
  formType = 'add',
  initialValues,
}: SupplierCustomProps) => {
  // Setup Kebutuhan Form
  const router = useRouter();
  const deleteModal = useModal();

  // Setup State
  const [supplierFormErrorMessage, setSupplierFormErrorMessage] = useState('');
  const [isDeleteLoading, setIsDeleteLoading] = useState(false);
  const [hatcheryOptionsValues, setHatcheryOptionValues] = useState<
    OptionType[]
  >([]);

  // -- Options data mapping
  const typeOptions = TYPE_OPTIONS;
  const categoryOptions = CATEGORY_OPTIONS;

  // Handler Event
  const createSupplierHandler = useCallback(
    async (payload: CreateSupplierPayload) => {
      const createSupplierRes = await SupplierApi.create(payload);

      if (isResponseError(createSupplierRes)) {
        setSupplierFormErrorMessage(createSupplierRes.message);
        return;
      }

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

  const updateSupplierHandler = useCallback(
    async (supplierId: number, payload: CreateSupplierPayload) => {
      const updateSupplierRes = await SupplierApi.update(supplierId, payload);

      if (isResponseError(updateSupplierRes)) {
        setSupplierFormErrorMessage(updateSupplierRes.message);
        return;
      }

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

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

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

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

    deleteModal.closeModal();
    setIsDeleteLoading(false);
    router.push('/master-data/supplier');
  };

  // Utils Functions
  const normalizeOptionValue = (
    type?: string | { value: string; label: string },
    options?: OptionType[]
  ): { value: string; label: string } => {
    if (!type && !options) return { value: '', label: '' };
    if (!type && options && options.length > 0)
      return options[0] as { value: string; label: string };
    if (typeof type === 'string') return { value: type, label: type };
    return type ?? { value: '', label: '' };
  };

  // Memo
  const formikInitialValues = useMemo<SupplierFormValues>(() => {
    return {
      name: initialValues?.name ?? '',
      alias: initialValues?.alias ?? '',
      pic: initialValues?.pic ?? '',
      type: normalizeOptionValue(initialValues?.type, typeOptions),
      category: normalizeOptionValue(initialValues?.category, categoryOptions),
      hatchery: initialValues?.hatchery ?? '',
      phone: initialValues?.phone ?? '',
      email: initialValues?.email ?? '',
      address: initialValues?.address ?? '',
      npwp: initialValues?.npwp ?? '',
      bank_name: initialValues?.bank_name ?? '',
      account_number: initialValues?.account_number ?? '',
      due_date: initialValues?.due_date ?? 1,
    };
  }, [initialValues, typeOptions, categoryOptions]);

  // Formik
  const formik = useFormik<SupplierFormValues>({
    initialValues: formikInitialValues,
    enableReinitialize: true,
    validationSchema:
      formType === 'edit' ? UpdateSupplierFormSchema : SupplierFormSchema,
    onSubmit: async (values) => {
      // reset error message
      setSupplierFormErrorMessage('');

      // create payload
      const payload: CreateSupplierPayload = {
        name: values.name,
        alias: values.alias,
        pic: values.pic,
        type: values.type.value,
        category: values.category.value,
        hatchery: values.hatchery ?? '',
        phone: values.phone,
        email: values.email,
        address: values.address,
        npwp: values.npwp,
        bank_name: values.bank_name,
        account_number: values.account_number,
        due_date: parseInt(values.due_date.toString()),
      };

      // cek type form yang disubmit
      switch (formType) {
        case 'add':
          await createSupplierHandler(payload);
          break;
        case 'edit':
          await updateSupplierHandler(initialValues?.id as number, payload);
          break;
        default:
          break;
      }
    },
  });

  const { setFieldValue } = formik;

  // Initialize Formik
  useEffect(() => {
    if (formType !== 'add' && initialValues?.hatchery) {
      const hatcheryArrays = initialValues.hatchery.split(',');
      const hatcheryCreatedOptions = hatcheryArrays.map((item) => ({
        value: item,
        label: item,
      }));
      setHatcheryOptionValues(hatcheryCreatedOptions);
    }
  }, [formType, initialValues?.hatchery]);

  useEffect(() => {
    const commaSeparatedValues = hatcheryOptionsValues
      .map((item) => item.value)
      .join(',');
    setFieldValue('hatchery', commaSeparatedValues);
  }, [hatcheryOptionsValues, setFieldValue]);

  // Option Handler
  const typeChangeHandler = (val: OptionType | OptionType[] | null) => {
    formik.setFieldTouched('type', true);
    formik.setFieldValue('type', val);
  };
  const categoryChangeHandler = (val: OptionType | OptionType[] | null) => {
    formik.setFieldTouched('category', true);
    formik.setFieldValue('category', val);
  };

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

  // Render
  return (
    <>
      <section className='w-full max-w-xl'>
        <header className='flex flex-col gap-4'>
          <Button
            href='/master-data/supplier'
            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'>
            {formType === 'add' && 'Tambah Supplier'}
            {formType === 'edit' && 'Ubah Supplier'}
            {formType === 'detail' && 'Detail Supplier'}
          </h1>
        </header>

        <form
          onSubmit={handleFormSubmit}
          onReset={formik.handleReset}
          className='w-full mt-8 flex flex-col gap-6'
        >
          {/* Fields Form */}
          <div className='flex flex-col gap-4'>
            <TextInput
              required
              label='Nama Supplier'
              name='name'
              placeholder='Masukkan nama supplier'
              value={formik.values.name}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={formik.touched.name && Boolean(formik.errors.name)}
              errorMessage={formik.errors.name}
              readOnly={formType === 'detail'}
            />
            <TextInput
              required
              label='Nama Alias'
              name='alias'
              placeholder='Masukkan alias supplier'
              value={formik.values.alias}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={formik.touched.alias && Boolean(formik.errors.alias)}
              errorMessage={formik.errors.alias}
              readOnly={formType === 'detail'}
            />
            <TextInput
              required
              label='Nama PIC'
              name='pic'
              placeholder='Masukkan PIC supplier'
              value={formik.values.pic}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={formik.touched.pic && Boolean(formik.errors.pic)}
              errorMessage={formik.errors.pic}
              readOnly={formType === 'detail'}
            />
            <SelectInput
              required
              placeholder='Pilih Tipe'
              label='Tipe'
              value={
                typeOptions.find(
                  (item) => item.value === formik.values.type?.value
                ) ?? undefined
              }
              onChange={typeChangeHandler}
              options={typeOptions}
              isError={formik.touched.type && Boolean(formik.errors.type)}
              errorMessage={formik.errors.type as string}
              isDisabled={formType === 'detail'}
              isClearable
              isSearchable={true}
            />
            <SelectInput
              required
              placeholder='Pilih Kategori'
              label='Kategori'
              value={
                categoryOptions.find(
                  (item) => item.value === formik.values.category?.value
                ) ?? undefined
              }
              onChange={categoryChangeHandler}
              options={categoryOptions}
              isError={
                formik.touched.category && Boolean(formik.errors.category)
              }
              errorMessage={formik.errors.category as string}
              isDisabled={formType === 'detail'}
              isClearable
              isSearchable={true}
            />
            <SelectInput
              isMulti
              createables
              placeholder='Pilih Hatchery'
              label='Hatchery'
              value={hatcheryOptionsValues}
              onChange={(val) => {
                setHatcheryOptionValues(val as OptionType[]);
              }}
              isError={
                formik.touched.hatchery && Boolean(formik.errors.hatchery)
              }
              errorMessage={formik.errors.hatchery as string}
              isDisabled={formType === 'detail'}
              isClearable
              isSearchable={true}
              options={[]}
            />

            <TextInput
              required
              label='Nomor Telepon'
              name='phone'
              placeholder='Masukkan nomor telepon supplier'
              value={formik.values.phone}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={formik.touched.phone && Boolean(formik.errors.phone)}
              errorMessage={formik.errors.phone}
              readOnly={formType === 'detail'}
            />
            <TextInput
              required
              label='Email'
              name='email'
              placeholder='Masukkan email supplier'
              value={formik.values.email}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={formik.touched.email && Boolean(formik.errors.email)}
              errorMessage={formik.errors.email}
              readOnly={formType === 'detail'}
            />
            <TextArea
              required
              label='Alamat'
              name='address'
              placeholder='Masukkan alamat supplier'
              value={formik.values.address}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={formik.touched.address && Boolean(formik.errors.address)}
              errorMessage={formik.errors.address}
              readOnly={formType === 'detail'}
            />
            <TextInput
              required
              label='NPWP'
              name='npwp'
              placeholder='Masukkan NPWP supplier'
              value={formik.values.npwp}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={formik.touched.npwp && Boolean(formik.errors.npwp)}
              errorMessage={formik.errors.npwp}
              readOnly={formType === 'detail'}
            />
            <TextInput
              required
              label='Nama Bank'
              name='bank_name'
              placeholder='Masukkan nama bank supplier'
              value={formik.values.bank_name}
              onChange={(e) =>
                formik.setFieldValue('bank_name', e.target.value.toUpperCase())
              }
              onBlur={formik.handleBlur}
              isError={
                formik.touched.bank_name && Boolean(formik.errors.bank_name)
              }
              errorMessage={formik.errors.bank_name}
              readOnly={formType === 'detail'}
            />
            <TextInput
              required
              label='Nomor Rekening'
              name='account_number'
              placeholder='Masukkan nomor rekening supplier'
              value={formik.values.account_number}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={
                formik.touched.account_number &&
                Boolean(formik.errors.account_number)
              }
              errorMessage={formik.errors.account_number}
              readOnly={formType === 'detail'}
            />
            <TextInput
              required
              type='number'
              className={{
                wrapper: 'w-fit',
              }}
              label='Jatuh Tempo'
              name='due_date'
              placeholder='Masukkan tanggal pembayaran supplier'
              value={formik.values.due_date}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={
                formik.touched.due_date && Boolean(formik.errors.due_date)
              }
              errorMessage={formik.errors.due_date}
              readOnly={formType === 'detail'}
              endAdornment={<div>Hari</div>}
            />
          </div>

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

                {formType !== 'edit' && (
                  <RequirePermission permissions='lti.master.suppliers.update'>
                    <Button
                      type='button'
                      color='warning'
                      href={`/master-data/supplier/detail/edit/?supplierId=${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} />

            {formType !== 'detail' && (
              <div
                className={cn('flex flex-row justify-end gap-2', {
                  'w-full': formType === '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>

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

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

export default SupplierForm;
