'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useFormik } from 'formik';
import { useRouter } from 'next/navigation';
import { Icon } from '@iconify/react';
import { toast } from 'react-hot-toast';
import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
import { useUiStore } from '@/stores/ui/ui.store';
import { useUniformityStore } from '@/stores/production/uniformity/uniformity.store';
import Button from '@/components/Button';
import DateInput from '@/components/input/DateInput';

import SelectInput, {
  OptionType,
  useSelect,
} from '@/components/input/SelectInput';

import RequirePermission from '@/components/helper/RequirePermission';

import {
  UniformityFormSchema,
  UniformityFormValues,
  getUniformityFormInitialValues,
} from '@/components/pages/production/uniformity/form/UniformityForm.schema';
import { LocationApi } from '@/services/api/master-data';
import {
  ProjectFlockApi,
  ProjectFlockKandangApi,
} from '@/services/api/production';
import { UniformityApi } from '@/services/api/uniformity';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import {
  Uniformity,
  VerifyUniformityPayload,
} from '@/types/api/production/uniformity';
import { type BaseApiResponse } from '@/types/api/api-general';
import {
  ProjectFlockKandangLookup,
  ProjectFlock,
} from '@/types/api/production/project-flock';
import { Kandang } from '@/types/api/master-data/kandang';
import UniformityPreviewForm from '@/components/pages/production/uniformity/form/UniformityPreviewForm';
import UniformityResultForm from '@/components/pages/production/uniformity/form/UniformityResultForm';
import { generateUniformityTemplate } from '@/components/pages/production/uniformity/export/UniformityTemplate';
import useSWR from 'swr';
import { cn, formatNumber } from '@/lib/helper';
import { getUniqueFormikErrors } from '@/lib/formik-helper';
import Tooltip from '@/components/Tooltip';
import AlertErrorList from '@/components/helper/form/FormErrors';

interface UniformityFormProps {
  formType?: 'add' | 'edit';
  initialValues?: Uniformity;
}

