import * as passwordInputMachine from "@zag-js/password-input";
import type { MachineInput } from "marko-zag";
import Icon from "../icon/icon.marko";
import { cn } from "#lib/utils.ts";
import { stripOwnProps } from "#lib/native-attrs.ts";
import { passwordInput as styles } from "./classes.ts";

export type Input = MachineInput<"input", passwordInputMachine.Props> & {
  visibleChange?: (visible: boolean) => void;
  label?: string;
};

<zag/api=() => passwordInputMachine from=input
  onVisibilityChange(details: passwordInputMachine.VisibilityChangeDetails) {
    input.onVisibilityChange?.(details);
    input.visibleChange?.(details.visible);
  }
/>

<const/nativeAttrs=() =>
  stripOwnProps(
    passwordInputMachine.splitProps(input)[1],
    "class",
    "visibleChange",
    "label",
  )
>

// Zag emits React-style camelCase `autoCapitalize` from getInputProps, which
// ships as a literal inert attribute (and is disallowed on type=password,
// html-validate input-attributes). Strip it; Marko does not dedupe spread
// attrs.
<const/inputProps=() => {
  const { autoCapitalize, ...machineProps } = api().getInputProps() as Record<string, unknown>;
  return { ...nativeAttrs(), ...machineProps };
}/>

<div ...api().getRootProps() data-slot="password-input-root" class=styles.root>
  <if=input.label>
    <label ...api().getLabelProps() data-slot="password-input-label" class=styles.label>
      ${input.label}
    </label>
  </if>
  <div ...api().getControlProps() data-slot="password-input-control" class=styles.control>
    <input type="text"
      ...inputProps()
      data-slot="password-input"
      class=cn(styles.input, styles.inputFocus, styles.inputInvalid, input.class)
    />
    <button type="button"
      ...api().getVisibilityTriggerProps()
      data-slot="password-input-visibility-trigger"
      class=styles.visibilityTrigger
    >
      <span ...api().getIndicatorProps() data-slot="password-input-indicator">
        // Sizing stays on the parent button's `[&_svg]:size-4`, matching the
        // markup these two replaced (bare <svg>, no class of its own) —
        // <Icon>'s own default `size-4` agrees with it either way.
        <if=api().visible>
          <Icon name="EyeOffIcon"/>
        </if>
        <else>
          <Icon name="EyeIcon"/>
        </else>
      </span>
      <span class=styles.srOnly>${api().visible ? "Hide password" : "Show password"}</span>
    </button>
  </div>
</div>

<return=api>
