'use client';

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

import Link from 'next/link';
import { Icon } from '@iconify/react';
import Button from '@/components/Button';
import SelectInput, {
  OptionType,
  useSelect,
} from '@/components/input/SelectInput';
import DateInput from '@/components/input/DateInput';
import DropFileInput from '@/components/input/DropFileInput';
import ExpenseKandangsTable from '@/components/pages/expense/form/ExpenseKandangsTable';
import ExpenseRealizationKandangDetailExpense from '@/components/pages/expense/form/ExpenseRealizationKandangDetailExpense';
import RequirePermission from '@/components/helper/RequirePermission';
import AlertErrorList from '@/components/helper/form/FormErrors';

import {
  CreateExpenseRealizationPayload,
  Expense,
  UpdateExpenseRealizationPayload,
} from '@/types/api/expense';
import {
  ExpenseRealizationFormSchema,
  ExpenseRealizationFormValues,
  getExpenseRealizationFormInitialValues,
  UpdateExpenseRealizationFormSchema,
} from '@/components/pages/expense/form/ExpenseRealizationForm.schema';
import { ExpenseApi } from '@/services/api/expense';
import { isResponseError } from '@/lib/api-helper';
import { LocationApi, SupplierApi } from '@/services/api/master-data';
import { Supplier } from '@/types/api/master-data/supplier';
import { ACCEPTED_FILE_TYPE } from '@/config/constant';
import { getExpenseListReturnTo } from '@/lib/expense-list-navigation';
import { cn } from '@/lib/helper';
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';

interface ExpenseRealizationFormProps {
  type?: 'add' | 'edit' | 'detail';
  initialValues?: Expense;
}