const UniformityForm = ({
  formType = 'add',
  initialValues,
}: UniformityFormProps) => {
  const router = useRouter();

  const subscribeValidate = useUiStore((s) => s.subscribeValidate);
  const setIsValid = useUiStore((s) => s.setIsValid);
  const expandedDrawerOpen = useUiStore((s) => s.expandedDrawerOpen);
  const setExpandedDrawerOpen = useUiStore((s) => s.setExpandedDrawerOpen);
  const setExpandedDrawerContent = useUiStore(
    (s) => s.setExpandedDrawerContent
  );
  const isNextStep = useUiStore((s) => s.isNextStep);
  const setIsNextStep = useUiStore((s) => s.setIsNextStep);

  const setVerifyUniformityResult = useUniformityStore(
    (s) => s.setVerifyUniformityResult
  );
  const setUniformityFormData = useUniformityStore(
    (s) => s.setUniformityFormData
  );
  const uniformityStep = useUniformityStore((s) => s.uniformityStep);
  const setUniformityStep = useUniformityStore((s) => s.setUniformityStep);

  const [uniformityFormErrorMessage, setUniformityFormErrorMessage] =
    useState('');
  const [formErrorList, setFormErrorList] = useState<string[]>([]);

  const fileInputRef = useRef<HTMLInputElement>(null);

  // ===== SELECT INPUT DATA =====
  const [, setSelectedLocation] = useState<OptionType | null>(null);

  const [selectedProjectFlockLocationId, setSelectedProjectFlockLocationId] =
    useState<string>('');

  const [selectedProjectFlock, setSelectedProjectFlock] =
    useState<OptionType | null>(null);

  const [selectedKandang, setSelectedKandang] = useState<OptionType | null>(
    null
  );

  const {
    setInputValue: setLocationSelectInputValue,
    options: locationOptions,
    isLoadingOptions: isLoadingLocations,
    loadMore: loadMoreLocations,
  } = useSelect(LocationApi.basePath, 'id', 'name', 'search');

  const {
    setInputValue: setProjectFlockSearchValue,
    options: projectFlockOptions,
    rawData: projectFlocksRawData,
    isLoadingOptions: isLoadingProjectFlocks,
    loadMore: loadMoreProjectFlocks,
  } = useSelect(ProjectFlockApi.basePath, 'id', 'flock_name', 'search', {
    location_id: selectedProjectFlockLocationId,
  });

  // ===== APPROVED PROJECT FLOCK KANDANGS =====
  const approvedProjectFlockKandangsUrl = useMemo(() => {
    const params = new URLSearchParams({
      step_name: 'Disetujui',
      page: '1',
      limit: '100',
    });
    return `${ProjectFlockKandangApi.basePath}?${params.toString()}`;
  }, []);

  const { data: approvedProjectFlockKandangsData } = useSWR(
    approvedProjectFlockKandangsUrl,
    ProjectFlockKandangApi.getAllFetcher
  );

  const approvedProjectFlockKandangs = useMemo(() => {
    if (!isResponseSuccess(approvedProjectFlockKandangsData)) return [];
    return approvedProjectFlockKandangsData.data;
  }, [approvedProjectFlockKandangsData]);

  // ===== KANDANG OPTIONS (FILTERED BY SELECTED PROJECT FLOCK) =====
  const kandangOptions = useMemo(() => {
    let options: OptionType[] = [];

    if (selectedProjectFlock && isResponseSuccess(projectFlocksRawData)) {
      const data = projectFlocksRawData.data as unknown as ProjectFlock[];
      const selectedProjectFlockData = data.find(
        (pf) => pf.id === selectedProjectFlock.value
      );

      if (selectedProjectFlockData?.kandangs) {
        const approvedKandangIds = approvedProjectFlockKandangs
          .filter((pfk) => pfk.project_flock_id === selectedProjectFlock.value)
          .map((pfk) => pfk.kandang_id);

        const kandangOpts = selectedProjectFlockData.kandangs
          .filter((kandang: Kandang) => {
            if (formType === 'add') {
              return (
                approvedKandangIds.includes(kandang.id) &&
                kandang.status === 'ACTIVE'
              );
            }
            return kandang.status === 'ACTIVE';
          })
          .map((kandang: Kandang) => ({
            value: kandang.id,
            label: kandang.name || '',
          }));
        options = options.concat(kandangOpts);
      }
    }

    return options;
  }, [
    selectedProjectFlock,
    projectFlocksRawData,
    approvedProjectFlockKandangs,
    formType,
  ]);

  // ===== PROJECT FLOCK KANDANG LOOKUP =====
  const projectFlockKandangLookupUrl = useMemo(() => {
    if (!selectedProjectFlock || !selectedKandang) return null;
    const params = new URLSearchParams({
      project_flock_id: selectedProjectFlock.value.toString(),
      kandang_id: selectedKandang.value.toString(),
      withpopulation: Boolean(true).toString(),
    });
    return `${ProjectFlockApi.basePath}/kandangs/lookup?${params.toString()}`;
  }, [selectedProjectFlock, selectedKandang]);

  const { data: projectFlockKandangLookupData } = useSWR(
    projectFlockKandangLookupUrl,
    projectFlockKandangLookupUrl
      ? () =>
          ProjectFlockApi.getAllFetcher(
            projectFlockKandangLookupUrl
          ) as Promise<BaseApiResponse<ProjectFlockKandangLookup>>
      : null
  );

  const projectFlockKandangLookup =
    projectFlockKandangLookupData?.status === 'success'
      ? projectFlockKandangLookupData.data
      : undefined;

  // ===== FORM CONFIGURATION =====
  const formikInitialValues = useMemo<UniformityFormValues>(
    () => getUniformityFormInitialValues(initialValues),
    [initialValues]
  );

  const formik = useFormik<UniformityFormValues>({
    initialValues: formikInitialValues,
    validationSchema: UniformityFormSchema,
    validateOnChange: true,
    validateOnBlur: true,
    validateOnMount: false,
    enableReinitialize: true,
    onSubmit: async (values) => {
      const projectFlockKandangId = projectFlockKandangLookup?.id;

      if (!projectFlockKandangId) {
        setUniformityFormErrorMessage(
          'Project Flock Kandang tidak ditemukan. Silakan pilih Project Flock dan Kandang yang valid.'
        );
        return;
      }

      setUniformityFormData({
        date: values.date,
        project_flock_kandang_id: projectFlockKandangId,
        document: values.document as File,
        document_name: (values.document as File).name,
      });

      const payload: VerifyUniformityPayload = {
        document: values.document as File,
      };

      const res = await UniformityApi.verifyUniformity(payload);

      if (isResponseError(res)) {
        setUniformityFormErrorMessage(res.message);
        return;
      }

      if (isResponseSuccess(res) && res.data) {
        setVerifyUniformityResult(res.data);
      }

      toast.success(res?.message as string);

      if (formType === 'add') {
        setIsNextStep(true);
        setExpandedDrawerOpen(true);
        setUniformityStep('preview');
      } else {
        router.push('/production/uniformity');
      }
    },
  });

  const { setFieldValue, setFieldTouched } = formik;

  const handleValidateForm = async () => {
    const errors = await formik.validateForm();

    if (Object.keys(errors).length > 0) {
      const errorMessages = getUniqueFormikErrors(errors);
      setFormErrorList(errorMessages);
      return;
    }
  };

  const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    handleValidateForm();
    formik.handleSubmit(e);
  };

  // ===== FORM HANDLERS =====
  const handleLocationChange = useCallback(
    (val: OptionType | OptionType[] | null) => {
      const location = val as OptionType | null;
      const locationId = Number(location?.value);

      setFieldTouched('location', true);
      setFieldValue('location', location);
      setFieldTouched('location_id', true);
      setFieldValue('location_id', locationId);

      setSelectedLocation(location);
      setSelectedProjectFlock(null);
      setSelectedProjectFlockLocationId(
        location ? location.value.toString() : ''
      );
    },
    [setFieldTouched, setFieldValue]
  );

  const handleProjectFlockChange = useCallback(
    (val: OptionType | OptionType[] | null) => {
      const projectFlock = val as OptionType | null;
      const projectFlockId = Number(projectFlock?.value);

      setFieldTouched('project_flock', true);
      setFieldValue('project_flock', projectFlock);
      setFieldTouched('project_flock_id', true);
      setFieldValue('project_flock_id', projectFlockId);

      setSelectedProjectFlock(projectFlock);
    },
    [setFieldTouched, setFieldValue]
  );

  const handleKandangChange = useCallback(
    (val: OptionType | OptionType[] | null) => {
      const kandang = val as OptionType | null;
      const kandangId = Number(kandang?.value);

      setFieldTouched('kandang', true);
      setFieldValue('kandang', kandang);
      setFieldTouched('kandang_id', true);
      setFieldValue('kandang_id', kandangId);

      setSelectedKandang(kandang);
    },
    [setFieldTouched, setFieldValue]
  );

  const handleFileChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const document = e.target.files?.[0];

      setFieldTouched('document', true);

      if (!document) {
        setFieldValue('document', undefined);
        return;
      }

      if (document.size > 5 * 1024 * 1024) {
        toast.error(`Ukuran file ${document.name} maksimal 5 MB!`);
        return;
      }

      const allowedTypes = [
        'application/vnd.ms-excel',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'text/csv',
      ];

      if (!allowedTypes.includes(document.type)) {
        toast.error(`Format file ${document.name} harus Excel atau CSV!`);
        return;
      }

      setFieldValue('document', document);
    },
    [setFieldTouched, setFieldValue]
  );

  const handleDateChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setFieldValue('date', e.target.value);
    },
    [setFieldValue]
  );

  const handleRemoveFile = useCallback(() => {
    setFieldValue('document', undefined);
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  }, [setFieldValue]);

  // ===== RESET PROJECT FLOCK & KANDANG WHEN LOCATION CHANGES =====
  const prevLocationIdRef = useRef<number | string>('');

  useEffect(() => {
    const currentLocationId = formik.values.location_id || '';

    if (currentLocationId === prevLocationIdRef.current) {
      return;
    }

    prevLocationIdRef.current = currentLocationId;

    if (formik.values.project_flock !== null) {
      setFieldTouched('project_flock', false);
      setFieldValue('project_flock', null);
    }
    if (formik.values.project_flock_id !== 0) {
      setFieldTouched('project_flock_id', false);
      setFieldValue('project_flock_id', 0);
    }

    if (formik.values.kandang !== null) {
      setFieldTouched('kandang', false);
      setFieldValue('kandang', null);
    }
    if (formik.values.kandang_id !== 0) {
      setFieldTouched('kandang_id', false);
      setFieldValue('kandang_id', 0);
    }

    setSelectedProjectFlock(null);
    setSelectedKandang(null);
  }, [
    formik.values.location_id,
    formik.values.project_flock,
    formik.values.project_flock_id,
    formik.values.kandang,
    formik.values.kandang_id,
    setFieldTouched,
    setFieldValue,
  ]);

  const prevProjectFlockIdRef = useRef<number | string>('');

  useEffect(() => {
    const currentProjectFlockId = formik.values.project_flock_id || '';

    if (currentProjectFlockId === prevProjectFlockIdRef.current) {
      return;
    }

    prevProjectFlockIdRef.current = currentProjectFlockId;

    if (formik.values.kandang !== null) {
      setFieldTouched('kandang', false);
      setFieldValue('kandang', null);
    }
    if (formik.values.kandang_id !== 0) {
      setFieldTouched('kandang_id', false);
      setFieldValue('kandang_id', 0);
    }

    setSelectedKandang(null);
  }, [
    formik.values.project_flock_id,
    formik.values.kandang,
    formik.values.kandang_id,
    setFieldTouched,
    setFieldValue,
  ]);

  const handleDownloadTemplate = useCallback(() => {
    const population = projectFlockKandangLookup?.population;

    if (!population || !projectFlockKandangLookup) {
      toast.error('Silakan pilih Project Flock dan Kandang terlebih dahulu.');
      return;
    }

    generateUniformityTemplate(population, projectFlockKandangLookup);
  }, [projectFlockKandangLookup]);

  useEffect(() => {
    const unsub = subscribeValidate(() => {
      setIsValid(true);
    });

    return () => {
      unsub?.();
      useUiStore.getState().setExpandedDrawerOpen(false);
      useUiStore.getState().setExpandedDrawerContent(null);
      useUiStore.getState().setIsNextStep(false);
      useUniformityStore.getState().setUniformityStep('preview');
      useUniformityStore.getState().setVerifyUniformityResult(null);
    };
  }, [subscribeValidate, setIsValid]);

  useEffect(() => {
    if (expandedDrawerOpen) {
      if (uniformityStep === 'preview') {
        setExpandedDrawerContent(<UniformityPreviewForm />);
      } else if (uniformityStep === 'result') {
        setExpandedDrawerContent(<UniformityResultForm />);
      }
    } else {
      setExpandedDrawerContent(null);
      setIsNextStep(false);
      setUniformityStep('preview');
      setVerifyUniformityResult(null);
    }
  }, [
    expandedDrawerOpen,
    uniformityStep,
    setExpandedDrawerContent,
    setIsNextStep,
    setUniformityStep,
    setVerifyUniformityResult,
  ]);

  return (
    <>
      <section className='w-full'>
        <DrawerHeader
          leftIcon={formType == 'add' ? 'heroicons:x-mark' : 'mdi:arrow-left'}
          leftIconSize={20}
          leftIconHref={
            formType == 'add'
              ? '/production/uniformity'
              : `/production/uniformity/detail`
          }
          leftIconClassName='hover:text-base-content'
          subtitle={formType == 'add' ? 'Add Uniformity' : 'Update Uniformity'}
          subtitleClassName='text-sm font-medium text-base-content/50'
          showDivider
        />

        <section className='w-full p-4'>
          <h2 className='text-base font-medium text-base-content/50 font-roboto mb-1.5'>
            Informasi Umum
          </h2>

          <form onSubmit={handleFormSubmit} className='flex flex-col'>
            <DateInput
              required
              label='Tanggal'
              name='date'
              value={formik.values.date}
              onChange={handleDateChange}
              onBlur={formik.handleBlur}
              isError={formik.touched.date && Boolean(formik.errors.date)}
              errorMessage={formik.errors.date as string}
              disabled={isNextStep}
            />

            <SelectInput
              required
              label='Lokasi'
              placeholder='Pilih Lokasi...'
              value={formik.values.location}
              onChange={handleLocationChange}
              options={locationOptions}
              onInputChange={setLocationSelectInputValue}
              isLoading={isLoadingLocations}
              onMenuScrollToBottom={loadMoreLocations}
              isError={
                formik.touched.location_id && Boolean(formik.errors.location_id)
              }
              errorMessage={formik.errors.location_id as string}
              isClearable
              className={{ wrapper: 'w-full' }}
              isDisabled={isNextStep}
            />

            <SelectInput
              required
              label='Project Flock'
              placeholder='Pilih Project Flock...'
              value={formik.values.project_flock}
              onChange={handleProjectFlockChange}
              options={projectFlockOptions}
              onInputChange={setProjectFlockSearchValue}
              isLoading={isLoadingProjectFlocks}
              onMenuScrollToBottom={loadMoreProjectFlocks}
              isDisabled={!formik.values.location_id || isNextStep}
              isError={
                formik.touched.project_flock_id &&
                Boolean(formik.errors.project_flock_id)
              }
              errorMessage={formik.errors.project_flock_id as string}
              isClearable
              className={{ wrapper: 'w-full' }}
            />

            <SelectInput
              required
              label='Kandang'
              placeholder='Pilih Kandang...'
              value={formik.values.kandang}
              onChange={handleKandangChange}
              options={kandangOptions}
              isDisabled={!formik.values.project_flock_id || isNextStep}
              isError={
                formik.touched.kandang_id && Boolean(formik.errors.kandang_id)
              }
              errorMessage={formik.errors.kandang_id as string}
              isClearable
              className={{ wrapper: 'w-full' }}
            />

            <div>
              <div className='flex items-center justify-between'>
                <label
                  htmlFor='file-upload-input'
                  className={cn(
                    "w-full text-xs font-semibold leading-5 after:content-['*'] after:ml-0.5 after:text-red-500 py-2",
                    formik.touched.document &&
                      formik.errors.document &&
                      'text-red-500'
                  )}
                >
                  Upload File
                </label>
                {formik.values.document && !isNextStep ? (
                  <button
                    onClick={handleRemoveFile}
                    className='cursor-pointer'
                    type='button'
                  >
                    <Icon
                      icon='heroicons-solid:trash'
                      width={15}
                      height={15}
                      className='text-gray-400 hover:text-gray-600'
                    />
                  </button>
                ) : !formik.values.document && !isNextStep ? (
                  <button className='cursor-pointer' type='button'>
                    <Tooltip
                      position='left'
                      content='Pastikan file yang diunggah sesuai dengan template yang disediakan, template akan menyesuaikan dengan jumlah populasi pada kandang yang dipilih.'
                    >
                      <Icon
                        icon='heroicons:information-circle'
                        width={15}
                        height={15}
                        className='text-gray-400 hover:text-gray-600'
                      />
                    </Tooltip>
                  </button>
                ) : null}
              </div>

              <section
                className={cn(
                  'h-full w-full border rounded-2xl border-dashed cursor-pointer',
                  formik.touched.document && formik.errors.document
                    ? 'border-red-500'
                    : 'border-gray-300'
                )}
                onClick={() =>
                  document.getElementById('file-upload-input')?.click()
                }
              >
                {formik.values.document ? (
                  <div className='flex flex-col items-center justify-center gap-2 my-10'>
                    <div className='border border-[#18181B]/25 rounded-2xl p-1 flex items-center justify-center'>
                      <Button
                        type='button'
                        className='rounded-2xl border border-sky-500 bg-primary  text-white'
                        onClick={(e) => {
                          e.stopPropagation();
                          document.getElementById('file-upload-input')?.click();
                        }}
                      >
                        <Icon
                          icon={'heroicons:document-text'}
                          className='text-2xl text-white'
                        />
                      </Button>
                    </div>
                    <span className='text-md font-semibold text-black line-clamp-2 text-center max-w-xs break-all'>
                      {formik.values.document.name}
                    </span>
                  </div>
                ) : (
                  <>
                    <div
                      className={`flex flex-col items-center justify-center text-center gap-2 ${projectFlockKandangLookup?.available_quantity ? 'my-10 mb-0' : 'my-10'}`}
                    >
                      <div className='border border-[#18181B]/25 rounded-2xl p-1 flex items-center justify-center'>
                        <Button
                          type='button'
                          className='rounded-2xl border border-sky-500 bg-primary  text-white'
                          onClick={(e) => {
                            e.stopPropagation();
                            document
                              .getElementById('file-upload-input')
                              ?.click();
                          }}
                        >
                          <Icon
                            icon={'heroicons-solid:arrow-up-tray'}
                            className='text-2xl text-white'
                          />
                        </Button>
                      </div>
                      <span className='text-md font-semibold text-[#18181B80]'>
                        Choose file to upload
                      </span>
                      <span className='text-xs font-light text-[#18181B80] text-center max-w-xs px-4'>
                        {projectFlockKandangLookup?.population
                          ? `Jumlah data yang dibutuhkan: ${formatNumber(Math.round(projectFlockKandangLookup.population * 0.02))} (2% dari ${formatNumber(projectFlockKandangLookup.population)} populasi).`
                          : 'Upload data file (*.xlsx)'}
                      </span>
                    </div>

                    {!!projectFlockKandangLookup?.population && (
                      <>
                        <div className='flex items-center justify-center gap-2 py-4'>
                          <div className='h-px bg-[#18181B33] w-8'></div>
                          <span className='text-[#18181B33] text-xs'>
                            Templates
                          </span>
                          <div className='h-px bg-[#18181B33] w-8'></div>
                        </div>

                        <div className='flex items-center justify-center mb-10'>
                          <Button
                            type='button'
                            variant='outline'
                            className='btn-sm rounded-2xl shadow-md border border-base-300'
                            onClick={(e) => {
                              e.stopPropagation();
                              handleDownloadTemplate();
                            }}
                          >
                            <Icon
                              icon='heroicons:arrow-down-tray'
                              width={18}
                              height={18}
                            />
                            Template XLSX
                          </Button>
                        </div>
                      </>
                    )}
                  </>
                )}
              </section>

              <input
                ref={fileInputRef}
                type='file'
                id='file-upload-input'
                name='document'
                accept='application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/csv'
                onChange={handleFileChange}
                className='hidden'
              />

              {formik.touched.document && formik.errors.document && (
                <p className='w-full text-sm text-red-500 mt-2'>
                  {formik.errors.document as string}
                </p>
              )}
            </div>

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

              {/* Error List Alert */}
              {formErrorList.length > 0 && (
                <AlertErrorList
                  formErrorList={formErrorList}
                  onClose={() => setFormErrorList([])}
                />
              )}
            </div>

            {!isNextStep && (
              <>
                <div className='border-t border-base-content/10 -mx-4 mt-4' />
                <RequirePermission permissions='lti.production.uniformity.create'>
                  <Button
                    type='submit'
                    color='primary'
                    className='w-full mt-4 px-3 py-2.5 text-sm text-base-100 rounded-lg shadow-sm'
                    disabled={formik.isSubmitting}
                  >
                    {formik.isSubmitting ? (
                      <span className='loading loading-spinner'></span>
                    ) : (
                      'Next'
                    )}
                  </Button>
                </RequirePermission>
              </>
            )}
          </form>
        </section>
      </section>
    </>
  );
};

export default UniformityForm;
