"use client";

import { useEffect, useRef, useState, useTransition } from "react";

type EditableCellProps = {
  value: string;
  onSave: (next: string) => Promise<{ ok: boolean; error?: string }>;
  label?: string;
  isCurrentlyEditing?: boolean;
  onEditStart?: () => void;
  onEditEnd?: () => void;
  /**
   * Override how the value is rendered in view mode. Use this to show
   * something other than plain text (e.g., a status pill) — clicking
   * the rendered element still starts edit mode.
   */
  renderView?: (value: string) => React.ReactNode;
};

export default function EditableCell({
  value,
  onSave,
  label,
  isCurrentlyEditing,
  onEditStart,
  onEditEnd,
  renderView,
}: EditableCellProps) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(value);
  const [error, setError] = useState<string | null>(null);
  const [isPending, startTransition] = useTransition();
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (!editing) setDraft(value);
  }, [value, editing]);

  useEffect(() => {
    if (!error) return;
    const id = setTimeout(() => setError(null), 3000);
    return () => clearTimeout(id);
  }, [error]);

  function begin() {
    setDraft(value);
    setEditing(true);
    onEditStart?.();
    requestAnimationFrame(() => {
      inputRef.current?.focus();
      inputRef.current?.select();
    });
  }

  function cancel() {
    setEditing(false);
    setDraft(value);
    setError(null);
    onEditEnd?.();
  }

  function commit() {
    if (draft === value) {
      cancel();
      return;
    }
    startTransition(async () => {
      const result = await onSave(draft);
      if (result.ok) {
        setEditing(false);
        setError(null);
        onEditEnd?.();
      } else {
        setError(result.error ?? "Save failed");
      }
    });
  }

  if (!editing) {
    return (
      <button
        type="button"
        onClick={begin}
        aria-label={label ? `Edit ${label}` : undefined}
        className="group flex w-full min-w-0 items-center gap-2 -mx-2 rounded-md px-2 py-1 text-left font-mono text-[13px] text-zinc-900 transition-colors hover:bg-zinc-100/70 focus:outline-none focus-visible:ring-2 focus-visible:ring-zinc-900"
      >
        <span className="min-w-0 flex-1 break-all">
          {renderView
            ? renderView(value)
            : value || <em className="not-italic text-zinc-400">—</em>}
        </span>
        <span
          aria-hidden="true"
          className="hidden shrink-0 self-center text-[10px] font-medium uppercase tracking-wider text-zinc-400 group-hover:inline"
        >
          edit
        </span>
      </button>
    );
  }

  return (
    <div className="flex flex-col gap-1">
      <div className="flex items-center gap-1.5">
        <input
          ref={inputRef}
          value={draft}
          onChange={(e) => setDraft(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter") {
              e.preventDefault();
              commit();
            } else if (e.key === "Escape") {
              e.preventDefault();
              cancel();
            }
          }}
          disabled={isPending}
          className="w-full min-w-0 rounded-md border-0 bg-zinc-100 px-2 py-1 font-mono text-base text-zinc-900 outline-none ring-1 ring-zinc-300 focus:bg-white focus:ring-2 focus:ring-zinc-900 disabled:opacity-60 sm:text-[13px]"
        />
        <button
          type="button"
          onClick={commit}
          disabled={isPending}
          aria-label="Save"
          className="shrink-0 rounded-md bg-zinc-900 px-2.5 py-1 text-[11px] font-medium text-white transition-colors hover:bg-zinc-700 disabled:opacity-60"
        >
          {isPending ? "…" : "Save"}
        </button>
        <button
          type="button"
          onClick={cancel}
          disabled={isPending}
          aria-label="Cancel"
          className="shrink-0 rounded-md px-2.5 py-1 text-[11px] font-medium text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-900 disabled:opacity-60"
        >
          Cancel
        </button>
      </div>
      {error && (
        <p className="font-mono text-[11px] text-red-600" role="alert">
          {error}
        </p>
      )}
    </div>
  );
}
