import { cn } from "@/lib/utils";
import { FormControl, FormDescription, FormField, FormItem, InputProps } from "@/ui";
import { CurrencyData, Language, MoneyValue, MoneyValueObject } from "@shared/contexts";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import CurrencyInput, { CurrencyInputOnChangeValues } from "react-currency-input-field";
import { FieldPath, FieldValues, UseControllerProps, useFormContext } from "react-hook-form";
import { FormErrorMessage } from "./FormErrorMessage";
import { FormLabel, FormLabelProps } from "./FormLabel";
import { FormInputProps, FormInputWithIconProps } from "./FormProps";

const formCurrencyFieldVariants = cva(
  "flex h-10 w-full rounded-md bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
  {
    variants: {
      variant: {
        default:
          "border border-input ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ",
        outline: "focus-visible:border focus-visible:border-input",
        ghost: "bg-transparent",
      },
    },
    defaultVariants: {
      variant: "default",
    },
  }
);

export type FormCurrencyFieldProps<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = {
  button?: (props?: React.PropsWithChildren) => React.ReactNode;
  defaultValue?: any;
} & InputProps &
  FormInputProps &
  Partial<FormLabelProps> &
  FormInputWithIconProps &
  UseControllerProps<TFieldValues, TName> &
  VariantProps<typeof formCurrencyFieldVariants> & {
    currency: CurrencyData;
    language: Language;
    scale: number;
  };

export const FormCurrencyField = React.forwardRef<HTMLInputElement, FormCurrencyFieldProps>(
  (props, ref) => {
    const {
      name,
      label,
      hint,
      description,
      placeholder,
      className,
      disabled,
      defaultValue,
      rules,
      readOnly,
      scale,
      currency,
      language,
      variant,
    } = props;

    const { control } = useFormContext();

    const [inputValue, setInputValue] = React.useState<string>("");

    const transform = {
      input: (value: MoneyValueObject) => {
        if (typeof value !== "object") {
          return value;
        }

        const moneyOrError = MoneyValue.create(value);

        if (moneyOrError.isFailure) {
          throw moneyOrError.error;
        }

        const result = moneyOrError.object.toString();
        return inputValue.endsWith(",") ? result.replace(/.0$/, ",") : result;
      },
      output: (
        _value: string | undefined,
        _name?: string,
        values?: CurrencyInputOnChangeValues
      ) => {
        const { value: amount } = values ?? { value: null };

        setInputValue(amount ?? "");

        const moneyOrError = MoneyValue.createFromFormattedValue(amount, currency.code);
        if (moneyOrError.isFailure) {
          throw moneyOrError.error;
        }

        return moneyOrError.object.toObject();
      },
    };

    return (
      <FormField
        defaultValue={defaultValue}
        control={control}
        name={name}
        disabled={disabled}
        rules={rules}
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        render={({ field }) => {
          return (
            <FormItem ref={ref} className={cn(className, "space-y-3")}>
              {label && (
                <FormLabel label={label} hint={hint} required={Boolean(rules?.required ?? false)} />
              )}
              <FormControl>
                <CurrencyInput
                  intlConfig={{
                    locale: language.code,
                  }}
                  name={field.name}
                  //ref={field.ref} <-- no activar que hace cosas raras
                  onBlur={field.onBlur}
                  disabled={field.disabled}
                  readOnly={readOnly}
                  className={cn(formCurrencyFieldVariants({ variant, className }))}
                  suffix={` ${currency?.symbol}`}
                  groupSeparator='.'
                  decimalSeparator=','
                  placeholder={placeholder}
                  //allowDecimals={scale !== 0}
                  decimalsLimit={scale}
                  decimalScale={scale}
                  //fixedDecimalLength={scale} <- no activar para que sea más cómodo escribir las cantidades
                  step={1}
                  // { ...field }
                  value={transform.input(field.value)}
                  //onChange={() => {}}
                  onValueChange={(value, name, values) =>
                    field.onChange(transform.output(value, name, values))
                  }
                />
              </FormControl>

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

FormCurrencyField.displayName = "FormCurrencyField";
