"use client";

import {mergeProps} from "@base-ui/react/merge-props";
import {Meter as BaseMeter} from "@base-ui/react/meter";
import {useRender} from "@base-ui/react/use-render";
import * as React from "react";

import {cn} from "@/lib/utilities";
import styles from "./meter.module.css";

/**
 * Displays a scalar measurement within a known range.
 *
 * @remarks
 * - Renders a `<div>` element by default
 * - Built on Base UI Meter primitives
 * - Intended for values such as storage usage, health, or completion
 *
 * @example
 * ```tsx
 * <Meter value={72}>
 *   <MeterTrack>
 *     <MeterIndicator />
 *   </MeterTrack>
 * </Meter>
 * ```
 *
 * @see {@link https://base-ui.com/react/components/meter | Base UI Meter Docs}
 */
const Meter = React.forwardRef<HTMLDivElement, Meter.Props>((props, forwardedRef) => {
  const {className, children, render, ...otherProps} = props;

  return (
    <BaseMeter.Root
      {...otherProps}
      ref={forwardedRef}
      render={useRender({
        defaultTagName: "div",
        render: render as never,
        props: mergeProps({className: cn(styles.root, className)}, {}),
      })}>
      {children}
    </BaseMeter.Root>
  );
});

/**
 * Renders the background track for a meter.
 *
 * @remarks
 * - Renders a `<div>` element by default
 * - Built on Base UI Meter track primitives
 *
 * @example
 * ```tsx
 * <MeterTrack />
 * ```
 *
 * @see {@link https://base-ui.com/react/components/meter | Base UI Meter Docs}
 */
const MeterTrack = React.forwardRef<HTMLDivElement, MeterTrack.Props>((props, forwardedRef) => {
  const {className, children, render, ...otherProps} = props;

  return (
    <BaseMeter.Track
      {...otherProps}
      ref={forwardedRef}
      render={useRender({
        defaultTagName: "div",
        render: render as never,
        props: mergeProps({className: cn(styles.track, className)}, {}),
      })}>
      {children}
    </BaseMeter.Track>
  );
});

/**
 * Renders the filled indicator that reflects the current meter value.
 *
 * @remarks
 * - Renders a `<div>` element by default
 * - Built on Base UI Meter indicator primitives
 *
 * @example
 * ```tsx
 * <MeterIndicator />
 * ```
 *
 * @see {@link https://base-ui.com/react/components/meter | Base UI Meter Docs}
 */
const MeterIndicator = React.forwardRef<HTMLDivElement, MeterIndicator.Props>((props, forwardedRef) => {
  const {className, children, render, ...otherProps} = props;

  return (
    <BaseMeter.Indicator
      {...otherProps}
      ref={forwardedRef}
      render={useRender({
        defaultTagName: "div",
        render: render as never,
        props: mergeProps({className: cn(styles.indicator, className)}, {}),
      })}>
      {children}
    </BaseMeter.Indicator>
  );
});

/**
 * Renders the accessible label associated with a meter.
 *
 * @remarks
 * - Renders a `<span>` element by default
 * - Built on Base UI Meter label primitives
 *
 * @example
 * ```tsx
 * <MeterLabel>Storage used</MeterLabel>
 * ```
 *
 * @see {@link https://base-ui.com/react/components/meter | Base UI Meter Docs}
 */
const MeterLabel = React.forwardRef<HTMLSpanElement, MeterLabel.Props>((props, forwardedRef) => {
  const {className, children, render, ...otherProps} = props;

  return (
    <BaseMeter.Label
      {...otherProps}
      ref={forwardedRef}
      render={useRender({
        defaultTagName: "span",
        render: render as never,
        props: mergeProps({className: cn(styles.label, className)}, {}),
      })}>
      {children}
    </BaseMeter.Label>
  );
});

// eslint-disable-next-line no-redeclare -- required for the canonical component namespace typing API
namespace Meter {
  export type Props = React.ComponentPropsWithRef<typeof BaseMeter.Root>;
  export type State = BaseMeter.Root.State;
}

// eslint-disable-next-line no-redeclare -- required for the canonical component namespace typing API
namespace MeterTrack {
  export type Props = React.ComponentPropsWithRef<typeof BaseMeter.Track>;
  export type State = BaseMeter.Track.State;
}

// eslint-disable-next-line no-redeclare -- required for the canonical component namespace typing API
namespace MeterIndicator {
  export type Props = React.ComponentPropsWithRef<typeof BaseMeter.Indicator>;
  export type State = BaseMeter.Indicator.State;
}

// eslint-disable-next-line no-redeclare -- required for the canonical component namespace typing API
namespace MeterLabel {
  export type Props = React.ComponentPropsWithRef<typeof BaseMeter.Label>;
  export type State = BaseMeter.Label.State;
}

Meter.displayName = "Meter";
MeterTrack.displayName = "MeterTrack";
MeterIndicator.displayName = "MeterIndicator";
MeterLabel.displayName = "MeterLabel";

export {Meter, MeterIndicator, MeterLabel, MeterTrack};
