import { FieldInputProps } from "formik";
import { ChangeEvent, FocusEvent, ReactElement, ReactNode } from "react";
import { AnyObject, AnySchema } from "yup";

export type ToastProps = {
  message: string;
  type: "SUCCESS" | "ERROR" | "LOADING";
  position?:
    | "top-right"
    | "top-center"
    | "top-left"
    | "bottom-right"
    | "bottom-center"
    | "bottom-left";
  autoClose?: number;
};

export type ModalProps = {
  show: boolean;
  onHide?: () => void;
  title?: string;
  children: ReactNode;
  className?: string;
  size: "sm" | "lg" | "xl";
  fullscreen?: string | true | undefined;
  onClose?: () => void;
};

export type InputFieldProps = {
  validationSchema: AnySchema<AnyObject> | undefined;
  label: string;
  type?: string;
  field: {
    name: string;
    value: string;
    onChange: (e: ChangeEvent<HTMLInputElement>) => void;
  };
  isValid: boolean;
  error: string | undefined;
  autoFocus?: boolean;
  placeholder?: string;
  component?: ReactNode;
  disabled?: boolean;
  as?: string;
  isPassword?: boolean;
  setPasswordIcon?: (data: boolean) => void;
  passwordIcon?: boolean;
  maxLength?: number;
  isAuth?: boolean;
  rightIcon?: boolean;
  icon?: React.ReactNode;
  onBlur?: () => void;
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
  unit?: string;
  value?: string;
};

export type CustomInputFieldProps = {
  validationSchema: AnySchema<AnyObject> | undefined;
  label: string;
  field: {
    name: string;
    value: Date | string | string[] | number | undefined | unknown;
    onChange: (e: ChangeEvent<HTMLInputElement>) => void;
    onBlur: (e?: FocusEvent<HTMLInputElement, Element> | undefined) => void;
  };
  error: string | undefined;
  children: ReactNode;
  inputId: string;
};

export type FormikTimeFieldProps = {
  name: string;
  label: string;
  errors?: string | "";
  validationSchema?: AnySchema<AnyObject, any>;
  isDisabled?: boolean;
  value?: string;
  onChange?: (time: string) => void;
  use12Hours?: boolean;
};

export type FormikPhoneNumberProps = {
  name: string;
  label: string;
  errors?: string | undefined;
  isDisabled?: boolean;
  validationSchema?: AnySchema<AnyObject>;
  onChange?: (phoneNumber: string) => void;
  isInternational?: boolean;
  value?: string;
};

export type FormikFieldProps = {
  name: string;
  errors: Record<string, string>;
  validationSchema: AnySchema<AnyObject>;
  label: string;
  type: string;
  autoFocus?: boolean;
  placeholder?: string;
  disabled?: boolean;
  as?: string;
  isPassword?: boolean;
  setPasswordIcon?: (data: boolean) => void;
  passwordIcon?: boolean;
  maxLength?: number;
  isAuth?: boolean;
  rightIcon?: boolean;
  icon?: React.ReactNode;
  onBlur?: () => void;
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
  unit?: string;
  value?: string;
};

export type FormikDateFieldProps = {
  name: string;
  label: string;
  errors?: string | undefined;
  validationSchema?: AnySchema<AnyObject>;
  minDate?: Date | string | number | undefined;
  maxDate?: Date | string | number | undefined;
  isDisabled?: boolean;
  onlyYearPicker?: boolean;
  onlyMonthPicker?: boolean;
};

export type CustomStylesProps = {
  isFocused: boolean;
  isSelected: boolean;
};

export type Option = {
  label: string;
  value: string;
  id?: number;
};

export type CustomCreatableSelectProps = {
  options: Option[];
  isMulti?: boolean;
  className?: string;
  placeholder?: string;
  callback?: (value: Option[]) => void;
  isDisabled: boolean;
  isClearable: boolean;
  field?: FieldInputProps<any> extends infer F ? F : never;
  form?: {
    setFieldValue: (name: string, value: string | string[]) => void;
  };
  displayName?: string;
  maxLength?: number;
};

export type CustomSelectProps = {
  options: Option[] | undefined;
  isMulti?: boolean;
  className?: string;
  placeholder?: string;
  id: string;
  callback?: (value: Option) => void;
  isDisabled: boolean;
  value?: Option | null | undefined | string;
  isClearable?: boolean;
  onFieldUpdate?: (value: Option[] | Option) => void;
  field?: FieldInputProps<Option | null | undefined | string> & {
    onBlur?: () => void;
  };
  form?: {
    setFieldValue: (name: string, value: string | string[]) => void;
  };
};

export type AccordionProps = {
  accordionText?: string | undefined;
  children: ReactElement;
  className?: string;
  icon?: ReactNode;
  rightHeader?: ReactNode;
};

export type BreadCrumbProps = {
  title: string;
  url?: string;
  isSubTitle?: boolean;
  isTitle?: boolean;
  breadCrumb?:
    | {
        title: string;
        url: string;
      }[]
    | undefined;
};

export type ButtonProps = {
  text: string;
  variant?: string;
  className?: string;
  type?: "submit" | "reset" | "button" | undefined;
  onClick?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
  onDoubleClick?: (() => void) | undefined;
  isDisabled?: boolean;
  isLoading?: boolean;
  prefixIconChildren?: ReactNode;
  sufixIconChildren?: ReactNode;
};

export type NavBarMenuItemsProps = {
  url: string;
  text: string;
  subMenu?: string;
  isRadius?: boolean;
  menu?: string;
  icon?: ReactNode;
};

export type PillProps = {
  pillText: string;
  pillColorClassName: string;
};

export type SwitchProps = {
  toggle?: boolean;
  textOff: string;
  textOn: string;
  isSwitchDefault?: boolean;
  checked?: boolean;
  className?: string;
  onChange?: ((e: ChangeEvent<HTMLInputElement>) => void) | undefined;
  isDisabled?: boolean;
};
