import React from "react";
import FormContainer from "./formContainer";
import { Controller, useFormState, Control } from "react-hook-form";
import { matchNumber, matchPersianChars } from "../utils/validations";
import { toEnglishNumber } from "../utils/functions";

export type InputProps = {
  name: string;
  label: string;
  required?: boolean;
  placeholder?: string;
  readOnly?: boolean;
  disabled?: boolean;
  ltr?: boolean;
  rules?: object;
  message?: string;
  fullWidth?: boolean;
  type?: string;
  inputClassnames?: string;
  hideLabel?: boolean;
  inputProps?: object;
  format?: string;
  onFormatError?: Function;
  control: Control;
};

const Input = ({
  name,
  label,
  required,
  control,
  placeholder,
  readOnly,
  disabled,
  ltr,
  rules = {},
  message,
  fullWidth,
  type = "text",
  inputClassnames = "",
  hideLabel,
  inputProps = {},
  format = "all",
  onFormatError = Function.prototype,
}: InputProps) => {
  const { errors } = useFormState();
  const customClass = !!errors[name]
    ? "border-red-500 focus:border-red-500 placeholder:font-light placeholder:text-red-500"
    : "border-gray-300 focus:border-blue-400";

  const validatePersianFormat = () => {
    return true;
  };

  const validatePersianCharsFormat = (value: string) => {
    return matchPersianChars(value);
  };

  const validateNonePersianCharsFormat = (value: string) => {
    return !matchPersianChars(value);
  };

  const validateNumberFormat = (value: string) => {
    return matchNumber(value);
  };

  const validateNumberRange = () => true;

  const handleChange = (
    e: React.ChangeEvent<HTMLInputElement>,
    onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
  ) => {
    const value = e.target.value;
    if (!onChange) {
      return;
    }

    if (
      format === "all" ||
      !value ||
      value.length === 0 ||
      (format === "persian" && validatePersianFormat()) ||
      (format === "persianChars" && validatePersianCharsFormat(value)) ||
      (format === "nonePersianChars" &&
        validateNonePersianCharsFormat(value)) ||
      (format === "number" &&
        validateNumberFormat(value) &&
        (type !== "number" || validateNumberRange()))
    ) {
      onChange(
        format === "number"
          ? {
              ...e,
              target: { ...e.target, value: toEnglishNumber(e.target.value) },
            }
          : e
      );
    } else if (!!onFormatError) {
      onFormatError();
    }
  };

  const controllerRule = {
    ...(!!required ? { required } : {}),
    ...(!!message ? { message } : {}),
    ...rules,
  };

  return (
    <FormContainer
      id={name}
      label={label}
      required={required}
      hideLabel={hideLabel}
      hideStar={false}
    >
      <Controller
        name={name}
        control={control}
        rules={controllerRule}
        render={({ field }) => (
          <input
            {...field}
            value={field.value || ""}
            onChange={(e) => handleChange(e, field.onChange)}
            {...inputProps}
            id={name}
            readOnly={readOnly}
            disabled={disabled}
            type={type}
            placeholder={placeholder || label}
            className={`block px-4 py-2 bg-white border ${
              ltr ? "text-ltr" : ""
            } text-gray-800 ${customClass} rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring focus:ring-blue-300 disabled:bg-gray-100 dark:disabled:bg-gray-700 ${inputClassnames} ${
              fullWidth ? "w-full" : ""
            }`}
          />
        )}
      />
      {!!errors[name] && (
        <h4 className="text-sm mt-2 mr-2 font-light text-red-600">
          {errors[name]?.message?.toString() || "این فیلد اجباریست"}
        </h4>
      )}
    </FormContainer>
  );
};

export default Input;