const ExpenseRealizationForm = ({
  type = 'add',
  initialValues,
}: ExpenseRealizationFormProps) => {
  const router = useRouter();
  const searchParams = useSearchParams();
  const returnTo = getExpenseListReturnTo(searchParams);

  const [expenseFormErrorMessage, setExpenseFormErrorMessage] = useState('');

  const createExpenseHandler = useCallback(
    async (payload: CreateExpenseRealizationPayload) => {
      const createExpenseRes = await ExpenseApi.createRealization(
        initialValues?.id as number,
        ExpenseApi.convertExpenseRealizationPayloadToFormData(payload)
      );

      if (isResponseError(createExpenseRes)) {
        setExpenseFormErrorMessage(createExpenseRes.message);
        return;
      }

      toast.success(createExpenseRes?.message as string);
      router.push(returnTo);
    },
    [initialValues?.id, returnTo, router]
  );

  const updateExpenseHandler = useCallback(
    async (expenseId: number, payload: UpdateExpenseRealizationPayload) => {
      const updateExpenseRes = await ExpenseApi.updateRealization(
        expenseId,
        ExpenseApi.convertExpenseRealizationPayloadToFormData(payload)
      );

      if (updateExpenseRes?.status === 'error') {
        setExpenseFormErrorMessage(updateExpenseRes.message);
        return;
      }

      toast.success(updateExpenseRes?.message as string);
      router.refresh();
      router.push(returnTo);
    },
    [returnTo, router]
  );

  const formik = useFormik<ExpenseRealizationFormValues>({
    initialValues: getExpenseRealizationFormInitialValues(initialValues),
    enableReinitialize: true,
    validationSchema:
      type === 'edit'
        ? UpdateExpenseRealizationFormSchema
        : ExpenseRealizationFormSchema,
    onSubmit: async (values) => {
      setExpenseFormErrorMessage('');

      const realizations: CreateExpenseRealizationPayload['realizations'] = [];

      values.realizations.forEach((realization) => {
        realization.cost_items.forEach((costItem) => {
          const realizationItem: {
            expense_nonstock_id: number;
            qty: number;
            price: number;
            notes: string;
            kandang_id?: number;
          } = {
            expense_nonstock_id: costItem.nonstock?.value as number,
            qty: parseFloat(String(costItem.quantity)) as number,
            price: parseFloat(String(costItem.price)) as number,
            notes: costItem.notes ?? '',
          };

          if (realization.kandang_id && realization.kandang_id > 0) {
            realizationItem.kandang_id = realization.kandang_id;
          }

          realizations.push(realizationItem);
        });
      });

      const expensePayload: CreateExpenseRealizationPayload = {
        realization_date: values.realization_date as string,
        documents: values.documents as File[],
        realizations,
      };

      switch (type) {
        case 'add':
          await createExpenseHandler(expensePayload);
          break;

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

  const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik);

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

  const {
    setInputValue: setVendorInputValue,
    options: vendorOptions,
    isLoadingOptions: isLoadingVendorOptions,
  } = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name');

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

    formik.setFieldValue('kandangs', []);

    // Auto-create realization item for location (without kandang)
    formik.setFieldValue('realizations', [
      {
        cost_items: [
          {
            nonstock: undefined,
            quantity: undefined,
            price: undefined,
            notes: '',
          },
        ],
      },
    ]);
  };

  const kandangsChangeHandler = (
    kandangs: { id?: number; name?: string }[]
  ) => {
    formik.setFieldTouched('kandangs', true);
    formik.setFieldValue('kandangs', kandangs);

    // If no kandangs selected, create realization item for location
    if (kandangs.length === 0) {
      formik.setFieldValue('realizations', [
        {
          cost_items: [
            {
              nonstock: undefined,
              quantity: undefined,
              price: undefined,
              notes: '',
            },
          ],
        },
      ]);
      return;
    }

    // Start with empty array when kandangs are selected
    const newRealizations: typeof formik.values.realizations = [];

    // add new realizations for each kandang
    kandangs.forEach((kandangItem) => {
      if (isNaN(Number(kandangItem.id))) return;

      const existingRealization = formik.values.realizations?.find(
        (realizationItem) => realizationItem.kandang_id === kandangItem.id
      );

      newRealizations.push({
        kandang_id: kandangItem.id,
        cost_items: existingRealization?.cost_items || [
          {
            nonstock: undefined,
            quantity: undefined,
            price: undefined,
            notes: '',
          },
        ],
      });
    });

    formik.setFieldValue('realizations', newRealizations);
  };

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

  const realizationDocumentsChangeHandler = (val: File[]) => {
    formik.setFieldTouched('documents', true);

    const invalidFiles = val.filter((file) => file.size > 5 * 1024 * 1024);
    if (invalidFiles.length > 0) {
      toast.error('Ukuran dokumen maksimal 5 MB!');
      return;
    }

    formik.setFieldValue('documents', val);
  };

  const realizationDocumentsDeleteHandler = (deletedFileIdx: number) => {
    const newRequestDocuments = formik.values.documents;

    newRequestDocuments?.splice(deletedFileIdx, 1);

    formik.setFieldValue('documents', newRequestDocuments);
  };

  return (
    <section className='w-full'>
      <header className='flex flex-col gap-4'>
        <Button
          href={returnTo}
          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'>
          Realisasi Biaya Operasional
        </h1>
      </header>

      <form
        onSubmit={handleFormSubmit}
        onReset={formik.handleReset}
        className='w-full mt-8 flex flex-col gap-6'
      >
        <div className='grid grid-cols-12 gap-4'>
          <SelectInput
            label='Lokasi'
            required
            placeholder='Pilih Lokasi'
            value={formik.values.location}
            onChange={locationChangeHandler}
            options={locationOptions}
            isLoading={isLoadingLocationOptions}
            onInputChange={setLocationInputValue}
            isDisabled
            className={{ wrapper: 'col-span-12 sm:col-span-6' }}
          />

          <DateInput
            name='realization_date'
            label='Tanggal Realisasi'
            required
            value={formik.values.realization_date}
            onChange={formik.handleChange}
            className={{
              wrapper: 'col-span-12 sm:col-span-6',
            }}
          />

          <ExpenseKandangsTable
            type='detail'
            formType='realization'
            locationId={formik.values.location?.value}
            selectedKandangs={formik.values.kandangs ?? []}
            onChange={kandangsChangeHandler}
            className={{
              wrapper: 'w-full col-span-12',
            }}
          />

          <SelectInput
            label='Vendor'
            required
            placeholder='Pilih Vendor'
            value={formik.values.supplier}
            onChange={vendorChangeHandler}
            options={vendorOptions}
            isLoading={isLoadingVendorOptions}
            onInputChange={setVendorInputValue}
            isDisabled
            className={{ wrapper: 'col-span-12' }}
          />

          <RequirePermission permissions='lti.expense.document.realization'>
            <DropFileInput
              label='Dokumen Realisasi'
              name='documents'
              values={formik.values.documents}
              onChange={realizationDocumentsChangeHandler}
              onDelete={realizationDocumentsDeleteHandler}
              accept={{
                ...ACCEPTED_FILE_TYPE.PDF,
                ...ACCEPTED_FILE_TYPE.IMAGE,
              }}
              className={{
                wrapper: 'col-span-12',
                inputWrapper: 'h-12 flex items-center',
              }}
            />
          </RequirePermission>

          {formik.values.existing_documents &&
            formik.values.existing_documents.length > 0 && (
              <div className='w-full col-span-12'>
                <ul className='pl-4 list-disc'>
                  {formik.values.existing_documents.map(
                    (existingDocument, existingDocumentIdx) => (
                      <li key={existingDocumentIdx}>
                        <Link
                          href={existingDocument.url}
                          target='_blank'
                          rel='noopener noreferrer'
                          className='text-blue-500 underline'
                        >
                          {existingDocument.name}{' '}
                          <Icon
                            icon='cuida:open-in-new-tab-outline'
                            width={12}
                            height={12}
                            className='inline'
                          />
                        </Link>
                      </li>
                    )
                  )}
                </ul>
              </div>
            )}

          <ExpenseRealizationKandangDetailExpense
            type={type}
            formik={formik}
            supplierId={formik.values.supplier?.value as number}
            location={formik.values.location}
            className={{
              wrapper: 'col-span-12',
            }}
          />
        </div>

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

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

        <div className='flex flex-row justify-between gap-2 flex-wrap'>
          {type !== 'add' && (
            <div className='flex flex-row justify-start gap-2'>
              {type !== 'edit' && (
                <RequirePermission permissions='lti.expense.update'>
                  <Button
                    type='button'
                    color='warning'
                    href={`/expense/detail/edit/?expenseId=${initialValues?.id}`}
                    className='px-4'
                  >
                    <Icon
                      icon='material-symbols:edit-outline'
                      width={24}
                      height={24}
                      className='justify-start text-sm'
                    />
                    Edit
                  </Button>
                </RequirePermission>
              )}
            </div>
          )}

          {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>
      </form>
    </section>
  );
};

export default ExpenseRealizationForm;
