'use client';

import Button from '@/components/Button';
import AlertErrorList from '@/components/helper/form/FormErrors';
import { FormHeader } from '@/components/helper/form/FormHeader';
import DateInput from '@/components/input/DateInput';
import NumberInput from '@/components/input/NumberInput';
import SelectInput, { useSelect } from '@/components/input/SelectInput';
import TextArea from '@/components/input/TextArea';
import {
  InjectionFormSchema,
  InjectionFormValues,
} from '@/components/pages/finance/add/injection/FormFinanceInjection.schema';
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { formatDate } from '@/lib/helper';
import { FinanceApi } from '@/services/api/finance';
import { BankApi } from '@/services/api/master-data';
import {
  CreateInjection,
  Finance,
  UpdateInjection,
} from '@/types/api/finance/finance';
import { Bank } from '@/types/api/master-data/bank';
import { useFormik } from 'formik';
import { useRouter } from 'next/navigation';
import { useCallback, useMemo, useState } from 'react';
import toast from 'react-hot-toast';
import Alert from '@/components/Alert';
import { Icon } from '@iconify/react';
import { FINANCE_INJECTION_TYPE_OPTIONS } from '@/config/constant';

interface FormFinanceInjectionProps {
  type?: 'add' | 'edit';
  initialValues?: Finance;
}

