import React, { useRef, useState } from "react";
import { format, parseISO } from "date-fns";
import { Pencil } from "lucide-react";
import { cn } from "@/lib/utils";
import { Input } from "./input";
import { DatePicker } from "./date-picker";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "./select";

/**
 * EditableTextField — shadcn/WealthX
 *
 * A single inline-editable value. Display mode shows the formatted value with a pencil affordance
 * (revealed on hover); activating it switches to an editor. Committing (blur / Enter for text,
 * selection for select/date) calls `onSave`; Escape cancels.
 *
 * Atom. Pure & controlled — no auto-save timers, no API. The parent owns the value and persistence.
 * Three editors via `variant`: "text" (Input), "select" (Select), "date" (DatePicker).
 *
 * NOTE: distinct from `EditableMoneyItem`, which is a money-specific row (swatch + currency + slider).
 */
export interface EditableTextFieldOption {
  value: string;
  label: string;
}

export interface EditableTextFieldProps {
  /** Accessible name — required, the field renders no visible label of its own. */
  ariaLabel: string;
  /** Current committed value, in string form (ISO `yyyy-MM-dd` for variant="date"). */
  value: string;
  /** Called with the new value when an edit is committed. */
  onSave: (value: string) => void;
  /** Editor kind. Default "text". */
  variant?: "text" | "select" | "date";
  /** Options for variant="select". */
  options?: EditableTextFieldOption[];
  /** Input type for variant="text" (e.g. "email", "tel"). */
  inputType?: React.HTMLInputTypeAttribute;
  placeholder?: string;
  /** Format the committed value for display (e.g. a date, a masked number). */
  formatDisplay?: (value: string) => string;
  /** Shown in display mode when `value` is empty. Default "—". */
  emptyLabel?: string;
  disabled?: boolean;
  className?: string;
}

export function EditableTextField({
  ariaLabel,
  value,
  onSave,
  variant = "text",
  options = [],
  inputType = "text",
  placeholder,
  formatDisplay,
  emptyLabel = "—",
  disabled,
  className,
}: EditableTextFieldProps) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(value);
  const inputRef = useRef<HTMLInputElement>(null);

  const startEditing = () => {
    if (disabled) return;
    setDraft(value);
    setEditing(true);
    setTimeout(() => inputRef.current?.select(), 0);
  };

  const commit = (next: string) => {
    onSave(next);
    setEditing(false);
  };

  const displayText = value
    ? variant === "select"
      ? (options.find((o) => o.value === value)?.label ?? value)
      : (formatDisplay?.(value) ?? value)
    : "";

  // ── Edit mode ───────────────────────────────────────────────────────────────
  if (editing && !disabled) {
    if (variant === "select") {
      return (
        <Select
          value={value}
          onValueChange={(next) => commit(next ?? "")}
          items={options.map((o) => ({ value: o.value, label: o.label }))}
          onOpenChange={(open) => {
            if (!open) setEditing(false);
          }}
        >
          <SelectTrigger
            aria-label={ariaLabel}
            className={cn("h-9", className)}
          >
            <SelectValue placeholder={placeholder ?? "Select…"} />
          </SelectTrigger>
          <SelectContent>
            {options.map((o) => (
              <SelectItem key={o.value} value={o.value}>
                {o.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      );
    }

    if (variant === "date") {
      return (
        <DatePicker
          value={value ? parseISO(value) : undefined}
          placeholder={placeholder}
          onChange={(date) => {
            // Local-date formatting (not toISOString, which is UTC and can shift the day).
            commit(date ? format(date, "yyyy-MM-dd") : "");
          }}
        />
      );
    }

    return (
      <Input
        ref={inputRef}
        autoFocus
        type={inputType}
        aria-label={ariaLabel}
        placeholder={placeholder}
        value={draft}
        onChange={(e) => setDraft(e.target.value)}
        onBlur={() => commit(draft)}
        onKeyDown={(e) => {
          if (e.key === "Enter") commit(draft);
          if (e.key === "Escape") setEditing(false);
        }}
        className={cn("h-9", className)}
      />
    );
  }

  // ── Display mode ──────────────────────────────────────────────────────────────
  return (
    <div
      className={cn(
        "group flex h-9 items-center justify-between gap-2",
        className,
      )}
    >
      <button
        type="button"
        disabled={disabled}
        onClick={startEditing}
        aria-label={`Edit ${ariaLabel}`}
        className={cn(
          "min-w-0 truncate text-left text-body-medium text-foreground",
          !disabled && "cursor-text hover:text-primary",
          !value && "text-muted-foreground",
        )}
      >
        {displayText || emptyLabel}
      </button>
      <button
        type="button"
        tabIndex={-1}
        aria-hidden
        disabled={disabled}
        onClick={startEditing}
        className={cn(
          "shrink-0 p-1 text-muted-foreground transition-opacity hover:text-foreground",
          "opacity-0 group-hover:opacity-100",
          disabled && "invisible pointer-events-none",
        )}
      >
        <Pencil size={14} />
      </button>
    </div>
  );
}
