import {
  fieldDescriptionProps,
  fieldItemProps,
  type FieldItemProps,
  fieldLabelProps,
  fieldMessageProps,
  formInputProps,
  type FormInputProps,
  formRadioGroupProps,
  formSelectProps,
  type FormSelectProps,
} from "@/components/tanstack-form-utils";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";
import type { FieldApi } from "@tanstack/react-form";
import { cloneElement, type ReactElement, type ReactNode, useId } from "react";

export interface FormLayoutBaseProps {
  fieldApi: FieldApi<
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any
  >;
  label?: ReactNode;
  description?: ReactNode;
  disabled?: boolean;
  className?: string;
}

export interface FormInputLayoutProps extends FormLayoutBaseProps {
  children: ReactElement<FieldItemProps & FormInputProps>;
}

export function FormInputLayout({
  label,
  disabled,
  fieldApi,
  description,
  children,
  className,
}: FormInputLayoutProps) {
  const id = useId();
  const props = {
    ...fieldItemProps(fieldApi, id),
    ...formInputProps(fieldApi, disabled),
  };
  props.className = cn(props.className, children.props.className);

  return (
    <div className={cn("space-y-2", className)}>
      {label != null && (
        <Label {...fieldLabelProps(fieldApi, id)}>{label}</Label>
      )}
      {cloneElement(children, props)}
      <p {...fieldMessageProps(fieldApi, id)} />
      {description != null && (
        <p {...fieldDescriptionProps(fieldApi, id)}>{description}</p>
      )}
    </div>
  );
}

export interface FormSelectLayoutProps<Data extends string | undefined = string>
  extends FormLayoutBaseProps {
  children: ReactElement<FieldItemProps & FormSelectProps<Data>>;
}

export function FormSelectLayout<Data extends string | undefined = string>({
  label,
  disabled,
  fieldApi,
  description,
  children,
  className,
}: FormSelectLayoutProps<Data>) {
  const id = useId();
  const props = {
    ...fieldItemProps(fieldApi, id),
    ...formSelectProps<Data>(fieldApi, disabled),
  };
  props.className = cn(props.className, children.props.className);

  return (
    <div className={cn("space-y-2", className)}>
      {label != null && (
        <Label {...fieldLabelProps(fieldApi, id)}>{label}</Label>
      )}
      {cloneElement(children, props)}
      <p {...fieldMessageProps(fieldApi, id)} />
      {description != null && (
        <p {...fieldDescriptionProps(fieldApi, id)}>{description}</p>
      )}
    </div>
  );
}

export interface FormRadioGroupLayoutProps extends FormLayoutBaseProps {
  children: ReactElement<FieldItemProps & FormRadioGroupLayoutProps>;
}

export function FormRadioGroupLayout({
  label,
  disabled,
  fieldApi,
  description,
  children,
  className,
}: FormRadioGroupLayoutProps) {
  const id = useId();
  const props = {
    ...fieldItemProps(fieldApi, id),
    ...formRadioGroupProps(fieldApi, disabled),
  };
  props.className = cn(props.className, children.props.className);

  return (
    <div className={cn("space-y-2", className)}>
      {label != null && (
        <Label {...fieldLabelProps(fieldApi, id)}>{label}</Label>
      )}
      {cloneElement(children, props)}
      <p {...fieldMessageProps(fieldApi, id)} />
      {description != null && (
        <p {...fieldDescriptionProps(fieldApi, id)}>{description}</p>
      )}
    </div>
  );
}

export function FormDisabledFieldLayout({
  children,
  label,
  className,
  description,
}: Omit<FormLayoutBaseProps, "fieldApi" | "disabled"> & {
  children: ReactElement<{ disabled?: boolean }, any>;
}) {
  return (
    <div className={cn("space-y-2", className)}>
      {label != null && <Label>{label}</Label>}
      {cloneElement(children, { disabled: true })}
      {description != null && (
        <p className="text-sm text-muted-frontend">{description}</p>
      )}
    </div>
  );
}
