"use client";

import clsx from "clsx";
import {
  Control,
  FieldPath,
  FieldValues,
  useController,
} from "react-hook-form";

interface ToggleProps<T extends FieldValues = FieldValues> {
  checked?: boolean;
  onChange?: (value: boolean) => void;

  control?: Control<T>;
  name?: FieldPath<T>;

  label?: string;
  description?: string;

  disabled?: boolean;

  size?: "sm" | "md" | "lg";

  activeColor?: string;
  inactiveColor?: string;

  className?: string;
  error?: string;
}

export default function Toggle<T extends FieldValues = FieldValues>({
  checked,
  onChange,
  control,
  name,
  label,
  description,
  disabled = false,
  size = "md",
  activeColor = "bg-link-1",
  inactiveColor = "bg-link-1/10",
  className = "",
  error,
}: ToggleProps<T>) {
  const controller =
    control && name
      ? useController({
          control,
          name,
        })
      : null;

  const value = controller?.field.value ?? checked ?? false;

  const handleChange = (newValue: boolean) => {
    controller?.field.onChange(newValue);
    onChange?.(newValue);
  };

  const sizes = {
    sm: {
      track: "h-5 w-9",
      thumb: "h-3.5 w-3.5",
      on: "translate-x-4",
      off: "translate-x-0",
    },
    md: {
      track: "h-7 w-12",
      thumb: "h-5 w-5",
      on: "translate-x-5",
      off: "translate-x-0",
    },
    lg: {
      track: "h-8 w-14",
      thumb: "h-6 w-6",
      on: "translate-x-6",
      off: "translate-x-0",
    },
  };

  const current = sizes[size];

  return (
    <div>
      <div
        className={clsx("flex items-center justify-between gap-4", className)}
      >
        {(label || description) && (
          <div>
            {label && <h4 className="font-medium text-heading">{label}</h4>}

            {description && (
              <p className="mt-1 text-sm text-gray-500">{description}</p>
            )}
          </div>
        )}

        <button
          type="button"
          role="switch"
          aria-checked={value}
          disabled={disabled}
          onClick={() => !disabled && handleChange(!value)}
          className={clsx(
            "relative shrink-0 rounded-full transition-all duration-300",
            current.track,
            value ? activeColor : inactiveColor,
            disabled && "cursor-not-allowed opacity-50",
          )}
        >
          <span
            className={clsx(
              "absolute left-1 top-1 rounded-full bg-white shadow-sm transition-transform duration-300",
              current.thumb,
              value ? current.on : current.off,
            )}
          />
        </button>
      </div>
      {error && <span className="text-xs text-danger">{error}</span>}
    </div>
  );
}
