"use client";

import React, {
  useState,
  useEffect,
  useRef,
  forwardRef,
  useCallback,
} from "react";
import { cn } from "@/lib/utils";

const CustomInput = forwardRef(
  (
    {
      id,
      name,
      type = "text",
      label,
      placeholder = "",
      value: propValue,
      defaultValue = "",
      onChange,
      onFocus,
      onBlur,
      disabled = false,
      readOnly = false,
      required = false,
      errors,
      helperText,
      autoComplete = "off",
      autoFocus = false,

      // Variant & size options
      variant = "outlined",
      size = "large",

      enablePasswordToggle = false,

      // For textarea support
      rows = 3,

      containerProps = {},
      labelProps = {},

      className = "",
      containerClassName = "",
      inputClassName = "",
      labelClassName = "",
      errorClassName = "",
      helperTextClassName = "",
      iconLeftClassName = "",
      iconRightClassName = "",
      style = {},
      containerStyle = {},
      inputStyle = {},
      labelStyle = {},
      errorStyle = {},
      helperTextStyle = {},

      iconLeft,
      iconRight,

      // Label placement options
      labelPlacement = "floating",

      renderLabel,
      renderInput,
      renderError,
      renderHelperText,

      "aria-label": ariaLabel,
      "aria-labelledby": ariaLabelledBy,
      "aria-describedby": ariaDescribedBy,

      ...restProps
    },
    ref
  ) => {
    // Controlled vs uncontrolled handling
    const isControlled = propValue !== undefined;
    const [internalValue, setInternalValue] = useState(defaultValue);
    const currentValue = isControlled ? propValue : internalValue;

    const [isFocused, setIsFocused] = useState(false);
    const [showPassword, setShowPassword] = useState(false);
    const internalRef = useRef(null);

    useEffect(() => {
      const valueToSet =
        propValue === null || propValue === undefined ? "" : propValue;
      setInternalValue(valueToSet);
    }, [propValue]);

    // Add the same nested error extraction logic from MultiSelect
    const getNestedError = (path, errors) => {
      if (!errors || !path) return null;
      const segments = path.split(/[\[\].]+/).filter(Boolean);
      let currentError = errors;
      for (const segment of segments) {
        if (/^\d+$/.test(segment)) {
          currentError = currentError?.[parseInt(segment)];
        } else {
          currentError = currentError?.[segment];
        }
        if (currentError?.message || currentError?.type) {
          return currentError;
        }
      }
      return currentError;
    };

    const error = getNestedError(name, errors);
    const errorMessage = error?.message || String(error || "");

    const handleChange = useCallback(
      (e) => {
        if (!isControlled) {
          setInternalValue(e.target.value);
        }
        onChange?.(e);
      },
      [onChange, isControlled]
    );

    const handleFocus = useCallback(
      (e) => {
        setIsFocused(true);
        onFocus?.(e);
      },
      [onFocus]
    );

    const handleBlur = useCallback(
      (e) => {
        setIsFocused(false);
        onBlur?.(e);
      },
      [onBlur]
    );

    const handleTogglePassword = () => {
      setShowPassword((prev) => !prev);
    };

    const shouldFloatLabel =
      labelPlacement === "floating" &&
      (isFocused || currentValue || placeholder);

    const hasError = !!errorMessage;

    const errorId = hasError ? `${id}-error` : undefined;
    const helperTextId = helperText ? `${id}-helper` : undefined;
    const ariaDescribedByIds = [ariaDescribedBy, errorId, helperTextId]
      .filter(Boolean)
      .join(" ");

    const combinedRef = (node) => {
      internalRef.current = node;
      if (ref) {
        if (typeof ref === "function") {
          ref(node);
        } else {
          ref.current = node;
        }
      }
    };

    // Tailwind variant classes
    const variantClasses = {
      outlined: "border border-gray-300 bg-transparent rounded-md",
      filled: "bg-gray-100 border-none rounded-md",
      standard: "border-0 border-b border-gray-300 rounded-none",
    };

    // Tailwind size classes
    const sizeClasses = {
      small: "text-xs py-1 px-2",
      medium: "text-sm py-1.5 px-2",
      large: "text-base py-2 px-3",
    };

    const renderLabelElement = () => {
      if (!label || labelPlacement === "hidden") return null;

      const labelContent = (
        <>
          {label}
          {required && <span className="text-red-500 ml-0.5">*</span>}
        </>
      );

      if (renderLabel) return renderLabel(label);

      if (labelPlacement === "floating") {
        return (
          <label
            htmlFor={id}
            className={cn(
              "absolute pointer-events-none transition-all duration-200",
              shouldFloatLabel
                ? "top-0 bg-white px-1.5 text-xs"
                : "top-1/2 -translate-y-1/2 left-2 text-sm",
              hasError ? "text-red-500" : "text-gray-700",
              disabled ? "text-gray-400" : "",
              labelClassName
            )}
            {...labelProps}
          >
            {labelContent}
          </label>
        );
      }

      return (
        <label
          htmlFor={id}
          className={cn(
            "block mb-1 text-sm",
            hasError ? "text-red-500" : "text-gray-700",
            disabled ? "text-gray-400" : "",
            labelClassName
          )}
          {...labelProps}
        >
          {labelContent}
        </label>
      );
    };

    const renderNativeInput = () => {
      let inputType = type;
      if (type === "password" && enablePasswordToggle) {
        inputType = showPassword ? "text" : "password";
      }

      // Safe value handling to prevent "uncontrolled to controlled" React warnings
      const safeValue =
        currentValue === null || currentValue === undefined ? "" : currentValue;

      const baseInputClasses = cn(
        "file:text-foreground placeholder:text-gray-400 w-full bg-transparent outline-none",
        "disabled:cursor-not-allowed disabled:opacity-50",
        "focus:outline-none",
        hasError ? "text-red-500" : "text-gray-900",
        iconLeft ? "pl-7" : "",
        iconRight || (type === "password" && enablePasswordToggle)
          ? "pr-7"
          : "",
        sizeClasses[size],
        inputClassName
      );

      if (type === "textarea") {
        return (
          <textarea
            id={id}
            ref={combinedRef}
            name={name}
            placeholder={placeholder}
            rows={rows}
            value={safeValue}
            onChange={handleChange}
            onFocus={handleFocus}
            onBlur={handleBlur}
            disabled={disabled}
            readOnly={readOnly}
            autoComplete={autoComplete}
            autoFocus={autoFocus}
            aria-label={ariaLabel}
            aria-labelledby={ariaLabelledBy}
            aria-describedby={ariaDescribedByIds}
            aria-invalid={hasError}
            aria-required={required}
            className={baseInputClasses}
            style={inputStyle}
            {...restProps}
          />
        );
      }

      return (
        <input
          id={id}
          ref={combinedRef}
          name={name}
          type={inputType}
          placeholder={placeholder}
          value={safeValue}
          onChange={handleChange}
          onFocus={handleFocus}
          onBlur={handleBlur}
          disabled={disabled}
          readOnly={readOnly}
          autoComplete={autoComplete}
          autoFocus={autoFocus}
          aria-label={ariaLabel}
          aria-labelledby={ariaLabelledBy}
          aria-describedby={ariaDescribedByIds}
          aria-invalid={hasError}
          aria-required={required}
          className={baseInputClasses}
          style={inputStyle}
          {...restProps}
        />
      );
    };

    const renderInputElement = () => {
      if (renderInput) {
        return renderInput({
          id,
          ref: internalRef,
          name,
          type,
          value: currentValue,
          placeholder,
          disabled,
          readOnly,
          required,
          autoComplete,
          autoFocus,
          "aria-label": ariaLabel,
          "aria-labelledby": ariaLabelledBy,
          "aria-describedby": ariaDescribedByIds,
          errors: errorMessage,
          size,
          variant,
          onChange: handleChange,
          onFocus: handleFocus,
          onBlur: handleBlur,
        });
      }

      return (
        <div className="relative flex items-center w-full">
          {iconLeft && (
            <span
              className={cn(
                "absolute left-2 top-1/2 -translate-y-1/2 text-gray-500",
                disabled ? "text-gray-400" : "",
                iconLeftClassName
              )}
            >
              {iconLeft}
            </span>
          )}

          {renderNativeInput()}

          {type === "password" && enablePasswordToggle && (
            <span
              className={cn(
                "absolute right-2 top-1/2 -translate-y-1/2 text-gray-500 cursor-pointer",
                iconRightClassName
              )}
              onClick={handleTogglePassword}
            >
              {showPassword ? "🙈" : "👁️"}
            </span>
          )}

          {type !== "password" && iconRight && (
            <span
              className={cn(
                "absolute right-2 top-1/2 -translate-y-1/2 text-gray-500",
                disabled ? "text-gray-400" : "",
                iconRightClassName
              )}
            >
              {iconRight}
            </span>
          )}
        </div>
      );
    };

    const renderErrorContent = () => {
      if (!errorMessage) return null;

      if (renderError) return renderError(errorMessage);

      return (
        <div
          id={errorId}
          className={cn("text-red-500 text-right text-xs mt-1", errorClassName)}
          style={errorStyle}
        >
          {errorMessage}
        </div>
      );
    };

    const renderHelperTextContent = () => {
      if (!helperText) return null;

      const helperElement = (
        <div
          id={helperTextId}
          className={cn("text-gray-500 text-xs mt-1", helperTextClassName)}
          style={helperTextStyle}
        >
          {helperText}
        </div>
      );

      return renderHelperText ? renderHelperText(helperElement) : helperElement;
    };

    return (
      <div
        className={cn(
          "w-full mb-4 relative",
          disabled ? "opacity-70 cursor-not-allowed" : "",
          className
        )}
        style={style}
        {...containerProps}
      >
        {labelPlacement === "default" && renderLabelElement()}

        <div
          className={cn(
            "relative min-h-8 flex items-center",
            variantClasses[variant],
            hasError
              ? "border-red-500 focus-within:ring-red-200"
              : "focus-within:border-blue-500 focus-within:ring-blue-200",
            disabled ? "bg-gray-100 border-gray-300" : "bg-white",
            "focus-within:ring-2 focus-within:ring-offset-0",
            !disabled ? "transition-all duration-200" : "",
            containerClassName
          )}
          style={containerStyle}
        >
          {labelPlacement === "floating" && renderLabelElement()}
          {renderInputElement()}
        </div>

        {renderErrorContent()}
        {renderHelperTextContent()}
      </div>
    );
  }
);

CustomInput.displayName = "CustomInput";

export { CustomInput };
