"use client";

import * as React from "react";
import { ChevronDown } from "lucide-react";

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";

export type TableFieldType =
  | "title"
  | "text"
  | "status"
  | "priority"
  | "date"
  | "select"
  | "assignees"
  | "created";

export interface TableCellProps {
  value: unknown;
  fieldType: TableFieldType;
  onChange?: (value: unknown) => void;
  readOnly?: boolean;
  className?: string;
  /** Options for status, priority, or custom select columns */
  selectOptions?: string[];
  /** Optional: move focus to next/previous cell (Tab / Shift+Tab) */
  onNavigate?: (dir: "next" | "prev") => void;
}

function formatDateDisplay(raw: string): string {
  if (!raw || raw === "—") return "—";
  try {
    const d = new Date(raw);
    if (Number.isNaN(d.getTime())) return raw;
    return d.toLocaleDateString(undefined, {
      month: "short",
      day: "numeric",
      year: "numeric",
    });
  } catch {
    return raw;
  }
}

function formatCreatedDisplay(raw: string): string {
  if (!raw) return "—";
  try {
    const d = new Date(raw);
    if (Number.isNaN(d.getTime())) return raw;
    return d.toLocaleString(undefined, {
      month: "short",
      day: "numeric",
      year: "numeric",
      hour: "numeric",
      minute: "2-digit",
    });
  } catch {
    return String(raw);
  }
}

function statusLabel(status: string | null): string {
  if (!status) return "—";
  return String(status).replace(/_/g, " ");
}

function initials(name: string | null): string {
  return (name ?? "?")
    .split(/\s+/)
    .map((p) => p[0])
    .join("")
    .slice(0, 2)
    .toUpperCase();
}

type AssigneeLike = { user: { id: string; name: string | null; avatarUrl: string | null } };

function isAssigneeArray(v: unknown): v is AssigneeLike[] {
  return Array.isArray(v) && v.every((x) => x && typeof x === "object" && "user" in x);
}

