import { useId, useState } from "react";
import { Button } from "../../components/ui/Button";
import { Input } from "../../components/ui/Input";
import {
  EyeIcon,
  EyeOffIcon,
  ShuffleIcon,
} from "../../components/layout/icons";
import { useClipboard } from "../../lib/useClipboard";
import { generatePassword, scorePassword } from "./password";

interface PasswordFieldProps {
  label: string;
  value: string;
  onChange: (next: string) => void;
  disabled?: boolean;
  /** Surface a server-side or validation error under the field. */
  error?: string;
  /**
   * Hint shown when the field is empty (e.g. "Leave blank to keep current" on
   * the edit form). Suppressed once the admin types.
   */
  emptyHint?: string;
}

/**
 * Password input with hygiene baked in:
 *  - type="password" with autoComplete="new-password" (never autofills or
 *    suggests the admin's own saved credentials),
 *  - a reveal toggle (off by default) so a generated value can be verified,
 *  - a "generate" action that fills a strong crypto-random value and copies it
 *    once, mirroring the cak_ key reveal discipline (copy now, it is not stored
 *    anywhere after the form closes),
 *  - an advisory strength meter (the server is the real policy authority).
 *
 * The value lives only in the parent's component state and is cleared on modal
 * close by the parent; it is never logged.
 */
export function PasswordField({
  label,
  value,
  onChange,
  disabled = false,
  error,
  emptyHint,
}: PasswordFieldProps) {
  const id = useId();
  const hintId = useId();
  const [revealed, setRevealed] = useState(false);
  const { copied, copy } = useClipboard();

  const strength = scorePassword(value);

  function handleGenerate() {
    const next = generatePassword(20);
    onChange(next);
    setRevealed(true);
    void copy(next);
  }

  const describedBy = error
    ? hintId
    : value || emptyHint
      ? hintId
      : undefined;

  return (
    <div className="field">
      <label className="field__label" htmlFor={id}>
        {label}
      </label>
      <div className="pwfield">
        <Input
          id={id}
          type={revealed ? "text" : "password"}
          value={value}
          onChange={(e) => onChange(e.target.value)}
          disabled={disabled}
          autoComplete="new-password"
          spellCheck={false}
          aria-invalid={error ? true : undefined}
          aria-describedby={describedBy}
          className="pwfield__input"
        />
        <div className="pwfield__actions">
          <button
            type="button"
            className="iconbtn"
            onClick={() => setRevealed((r) => !r)}
            disabled={disabled}
            aria-label={revealed ? "Hide password" : "Show password"}
            aria-pressed={revealed}
          >
            {revealed ? (
              <EyeOffIcon width={16} height={16} />
            ) : (
              <EyeIcon width={16} height={16} />
            )}
          </button>
          <Button
            type="button"
            variant="ghost"
            size="sm"
            onClick={handleGenerate}
            disabled={disabled}
          >
            <ShuffleIcon width={14} height={14} />
            {copied ? "Copied" : "Generate"}
          </Button>
        </div>
      </div>

      {error ? (
        <p className="pwfield__msg pwfield__msg--error" id={hintId} role="alert">
          {error}
        </p>
      ) : value ? (
        <div className="pwfield__strength" id={hintId}>
          <span
            className={`pwfield__bar pwfield__bar--${strength.level}`}
            aria-hidden="true"
          />
          <span className="pwfield__strengthtext">{strength.hint}</span>
        </div>
      ) : emptyHint ? (
        <p className="pwfield__msg" id={hintId}>
          {emptyHint}
        </p>
      ) : null}
    </div>
  );
}