const FormFinanceInjection = ({
  type = 'add',
  initialValues,
}: FormFinanceInjectionProps) => {
  const router = useRouter();
  const [serverErrorMessage, setServerErrorMessage] = useState('');

  // ===== Formik =====
  const formikInitialValues = useMemo((): InjectionFormValues => {
    return {
      bank_id_option: initialValues?.bank
        ? {
            label: initialValues.bank?.name,
            value: initialValues.bank?.id,
          }
        : null,
      adjustment_date: initialValues?.payment_date || '',
      injection_type: initialValues?.nominal
        ? initialValues.nominal < 0
          ? FINANCE_INJECTION_TYPE_OPTIONS[1]
          : FINANCE_INJECTION_TYPE_OPTIONS[0]
        : FINANCE_INJECTION_TYPE_OPTIONS[0],
      nominal: initialValues?.nominal?.toString() || '',
      note: initialValues?.notes || '',
    };
  }, [initialValues]);

  const formik = useFormik<InjectionFormValues>({
    initialValues: formikInitialValues,
    validationSchema: InjectionFormSchema,
    validateOnChange: true,
    validateOnBlur: true,
    onSubmit: async (values) => {
      const payload = transformFormValuesToPayload(values);

      switch (type) {
        case 'add':
          await createInjection(payload);
          break;

        case 'edit':
          if (initialValues?.id) {
            await updateInjection(initialValues.id, payload);
          }
          break;
      }
    },
  });

  // ===== Options =====
  const {
    options: bankOptions,
    rawData: bankRawData,
    isLoadingOptions: isLoadingBankOptions,
    setInputValue: setBankInputValue,
    loadMore: loadMoreBankOptions,
  } = useSelect<Bank>(BankApi.basePath, 'id', 'name');

  // ===== Helper Functions =====
  const transformFormValuesToPayload = (
    values: InjectionFormValues
  ): CreateInjection => {
    return {
      bank_id: Number(values.bank_id_option?.value) || 0,
      adjustment_date: formatDate(values.adjustment_date, 'YYYY-MM-DD'),
      nominal:
        values.injection_type?.value == 'POSITIVE'
          ? Math.abs(Number(values.nominal))
          : -Math.abs(Number(values.nominal)),
      notes: values.note,
    };
  };

  // ===== Handler =====
  const createInjection = useCallback(
    async (payload: CreateInjection) => {
      const response = await FinanceApi.createInjections(payload);

      if (isResponseError(response)) {
        toast.error(response.message);
        setServerErrorMessage(response.message);
        return;
      }

      toast.success('Injeksi dana berhasil ditambahkan');
      router.refresh();
      router.push('/finance');
    },
    [router]
  );

  const updateInjection = useCallback(
    async (financeId: number, payload: UpdateInjection) => {
      const response = await FinanceApi.updateInjections(financeId, payload);

      if (isResponseError(response)) {
        toast.error(response.message);
        setServerErrorMessage(response.message);
        return;
      }

      toast.success('Injeksi dana berhasil diperbarui');
      router.refresh();
      router.push('/finance');
    },
    [router]
  );

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

  return (
    <>
      <section className='w-full max-w-xl mx-auto'>
        <div className='flex flex-col gap-6 p-6'>
          <FormHeader
            title={`${type === 'add' ? 'Tambah' : 'Ubah'} Injeksi Dana`}
            backUrl='/finance'
          />
          <form className='flex flex-col gap-4' onSubmit={handleFormSubmit}>
            <SelectInput
              label='Bank'
              placeholder='Pilih bank'
              options={
                isResponseSuccess(bankRawData)
                  ? bankOptions.map((option) => ({
                      label:
                        bankRawData.data?.find(
                          (item) => item.id === option.value
                        )?.alias +
                        ' - ' +
                        bankRawData.data?.find(
                          (item) => item.id === option.value
                        )?.account_number +
                        ' - ' +
                        bankRawData.data?.find(
                          (item) => item.id === option.value
                        )?.owner,
                      value: option.value,
                    }))
                  : []
              }
              value={formik.values.bank_id_option}
              onInputChange={setBankInputValue}
              onMenuScrollToBottom={loadMoreBankOptions}
              onChange={(value) => {
                formik.setFieldValue('bank_id_option', value);
              }}
              isLoading={isLoadingBankOptions}
              isError={Boolean(
                formik.touched.bank_id_option && formik.errors.bank_id_option
              )}
              errorMessage={
                formik.touched.bank_id_option && formik.errors.bank_id_option
                  ? formik.errors.bank_id_option
                  : ''
              }
              required
              isClearable
            />
            <DateInput
              label='Tanggal Penyesuaian'
              placeholder='Pilih tanggal penyesuaian'
              name='adjustment_date'
              value={formik.values.adjustment_date}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={Boolean(
                formik.touched.adjustment_date && formik.errors.adjustment_date
              )}
              errorMessage={
                formik.touched.adjustment_date && formik.errors.adjustment_date
                  ? formik.errors.adjustment_date
                  : ''
              }
              required
            />
            <SelectInput
              label='Tipe Injeksi'
              placeholder='Pilih tipe injeksi'
              options={FINANCE_INJECTION_TYPE_OPTIONS}
              value={formik.values.injection_type}
              onChange={(value) => {
                formik.setFieldValue('injection_type', value);
              }}
              isError={Boolean(
                formik.touched.injection_type && formik.errors.injection_type
              )}
              errorMessage={
                formik.touched.injection_type && formik.errors.injection_type
                  ? formik.errors.injection_type
                  : ''
              }
              required
            />
            <NumberInput
              label='Nominal'
              placeholder='Masukkan nominal'
              name='nominal'
              value={formik.values.nominal}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={Boolean(formik.touched.nominal && formik.errors.nominal)}
              errorMessage={
                formik.touched.nominal && formik.errors.nominal
                  ? formik.errors.nominal
                  : ''
              }
              allowNegative={false}
              required
              startAdornment={
                formik.values.injection_type?.value === 'POSITIVE' ? (
                  <Icon icon='mdi:plus' />
                ) : formik.values.injection_type?.value === 'NEGATIVE' ? (
                  <Icon icon='mdi:minus' />
                ) : (
                  ''
                )
              }
            />
            <TextArea
              label='Catatan'
              placeholder='Masukkan catatan'
              name='note'
              value={formik.values.note}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              isError={Boolean(formik.touched.note && formik.errors.note)}
              errorMessage={
                formik.touched.note && formik.errors.note
                  ? formik.errors.note
                  : ''
              }
              required
            />
            <AlertErrorList formErrorList={formErrorList} onClose={close} />
            {serverErrorMessage && (
              <Alert color='error'>
                <Icon icon='mdi:alert' />
                {serverErrorMessage}
                <Button color='error' onClick={() => setServerErrorMessage('')}>
                  <Icon icon='mdi:close' />
                </Button>
              </Alert>
            )}
            <div className='flex justify-center gap-4'>
              <Button
                type='reset'
                color='warning'
                className='w-min-24'
                onClick={() => formik.resetForm()}
                disabled={formik.isSubmitting}
              >
                Reset
              </Button>
              <Button
                type='submit'
                className='w-min-24'
                disabled={formik.isSubmitting}
              >
                Submit
              </Button>
            </div>
          </form>
        </div>
      </section>
    </>
  );
};

export default FormFinanceInjection;