export function TableCell({
  value,
  fieldType,
  onChange,
  readOnly = false,
  className,
  selectOptions = [],
  onNavigate,
}: TableCellProps) {
  const [editing, setEditing] = React.useState(false);
  const [draft, setDraft] = React.useState("");
  const inputRef = React.useRef<HTMLInputElement>(null);

  const stringValue = React.useMemo(() => {
    if (value === null || value === undefined) return "";
    if (typeof value === "string") return value;
    return String(value);
  }, [value]);

  React.useEffect(() => {
    if (!editing) return;
    if (fieldType === "date") {
      const raw = stringValue;
      if (raw && raw !== "—") {
        const d = new Date(raw);
        if (!Number.isNaN(d.getTime())) {
          setDraft(d.toISOString().slice(0, 10));
          return;
        }
      }
      setDraft("");
      return;
    }
    setDraft(stringValue);
  }, [editing, fieldType, stringValue]);

  React.useEffect(() => {
    if (editing && fieldType !== "assignees" && fieldType !== "created") {
      const id = requestAnimationFrame(() => inputRef.current?.focus());
      return () => cancelAnimationFrame(id);
    }
  }, [editing, fieldType]);

  const commit = React.useCallback(() => {
    if (!onChange) {
      setEditing(false);
      return;
    }
    if (fieldType === "date") {
      onChange(draft || null);
    } else if (fieldType === "title" || fieldType === "text" || fieldType === "select") {
      onChange(draft);
    } else if (fieldType === "status" || fieldType === "priority") {
      onChange(draft);
    }
    setEditing(false);
  }, [draft, fieldType, onChange]);

  const cancel = React.useCallback(() => {
    setEditing(false);
  }, []);

  const startEdit = React.useCallback(() => {
    if (readOnly || fieldType === "assignees") return;
    if (fieldType === "created") return;
    if (fieldType === "status" || fieldType === "priority" || fieldType === "select") return;
    setEditing(true);
  }, [readOnly, fieldType]);

  const onKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Enter") {
      e.preventDefault();
      commit();
    } else if (e.key === "Escape") {
      e.preventDefault();
      cancel();
    } else if (e.key === "Tab" && onNavigate) {
      e.preventDefault();
      commit();
      onNavigate(e.shiftKey ? "prev" : "next");
    }
  };

  const displayNode = (() => {
    if (fieldType === "assignees" && isAssigneeArray(value)) {
      const list = value;
      if (list.length === 0) {
        return <span className="text-muted-foreground">—</span>;
      }
      return (
        <div className="flex min-w-0 -space-x-1.5 overflow-hidden">
          {list.slice(0, 4).map((a) => (
            <Avatar
              key={a.user.id}
              className="h-6 w-6 border-2 border-background text-[10px]"
            >
              <AvatarImage src={a.user.avatarUrl ?? undefined} alt="" />
              <AvatarFallback className="text-[9px]">{initials(a.user.name)}</AvatarFallback>
            </Avatar>
          ))}
        </div>
      );
    }

    if (fieldType === "status") {
      const s = typeof value === "string" ? value : value === null ? null : String(value);
      return (
        <Badge variant="muted" className="max-w-full truncate px-1.5 py-0 text-[11px] font-medium capitalize">
          {statusLabel(s)}
        </Badge>
      );
    }

    if (fieldType === "priority") {
      return (
        <Badge variant="muted" className="max-w-full truncate px-1.5 py-0 text-[11px] font-medium">
          {stringValue || "—"}
        </Badge>
      );
    }

    if (fieldType === "date") {
      return (
        <span className="tabular-nums text-muted-foreground">{formatDateDisplay(stringValue || "—")}</span>
      );
    }

    if (fieldType === "created") {
      return (
        <span className="tabular-nums text-muted-foreground">
          {formatCreatedDisplay(stringValue)}
        </span>
      );
    }

    return (
      <span className="min-w-0 truncate text-sm text-foreground">{stringValue || "—"}</span>
    );
  })();

  if (readOnly || fieldType === "assignees" || fieldType === "created") {
    return (
      <div
        className={cn(
          "flex h-9 min-h-9 max-h-9 items-center px-2 text-sm",
          className,
        )}
      >
        {displayNode}
      </div>
    );
  }

  if (fieldType === "status" || fieldType === "priority" || fieldType === "select") {
    const opts =
      fieldType === "status"
        ? ["open", "in_progress", "done", "closed"]
        : fieldType === "priority"
          ? ["High", "Medium", "Low"]
          : selectOptions;

    return (
      <div className={cn("flex h-9 min-h-9 max-h-9 items-stretch px-1", className)}>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <button
              type="button"
              className="flex h-9 min-h-9 w-full min-w-0 items-center justify-between gap-1 rounded-sm px-2 text-left text-sm outline-none transition-colors hover:bg-accent/50 focus-visible:ring-2 focus-visible:ring-ring"
            >
              <span className="min-w-0 flex-1">{displayNode}</span>
              <ChevronDown className="h-3 w-3 shrink-0 opacity-40" aria-hidden />
            </button>
          </DropdownMenuTrigger>
          <DropdownMenuContent className="min-w-[8rem]" align="start">
            {opts.map((opt) => (
              <DropdownMenuItem
                key={opt}
                className="text-xs"
                onSelect={() => onChange?.(opt)}
              >
                {fieldType === "status" ? statusLabel(opt) : opt}
              </DropdownMenuItem>
            ))}
          </DropdownMenuContent>
        </DropdownMenu>
      </div>
    );
  }

  if (fieldType === "date") {
    if (editing) {
      return (
        <div className={cn("flex h-9 items-center px-1", className)}>
          <Input
            ref={inputRef}
            type="date"
            value={draft}
            onChange={(e) => setDraft(e.target.value)}
            onBlur={commit}
            onKeyDown={onKeyDown}
            className="h-7 border-0 bg-transparent px-2 py-0 text-xs shadow-none focus-visible:ring-1"
          />
        </div>
      );
    }
    return (
      <button
        type="button"
        onClick={startEdit}
        className={cn(
          "flex h-9 w-full min-w-0 items-center rounded-sm px-2 text-left outline-none transition-colors hover:bg-accent/50 focus-visible:ring-2 focus-visible:ring-ring",
          className,
        )}
      >
        {displayNode}
      </button>
    );
  }

  if (editing) {
    return (
      <div className={cn("flex h-9 items-center px-1", className)}>
        <Input
          ref={inputRef}
          value={draft}
          onChange={(e) => setDraft(e.target.value)}
          onBlur={commit}
          onKeyDown={onKeyDown}
          className="h-7 border-0 bg-transparent px-2 py-0 text-sm shadow-none focus-visible:ring-1"
        />
      </div>
    );
  }

  return (
    <button
      type="button"
      onClick={startEdit}
      className={cn(
        "flex h-9 w-full min-w-0 items-center rounded-sm px-2 text-left outline-none transition-colors hover:bg-accent/50 focus-visible:ring-2 focus-visible:ring-ring",
        className,
      )}
    >
      {displayNode}
    </button>
  );
}
