import {
  Field,
  FieldDescription,
  FieldError,
  FormControl,
  RadioGroup,
  RadioGroupItem,
} from "@repo/shadcn-ui/components";
import { cn } from "@repo/shadcn-ui/lib/utils";
import * as React from "react";
import { Controller, type FieldPath, type FieldValues, useFormContext } from "react-hook-form";

import { FormFieldLabel } from "./form-field-label.tsx";

export interface RadioGroupFieldItem {
  value: string;
  label: string;
  description?: string;
  disabled?: boolean;
}

type RadioGroupFieldProps<TFormValues extends FieldValues> = {
  name: FieldPath<TFormValues>;
  items: RadioGroupFieldItem[];

  label?: string;
  description?: string;

  disabled?: boolean;
  required?: boolean;
  readOnly?: boolean;

  orientation?: "vertical" | "horizontal" | "responsive";

  className?: string;
  inputClassName?: string;
  itemClassName?: string;
};

export const RadioGroupField = <TFormValues extends FieldValues>({
  name,
  items,
  label,
  description,
  disabled = false,
  required = false,
  readOnly = false,
  orientation = "vertical",
  className,
  inputClassName,
  itemClassName,
}: RadioGroupFieldProps<TFormValues>) => {
  const baseId = React.useId();
  const { control, formState } = useFormContext<TFormValues>();

  const isDisabled = Boolean(disabled || readOnly || formState.isSubmitting);

  return (
    <Controller
      control={control}
      name={name}
      render={({ field, fieldState }) => (
        <Field
          className={cn("gap-1", className)}
          data-invalid={fieldState.invalid}
          orientation={orientation}
        >
          {label ? (
            <FormFieldLabel
              htmlFor={`${baseId}-${items[0]?.value ?? "option"}`}
              required={required}
            >
              {label}
            </FormFieldLabel>
          ) : null}

          <FormControl>
            <RadioGroup
              className={cn(
                "gap-3",
                orientation === "horizontal" && "flex flex-row flex-wrap items-center gap-6",
                orientation === "responsive" &&
                  "flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center sm:gap-6",
                inputClassName
              )}
              disabled={isDisabled}
              name={field.name}
              onValueChange={field.onChange}
              value={field.value ?? ""}
            >
              {items.map((item, index) => {
                const itemId = `${baseId}-${index}-${item.value}`;
                const itemDisabled = Boolean(isDisabled || item.disabled);

                return (
                  <div className={cn("flex items-start gap-2", itemClassName)} key={item.value}>
                    <RadioGroupItem
                      aria-invalid={fieldState.invalid}
                      aria-required={required || undefined}
                      className="mt-0.5"
                      disabled={itemDisabled}
                      id={itemId}
                      onBlur={field.onBlur}
                      value={item.value}
                    />

                    <div className="grid gap-0.5">
                      <label
                        className={cn(
                          "cursor-pointer text-sm font-medium leading-none",
                          itemDisabled && "cursor-not-allowed opacity-70"
                        )}
                        htmlFor={itemId}
                      >
                        {item.label}
                      </label>

                      {item.description ? (
                        <p className="text-muted-foreground text-sm">{item.description}</p>
                      ) : null}
                    </div>
                  </div>
                );
              })}
            </RadioGroup>
          </FormControl>

          {description ? (
            <FieldDescription>{description}</FieldDescription>
          ) : (
            <div aria-hidden="true" className="min-h-5" />
          )}

          <FieldError errors={[fieldState.error]} />
        </Field>
      )}
    />
  );
};
