import { cn } from "@/lib/utils";
import { FormControl, FormDescription, FormField, FormItem, Input, InputProps } from "@/ui";

import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { createElement } from "react";
import { FieldPath, FieldValues, UseControllerProps, useFormContext } from "react-hook-form";
import { FormErrorMessage } from "./FormErrorMessage";
import { FormLabel, FormLabelProps } from "./FormLabel";
import { FormInputProps, FormInputWithIconProps } from "./FormProps";

const formTextFieldVariants = cva("", {
  variants: {
    variant: {
      default: "",
      ghost:
        "border-0 focus-visible:border focus-visible:border-input focus-visible:ring-0 focus-visible:ring-offset-0 ",
    },
  },
  defaultVariants: {
    variant: "default",
  },
});

export type FormTextFieldProps<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = {
  button?: (props?: React.PropsWithChildren) => React.ReactNode;
} & InputProps &
  FormInputProps &
  Partial<FormLabelProps> &
  FormInputWithIconProps &
  UseControllerProps<TFieldValues, TName> &
  VariantProps<typeof formTextFieldVariants>;

export const FormTextField = React.forwardRef<HTMLInputElement, FormTextFieldProps>(
  (props, ref) => {
    const {
      name,
      label,
      hint,
      description,
      placeholder,
      className,
      disabled,
      defaultValue,
      rules,
      type,
      variant,
      required,

      button,
      leadIcon,
      trailIcon,
    } = props;

    const { control } = useFormContext();

    return (
      <FormField
        defaultValue={defaultValue}
        control={control}
        name={name}
        disabled={disabled}
        rules={{
          required,
          ...rules,
        }}
        render={({ field, fieldState }) => {
          return (
            <FormItem ref={ref} className={cn(className, "space-y-3")}>
              {label && (
                <FormLabel
                  label={label}
                  hint={hint}
                  required={Boolean(rules?.required ?? required)}
                />
              )}
              <div className={cn(button ? "flex" : null)}>
                <div
                  className={cn(
                    leadIcon ? "relative flex items-stretch flex-grow focus-within:z-10" : ""
                  )}
                >
                  {leadIcon && (
                    <div className='absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none'>
                      {React.createElement(
                        leadIcon,
                        {
                          className: "h-5 w-5 text-muted-foreground",
                          "aria-hidden": true,
                        },
                        null
                      )}
                    </div>
                  )}

                  <FormControl
                    className={cn("block", leadIcon ? "pl-10" : "", trailIcon ? "pr-10" : "")}
                  >
                    <Input
                      type={type}
                      placeholder={placeholder}
                      className={cn(
                        fieldState.error ? "border-destructive focus-visible:ring-destructive" : "",
                        formTextFieldVariants({ variant, className })
                      )}
                      {...field}
                    />
                  </FormControl>

                  {trailIcon && (
                    <div className='absolute inset-y-0 right-0 flex items-center pl-3 pointer-events-none'>
                      {createElement(
                        trailIcon,
                        {
                          className: "h-5 w-5 text-muted-foreground",
                          "aria-hidden": true,
                        },
                        null
                      )}
                    </div>
                  )}
                </div>
                {button && <>{createElement(button)}</>}
              </div>

              {description && <FormDescription>{description}</FormDescription>}
              <FormErrorMessage />
            </FormItem>
          );
        }}
      />
    );
  }
);
