import { Machine, EventObject, Service } from '@zag-js/core';
import { PropTypes, RequiredBy, DirectionProperty, CommonProperties, Rect } from '@zag-js/types';

interface ValueChangeDetails {
    value: string | null;
}
type ElementIds = Partial<{
    root: string;
    label: string;
    indicator: string;
    item: (value: string) => string;
    itemLabel: (value: string) => string;
    itemControl: (value: string) => string;
    itemHiddenInput: (value: string) => string;
}>;
interface RadioGroupProps extends DirectionProperty, CommonProperties {
    /**
     * The ids of the elements in the radio. Useful for composition.
     */
    ids?: ElementIds | undefined;
    /**
     * The controlled value of the radio group
     */
    value?: string | null | undefined;
    /**
     * The initial value of the checked radio when rendered.
     * Use when you don't need to control the value of the radio group.
     */
    defaultValue?: string | null | undefined;
    /**
     * The name of the input fields in the radio
     * (Useful for form submission).
     */
    name?: string | undefined;
    /**
     * The associate form of the underlying input.
     */
    form?: string | undefined;
    /**
     * If `true`, the radio group will be disabled
     */
    disabled?: boolean | undefined;
    /**
     * If `true`, the radio group is marked as invalid.
     */
    invalid?: boolean | undefined;
    /**
     * If `true`, the radio group is marked as required.
     */
    required?: boolean | undefined;
    /**
     * Whether the radio group is read-only
     */
    readOnly?: boolean | undefined;
    /**
     * Function called once a radio is checked
     */
    onValueChange?: ((details: ValueChangeDetails) => void) | undefined;
    /**
     * Orientation of the radio group
     */
    orientation?: "horizontal" | "vertical" | undefined;
}
interface PrivateContext {
    /**
     * The value of the checked radio
     */
    value: string | null;
    /**
     * The id of the active radio
     */
    activeValue: string | null;
    /**
     * The id of the focused radio
     */
    focusedValue: string | null;
    /**
     * The id of the radio that has focus-visible
     */
    focusVisibleValue: string | null;
    /**
     * The id of the hovered radio
     */
    hoveredValue: string | null;
    /**
     * The active tab indicator's dom rect
     */
    indicatorRect: Rect | null;
    /**
     * Whether indicator transitions should be animated
     */
    animateIndicator: boolean;
    /**
     * Whether the radio group's fieldset is disabled
     */
    fieldsetDisabled: boolean;
    /**
     * Whether the radio group is in server-side rendering
     */
    ssr: boolean;
}
type PropsWithDefault = "orientation";
type ComputedContext = Readonly<{
    /**
     * Whether the radio group is disabled
     */
    isDisabled: boolean;
}>;
interface Refs {
    /**
     * Function to clean up the observer for the active tab's rect
     */
    indicatorCleanup: VoidFunction | null;
    /**
     * Previous selected value, used to detect real value transitions
     */
    prevValue: string | null;
}
interface RadioGroupSchema {
    state: "idle";
    props: RequiredBy<RadioGroupProps, PropsWithDefault>;
    context: PrivateContext;
    computed: ComputedContext;
    refs: Refs;
    event: EventObject;
    action: string;
    effect: string;
    guard: string;
}
type RadioGroupService = Service<RadioGroupSchema>;
type RadioGroupMachine = Machine<RadioGroupSchema>;
interface ItemProps {
    value: string;
    disabled?: boolean | undefined;
    invalid?: boolean | undefined;
}
interface ItemState {
    /**
     * The value of the item
     */
    value: string;
    /**
     * Whether the item is invalid
     */
    invalid: boolean;
    /**
     * Whether the item is disabled
     */
    disabled: boolean;
    /**
     * Whether the item is checked
     */
    checked: boolean;
    /**
     *  Whether the item is focused
     */
    focused: boolean;
    /**
     * Whether the item is focused and the focus is visible
     */
    focusVisible: boolean;
    /**
     * Whether the item is hovered
     */
    hovered: boolean;
    /**
     * Whether the item is active or pressed
     */
    active: boolean;
}
interface RadioGroupApi<T extends PropTypes = PropTypes> {
    /**
     * The current value of the radio group
     */
    value: string | null;
    /**
     * Function to set the value of the radio group
     */
    setValue: (value: string) => void;
    /**
     * Function to clear the value of the radio group
     */
    clearValue: VoidFunction;
    /**
     * Function to focus the radio group
     */
    focus: VoidFunction;
    /**
     * Returns the state details of a radio input
     */
    getItemState: (props: ItemProps) => ItemState;
    getRootProps: () => T["element"];
    getLabelProps: () => T["element"];
    getItemProps: (props: ItemProps) => T["label"];
    getItemTextProps: (props: ItemProps) => T["element"];
    getItemControlProps: (props: ItemProps) => T["element"];
    getItemHiddenInputProps: (props: ItemProps) => T["input"];
    getIndicatorProps: () => T["element"];
}

export type { ElementIds, ItemProps, ItemState, RadioGroupApi, RadioGroupMachine, RadioGroupProps, RadioGroupSchema, RadioGroupService, ValueChangeDetails };
