'use client';

import React, { FC, useContext, useEffect, useId, useState } from 'react';
import { Controller } from 'react-hook-form';

import { IMakeSelectProps } from '../../interfaces/make-select';
import { ComponentStateContext } from '../../context/component/component-state';
import useEnableIf from '../../hooks/use-enable-if';
import useRenderIf from '../../hooks/use-render-if';
import useLiveData from '../../hooks/use-live-data';

const MakeSelect: FC<IMakeSelectProps> = ({
  element,
  control,
  watch,
  setValue,
  unregister,
}) => {
  const { Select } = useContext(ComponentStateContext);

  const {
    name: elementName,
    validation: { required, message, regex, ...otherValidation },
    enableIf,
    renderIf,
    liveData: elementLiveData,
    ...inputProps
  } = element;

  const [liveSearching, setLiveSearching] = useState<boolean>(false);

  const { checkLiveData, liveData, setLiveData } = useLiveData({
    elementLiveData,
  });
  const { checkEnable, enable, setEnable } = useEnableIf({
    elementEnableIf: enableIf,
  });
  const { checkRender, render, setRender } = useRenderIf({
    elementRenderIf: renderIf,
  });

  const elementId = useId();

  useEffect(() => {
    const { unsubscribe } = watch((formData, { name, type }) => {
      if (!name) return;

      if (enableIf) {
        checkEnable(formData, { name, type }).then((enableStatus) => {
          if (enableStatus === undefined || enableStatus === null) return;
          if (enable !== enableStatus) setEnable(enableStatus);
        });
      }

      if (renderIf) {
        checkRender(formData, { name, type }).then((renderStatus) => {
          if (renderStatus === undefined || renderStatus === null) return;

          if (render !== renderStatus) {
            if (render && !renderStatus) unregister(elementName as string);
            setRender(!!renderStatus);
          }
        });
      }

      if (elementLiveData) {
        setLiveSearching(true);

        checkLiveData(formData, { name, type })
          .then((options) => {
            if (options === undefined || options === null) return;

            setLiveData(options);
            setValue(elementName, options);
          })
          .finally(() => {
            setLiveSearching(false);
          });
      }
    });

    return () => unsubscribe();
  }, [watch, render, enable, liveData]);

  if (!render) return null;

  return (
    <Controller
      control={control}
      name={elementName}
      rules={{
        required: {
          value: required,
          message: message ?? '',
        },
        pattern: regex
          ? {
              value: regex,
              message: message ?? '',
            }
          : undefined,
        ...otherValidation,
      }}
      render={({
        field: { onChange, value },
        fieldState: { invalid, error },
      }) => (
        <Select
          {...inputProps}
          id={elementId}
          name={elementName}
          onChange={onChange}
          value={value}
          invalid={invalid}
          error={error}
          disabled={element.disabled ?? !enable}
          liveSearching={liveSearching}
          options={liveData || (element.options ?? [])}
        />
      )}
    />
  );
};

export default MakeSelect;
