'use client';

import { useEffect, useRef, useState } from 'react';
import { Loader2, Pencil } from 'lucide-react';

import { toastError } from '@/lib/api/toast-error';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { cn } from '@/lib/utils';

interface SelectOption {
  value: string;
  label: string;
}

interface BaseProps {
  value: string | null | undefined;
  onSave: (next: string | null) => Promise<void>;
  placeholder?: string;
  emptyText?: string;
  className?: string;
  disabled?: boolean;
}

interface TextProps extends BaseProps {
  variant?: 'text';
}

interface SelectFieldProps extends BaseProps {
  variant: 'select';
  options: SelectOption[];
}

interface TextareaProps extends BaseProps {
  variant: 'textarea';
  rows?: number;
}

export type InlineEditableFieldProps = TextProps | SelectFieldProps | TextareaProps;

/**
 * Click-to-edit field used in detail panels. Shows the value as plain text
 * with a pencil affordance on hover; clicking swaps to an input that saves on
 * Enter/blur and cancels on Escape.
 */
export function InlineEditableField(props: InlineEditableFieldProps) {
  const { value, onSave, placeholder, emptyText = '-', className, disabled } = props;
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(value ?? '');
  const [saving, setSaving] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  useEffect(() => {
    setDraft(value ?? '');
  }, [value]);

  useEffect(() => {
    if (editing) {
      if (inputRef.current) {
        inputRef.current.focus();
        inputRef.current.select();
      } else if (textareaRef.current) {
        textareaRef.current.focus();
        textareaRef.current.select();
      }
    }
  }, [editing]);

  async function commit(nextRaw: string) {
    const trimmed = nextRaw.trim();
    if (trimmed === (value ?? '')) {
      setEditing(false);
      return;
    }
    setSaving(true);
    try {
      await onSave(trimmed === '' ? null : trimmed);
      setEditing(false);
    } catch (err) {
      toastError(err);
      setDraft(value ?? '');
    } finally {
      setSaving(false);
    }
  }

  function cancel() {
    setDraft(value ?? '');
    setEditing(false);
  }

  if (props.variant === 'select') {
    const labelFor = (v: string | null | undefined) =>
      v ? (props.options.find((o) => o.value === v)?.label ?? v) : null;

    if (!editing) {
      return (
        <ReadButton
          value={labelFor(value)}
          emptyText={emptyText}
          disabled={disabled}
          onClick={() => setEditing(true)}
          className={className}
        />
      );
    }

    return (
      <div className={cn('flex items-center gap-1', className)}>
        <Select
          value={draft}
          onValueChange={(v) => void commit(v)}
          open
          onOpenChange={(open) => {
            if (!open && !saving) setEditing(false);
          }}
        >
          <SelectTrigger className="h-7 text-sm w-full">
            <SelectValue placeholder={placeholder} />
          </SelectTrigger>
          <SelectContent>
            {props.options.map((o) => (
              <SelectItem key={o.value} value={o.value}>
                {o.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
        {saving && <Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />}
      </div>
    );
  }

  if (props.variant === 'textarea') {
    if (!editing) {
      return (
        <ReadButton
          value={value || null}
          emptyText={emptyText}
          disabled={disabled}
          onClick={() => setEditing(true)}
          multiline
          className={className}
        />
      );
    }

    return (
      <div className={cn('flex flex-col gap-1', className)}>
        <Textarea
          ref={textareaRef}
          value={draft}
          onChange={(e) => setDraft(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === 'Escape') {
              e.preventDefault();
              cancel();
            }
            if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
              e.preventDefault();
              void commit(draft);
            }
          }}
          onBlur={() => {
            if (!saving) void commit(draft);
          }}
          placeholder={placeholder}
          disabled={saving}
          rows={props.rows ?? 4}
          className="text-sm"
        />
        {saving && <Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />}
      </div>
    );
  }

  if (!editing) {
    return (
      <ReadButton
        value={value || null}
        emptyText={emptyText}
        disabled={disabled}
        onClick={() => setEditing(true)}
        className={className}
      />
    );
  }

  return (
    <div className={cn('flex items-center gap-1', className)}>
      <Input
        ref={inputRef}
        value={draft}
        onChange={(e) => setDraft(e.target.value)}
        onKeyDown={(e) => {
          if (e.key === 'Enter') {
            e.preventDefault();
            void commit(draft);
          }
          if (e.key === 'Escape') {
            e.preventDefault();
            cancel();
          }
        }}
        onBlur={() => {
          if (!saving) void commit(draft);
        }}
        placeholder={placeholder}
        disabled={saving}
        className="h-7 text-sm"
      />
      {saving && <Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />}
    </div>
  );
}

function ReadButton({
  value,
  emptyText,
  disabled,
  onClick,
  multiline,
  className,
}: {
  value: string | null;
  emptyText: string;
  disabled?: boolean;
  onClick: () => void;
  multiline?: boolean;
  className?: string;
}) {
  return (
    <button
      type="button"
      disabled={disabled}
      onClick={onClick}
      className={cn(
        'group rounded px-1 -mx-1 py-0.5 text-left text-sm',
        multiline ? 'flex w-full items-start gap-1.5' : 'inline-flex items-center gap-1.5',
        'hover:bg-muted/60 focus-visible:bg-muted/60 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
        disabled && 'cursor-not-allowed opacity-60 hover:bg-transparent',
        className,
      )}
    >
      <span
        className={cn(
          'flex-1',
          multiline && 'whitespace-pre-wrap',
          !value && 'text-muted-foreground',
        )}
      >
        {value ?? emptyText}
      </span>
      {!disabled && (
        <Pencil
          className={cn(
            // Show the pencil faintly at rest so users discover the field is
            // editable without having to hover-and-test every label.
            'h-3 w-3 opacity-20 transition-opacity group-hover:opacity-60',
            multiline && 'mt-1 shrink-0',
          )}
        />
      )}
    </button>
  );
}
