"use client";

import * as React from "react";
import { useParams } from "next/navigation";
import {
  ArrowDown,
  ArrowUp,
  ArrowUpDown,
  Plus,
} from "lucide-react";

import { ScrollArea } from "@/components/ui/scroll-area";
import {
  getDueDateValue,
  getPriorityValue,
} from "@/components/views/list/list-item";
import type { ViewConfig, ViewObject, ViewSort } from "@/lib/hooks/use-view-data";
import { useViewData } from "@/lib/hooks/use-view-data";
import { api } from "@/lib/trpc";
import { usePanelStore } from "@/lib/stores/panel-store";
import { cn } from "@/lib/utils";

import { TableCell, type TableFieldType } from "./table-cell";

type SortField =
  | "title"
  | "status"
  | "priority"
  | "dueDate"
  | "assignees"
  | "createdAt"
  | string;

const CHECKBOX_W = 36;
const DEFAULT_COL_WIDTHS: Record<string, number> = {
  select: CHECKBOX_W,
  title: 280,
  status: 128,
  priority: 104,
  assignees: 148,
  dueDate: 120,
  created: 132,
};

function collectCustomColumns(items: ViewObject[]) {
  const map = new Map<string, { id: string; name: string; fieldType: string }>();
  for (const o of items) {
    for (const pv of o.propertyValues ?? []) {
      const def = pv.propertyDefinition;
      if (def.name === "Priority" || def.name === "Due Date") continue;
      if (!map.has(def.id)) map.set(def.id, def);
    }
  }
  return Array.from(map.values());
}

function getPropertyValue(obj: ViewObject, propId: string): unknown {
  return obj.propertyValues?.find((p) => p.propertyDefinition.id === propId)?.value;
}

function mapCustomFieldType(ft: string): TableFieldType {
  if (ft === "select") return "select";
  if (ft === "date") return "date";
  return "text";
}

function rankPriority(p: string): number {
  const order = ["High", "Medium", "Low"];
  const i = order.indexOf(p);
  return i === -1 ? 999 : i;
}

function firstAssigneeName(o: ViewObject): string {
  return o.assignees?.[0]?.user?.name ?? "";
}

function compareIsoDate(a: string, b: string): number {
  const ta = new Date(a).getTime();
  const tb = new Date(b).getTime();
  if (Number.isNaN(ta) || Number.isNaN(tb)) return a.localeCompare(b);
  return ta - tb;
}

function compareDue(a: string, b: string): number {
  if (a === "—" && b === "—") return 0;
  if (a === "—") return 1;
  if (b === "—") return -1;
  return compareIsoDate(a, b);
}

function sortItemsByField(items: ViewObject[], sort: ViewSort): ViewObject[] {
  const dir = sort.direction === "asc" ? 1 : -1;
  const copy = [...items];
  copy.sort((a, b) => {
    let cmp = 0;
    if (sort.field.startsWith("prop:")) {
      const pid = sort.field.slice("prop:".length);
      const va = getPropertyValue(a, pid);
      const vb = getPropertyValue(b, pid);
      cmp = String(va ?? "").localeCompare(String(vb ?? ""));
    } else {
      switch (sort.field) {
        case "priority": {
          const pa = getPriorityValue(a);
          const pb = getPriorityValue(b);
          cmp = rankPriority(pa) - rankPriority(pb);
          if (cmp === 0) cmp = pa.localeCompare(pb);
          break;
        }
        case "dueDate":
          cmp = compareDue(getDueDateValue(a), getDueDateValue(b));
          break;
        case "assignees":
          cmp = firstAssigneeName(a).localeCompare(firstAssigneeName(b));
          break;
        case "title":
          cmp = a.title.localeCompare(b.title);
          break;
        case "status":
          cmp = String(a.status ?? "").localeCompare(String(b.status ?? ""));
          break;
        case "createdAt":
          cmp = compareIsoDate(a.createdAt, b.createdAt);
          break;
        default:
          cmp = 0;
      }
    }
    return cmp * dir;
  });
  return copy;
}

function refineSort(items: ViewObject[], sorts: ViewSort[]): ViewObject[] {
  if (sorts.length === 0) return items;
  const s = sorts[0];
  if (s.field === "title" || s.field === "status") {
    return items;
  }
  return sortItemsByField(items, s);
}

function nextSort(field: SortField, sorts: ViewSort[]): ViewSort[] {
  const first = sorts[0];
  if (first?.field === field) {
    return [{ field, direction: first.direction === "asc" ? "desc" : "asc" }];
  }
  return [{ field, direction: "asc" }];
}

type RowEdit = {
  title?: string;
  status?: string | null;
  priority?: string;
  dueDate?: string;
  properties?: Record<string, unknown>;
};

function mergePriority(obj: ViewObject, priority: string): ViewObject {
  const pvs = [...(obj.propertyValues ?? [])];
  const idx = pvs.findIndex((p) => p.propertyDefinition.name === "Priority");
  const def =
    idx >= 0
      ? pvs[idx].propertyDefinition
      : { id: "priority-def", name: "Priority", fieldType: "select" };
  if (idx >= 0) {
    pvs[idx] = { ...pvs[idx], value: priority };
  } else {
    pvs.push({
      propertyDefinition: def,
      value: priority,
    });
  }
  return { ...obj, propertyValues: pvs };
}

function mergeDueDate(obj: ViewObject, due: string): ViewObject {
  const pvs = [...(obj.propertyValues ?? [])];
  const idx = pvs.findIndex((p) => p.propertyDefinition.name === "Due Date");
  const def =
    idx >= 0
      ? pvs[idx].propertyDefinition
      : { id: "due-def", name: "Due Date", fieldType: "date" };
  if (idx >= 0) {
    pvs[idx] = { ...pvs[idx], value: due };
  } else {
    pvs.push({
      propertyDefinition: def,
      value: due,
    });
  }
  return { ...obj, propertyValues: pvs };
}

function mergeProperty(
  obj: ViewObject,
  propId: string,
  val: unknown,
  def?: { id: string; name: string; fieldType: string },
): ViewObject {
  const pvs = [...(obj.propertyValues ?? [])];
  const idx = pvs.findIndex((p) => p.propertyDefinition.id === propId);
  if (idx >= 0) {
    pvs[idx] = { ...pvs[idx], value: val };
  } else if (def) {
    pvs.push({ propertyDefinition: def, value: val });
  }
  return { ...obj, propertyValues: pvs };
}

function applyEdits(
  obj: ViewObject,
  edit: RowEdit | undefined,
  customCols: { id: string; name: string; fieldType: string }[],
): ViewObject {
  if (!edit) return obj;
  let next = obj;
  if (edit.title !== undefined) next = { ...next, title: edit.title };
  if (edit.status !== undefined) next = { ...next, status: edit.status };
  if (edit.priority !== undefined) next = mergePriority(next, edit.priority);
  if (edit.dueDate !== undefined) next = mergeDueDate(next, edit.dueDate);
  if (edit.properties) {
    for (const [pid, val] of Object.entries(edit.properties)) {
      const def = customCols.find((c) => c.id === pid);
      next = mergeProperty(next, pid, val, def);
    }
  }
  return next;
}

function ResizeHandle({
  onResize,
  className,
}: {
  onResize: (delta: number) => void;
  className?: string;
}) {
  const start = React.useRef(0);
  const onMouseDown = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    start.current = e.clientX;
    const onMove = (ev: MouseEvent) => {
      const d = ev.clientX - start.current;
      start.current = ev.clientX;
      if (d !== 0) onResize(d);
    };
    const onUp = () => {
      document.removeEventListener("mousemove", onMove);
      document.removeEventListener("mouseup", onUp);
    };
    document.addEventListener("mousemove", onMove);
    document.addEventListener("mouseup", onUp);
  };
  return (
    <div
      role="separator"
      aria-orientation="vertical"
      onMouseDown={onMouseDown}
      className={cn(
        "absolute right-0 top-0 z-10 h-full w-1.5 translate-x-1/2 cursor-col-resize select-none hover:bg-primary/30",
        className,
      )}
    />
  );
}

function SortHeader({
  label,
  field,
  sorts,
  onSort,
  width,
  stickyClass,
  children,
}: {
  label: string;
  field: SortField;
  sorts: ViewSort[];
  onSort: (field: SortField) => void;
  width: number;
  stickyClass?: string;
  children?: React.ReactNode;
}) {
  const active = sorts[0]?.field === field;
  const dir = active ? sorts[0].direction : null;
  return (
    <th
      scope="col"
      style={{ width, minWidth: width }}
      className={cn(
        "sticky top-0 z-20 border-b border-r border-border/70 bg-muted/50 px-0 text-left text-xs font-semibold uppercase tracking-wide text-muted-foreground backdrop-blur supports-[backdrop-filter]:bg-muted/40",
        stickyClass,
      )}
    >
      <button
        type="button"
        onClick={() => onSort(field)}
        className="flex h-9 w-full items-center gap-1 px-2 text-left transition-colors hover:bg-accent/40 hover:text-foreground"
      >
        <span className="min-w-0 flex-1 truncate">{label}</span>
        {active ? (
          dir === "asc" ? (
            <ArrowUp className="h-3 w-3 shrink-0 opacity-80" />
          ) : (
            <ArrowDown className="h-3 w-3 shrink-0 opacity-80" />
          )
        ) : (
          <ArrowUpDown className="h-3 w-3 shrink-0 opacity-35" />
        )}
      </button>
      {children}
    </th>
  );
}

function TableSkeleton({ colCount }: { colCount: number }) {
  return (
    <tbody>
      {Array.from({ length: 8 }).map((_, i) => (
        <tr key={i} className={cn("border-b border-border/50", i % 2 === 1 && "bg-muted/[0.12]")}>
          {Array.from({ length: colCount }).map((__, j) => (
            <td key={j} className="border-r border-border/50 px-2 py-1.5">
              <div className="h-3 animate-pulse rounded bg-muted/80" />
            </td>
          ))}
        </tr>
      ))}
    </tbody>
  );
}

function EmptyState() {
  return (
    <div className="flex flex-col items-center justify-center gap-2 px-6 py-16 text-center">
      <p className="text-sm font-medium text-foreground">No rows yet</p>
      <p className="max-w-sm text-xs text-muted-foreground">
        Add a row or adjust filters to see data here.
      </p>
    </div>
  );
}

export interface TableViewProps {
  config: ViewConfig;
}

export function TableView({ config }: TableViewProps) {
  const params = useParams();
  const workspaceId =
    typeof params?.workspaceSlug === "string" ? params.workspaceSlug : undefined;
  const parentId =
    typeof params?.projectId === "string" ? params.projectId : undefined;

  const openDetail = usePanelStore((s) => s.open);
  const [sorts, setSorts] = React.useState<ViewSort[]>(config.sorts);
  React.useEffect(() => {
    setSorts(config.sorts);
  }, [config.sorts]);

  const effectiveConfig = React.useMemo(
    () => ({ ...config, sorts }),
    [config, sorts],
  );

  const { items, isLoading, total } = useViewData(
    effectiveConfig,
    workspaceId,
    parentId,
  );

  const [edits, setEdits] = React.useState<Record<string, RowEdit>>({});
  const [isCreating, setIsCreating] = React.useState(false);
  const [newTitle, setNewTitle] = React.useState("");

  const utils = api.useUtils();
  const createObject = api.objects.create.useMutation({
    onSuccess: () => {
      utils.objects.list.invalidate();
      setNewTitle("");
      setIsCreating(false);
    },
  });

  const baseItems = items;

  const customCols = React.useMemo(() => collectCustomColumns(baseItems), [baseItems]);

  const displayItems = React.useMemo(
    () => refineSort(baseItems, sorts),
    [baseItems, sorts],
  );

  const [selected, setSelected] = React.useState<Set<string>>(new Set());

  const [widths, setWidths] = React.useState<Record<string, number>>(() => {
    const w = { ...DEFAULT_COL_WIDTHS };
    return w;
  });

  React.useEffect(() => {
    setWidths((prev) => {
      const next = { ...prev };
      for (const c of customCols) {
        if (next[c.id] === undefined) next[c.id] = 140;
      }
      return next;
    });
  }, [customCols]);

  const setColWidth = React.useCallback((key: string, delta: number) => {
    setWidths((prev) => {
      const cur = prev[key] ?? 120;
      const min = key === "select" ? CHECKBOX_W : 72;
      const nextW = Math.max(min, cur + delta);
      return { ...prev, [key]: nextW };
    });
  }, []);

  const toggleSelect = React.useCallback((id: string) => {
    setSelected((prev) => {
      const n = new Set(prev);
      if (n.has(id)) n.delete(id);
      else n.add(id);
      return n;
    });
  }, []);

  const toggleSelectAll = React.useCallback(() => {
    if (selected.size === displayItems.length && displayItems.length > 0) {
      setSelected(new Set());
      return;
    }
    setSelected(new Set(displayItems.map((o) => o.id)));
  }, [displayItems, selected.size]);

  const onHeaderSort = React.useCallback((field: SortField) => {
    setSorts((s) => nextSort(field, s));
  }, []);

  const patchEdit = React.useCallback((id: string, patch: RowEdit) => {
    setEdits((prev) => {
      const cur = prev[id];
      const merged: RowEdit = { ...cur, ...patch };
      if (patch.properties || cur?.properties) {
        merged.properties = {
          ...(cur?.properties ?? {}),
          ...(patch.properties ?? {}),
        };
      }
      return { ...prev, [id]: merged };
    });
  }, []);

  const getRow = React.useCallback(
    (obj: ViewObject) => applyEdits(obj, edits[obj.id], customCols),
    [edits, customCols],
  );

  const colCount =
    1 + 1 + 1 + 1 + 1 + 1 + 1 + customCols.length;

  const allSelected =
    displayItems.length > 0 && selected.size === displayItems.length;

  const tableMinWidth = React.useMemo(() => {
    let sum = 0;
    sum += widths.select ?? DEFAULT_COL_WIDTHS.select;
    sum += widths.title ?? DEFAULT_COL_WIDTHS.title;
    sum += widths.status ?? DEFAULT_COL_WIDTHS.status;
    sum += widths.priority ?? DEFAULT_COL_WIDTHS.priority;
    sum += widths.assignees ?? DEFAULT_COL_WIDTHS.assignees;
    sum += widths.dueDate ?? DEFAULT_COL_WIDTHS.dueDate;
    sum += widths.created ?? DEFAULT_COL_WIDTHS.created;
    for (const c of customCols) {
      sum += widths[c.id] ?? 140;
    }
    return sum;
  }, [widths, customCols]);

  return (
    <div className="flex h-full min-h-0 flex-col rounded-md border border-border bg-card text-card-foreground shadow-sm">
      <ScrollArea className="min-h-0 flex-1">
        <table
          className="w-full border-collapse text-sm"
          style={{ minWidth: tableMinWidth }}
        >
            <thead>
              <tr>
                <th
                  scope="col"
                  style={{
                    width: widths.select ?? DEFAULT_COL_WIDTHS.select,
                    minWidth: widths.select ?? DEFAULT_COL_WIDTHS.select,
                  }}
                  className={cn(
                    "sticky left-0 top-0 z-40 border-b border-r border-border/70 bg-muted/50 px-0 backdrop-blur supports-[backdrop-filter]:bg-muted/40",
                  )}
                >
                  <div className="relative flex h-9 items-center justify-center border-b border-border/40">
                    <input
                      type="checkbox"
                      checked={allSelected}
                      onChange={toggleSelectAll}
                      className={cn(
                        "h-3.5 w-3.5 cursor-pointer rounded border border-input bg-background",
                        "text-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
                      )}
                      aria-label="Select all rows"
                    />
                    <ResizeHandle onResize={(d) => setColWidth("select", d)} />
                  </div>
                </th>
                <SortHeader
                  label="Title"
                  field="title"
                  sorts={sorts}
                  onSort={onHeaderSort}
                  width={widths.title ?? DEFAULT_COL_WIDTHS.title}
                  stickyClass="left-9 z-30 border-border/70 bg-muted/50 backdrop-blur supports-[backdrop-filter]:bg-muted/40"
                >
                  <ResizeHandle onResize={(d) => setColWidth("title", d)} />
                </SortHeader>
                <SortHeader
                  label="Status"
                  field="status"
                  sorts={sorts}
                  onSort={onHeaderSort}
                  width={widths.status ?? DEFAULT_COL_WIDTHS.status}
                >
                  <ResizeHandle onResize={(d) => setColWidth("status", d)} />
                </SortHeader>
                <SortHeader
                  label="Priority"
                  field="priority"
                  sorts={sorts}
                  onSort={onHeaderSort}
                  width={widths.priority ?? DEFAULT_COL_WIDTHS.priority}
                >
                  <ResizeHandle onResize={(d) => setColWidth("priority", d)} />
                </SortHeader>
                <SortHeader
                  label="Assignees"
                  field="assignees"
                  sorts={sorts}
                  onSort={onHeaderSort}
                  width={widths.assignees ?? DEFAULT_COL_WIDTHS.assignees}
                >
                  <ResizeHandle onResize={(d) => setColWidth("assignees", d)} />
                </SortHeader>
                <SortHeader
                  label="Due date"
                  field="dueDate"
                  sorts={sorts}
                  onSort={onHeaderSort}
                  width={widths.dueDate ?? DEFAULT_COL_WIDTHS.dueDate}
                >
                  <ResizeHandle onResize={(d) => setColWidth("dueDate", d)} />
                </SortHeader>
                <SortHeader
                  label="Created"
                  field="createdAt"
                  sorts={sorts}
                  onSort={onHeaderSort}
                  width={widths.created ?? DEFAULT_COL_WIDTHS.created}
                >
                  <ResizeHandle onResize={(d) => setColWidth("created", d)} />
                </SortHeader>
                {customCols.map((c) => (
                  <SortHeader
                    key={c.id}
                    label={c.name}
                    field={`prop:${c.id}`}
                    sorts={sorts}
                    onSort={onHeaderSort}
                    width={widths[c.id] ?? 140}
                  >
                    <ResizeHandle onResize={(d) => setColWidth(c.id, d)} />
                  </SortHeader>
                ))}
              </tr>
            </thead>
            {isLoading ? (
              <TableSkeleton colCount={colCount} />
            ) : total === 0 && !isCreating ? (
              <tbody>
                <tr>
                  <td colSpan={colCount} className="p-0">
                    <EmptyState />
                  </td>
                </tr>
              </tbody>
            ) : (
              <tbody>
                {displayItems.map((raw, rowIndex) => {
                  const obj = getRow(raw);
                  const isSelected = selected.has(obj.id);
                  const zebra = rowIndex % 2 === 1;
                  const rowBg = isSelected
                    ? "bg-primary/10"
                    : zebra
                      ? "bg-muted/[0.12]"
                      : "bg-background";

                  return (
                    <tr
                      key={obj.id}
                      onDoubleClick={() => openDetail("object-detail", obj.id)}
                      className={cn(
                        "group/row border-b border-border/60 transition-colors",
                        rowBg,
                      )}
                    >
                      <td
                        style={{
                          width: widths.select ?? DEFAULT_COL_WIDTHS.select,
                          minWidth: widths.select ?? DEFAULT_COL_WIDTHS.select,
                        }}
                        className={cn(
                          "sticky left-0 z-20 border-r border-border/60 px-0",
                          rowBg,
                          isSelected && "bg-primary/10",
                          !isSelected && "group-hover/row:bg-accent/35",
                        )}
                      >
                        <div className="flex h-9 items-center justify-center">
                          <input
                            type="checkbox"
                            checked={isSelected}
                            onChange={() => toggleSelect(obj.id)}
                            className={cn(
                              "h-3.5 w-3.5 cursor-pointer rounded border border-input bg-background",
                              "text-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
                            )}
                            aria-label={`Select ${obj.title}`}
                          />
                        </div>
                      </td>
                      <td
                        style={{
                          width: widths.title ?? DEFAULT_COL_WIDTHS.title,
                          minWidth: widths.title ?? DEFAULT_COL_WIDTHS.title,
                        }}
                        className={cn(
                          "sticky left-9 z-10 border-r border-border/60 p-0",
                          rowBg,
                          isSelected && "bg-primary/10",
                          !isSelected && "group-hover/row:bg-accent/35",
                        )}
                      >
                        <TableCell
                          fieldType="title"
                          value={obj.title}
                          onChange={(v) =>
                            patchEdit(obj.id, { title: typeof v === "string" ? v : String(v) })
                          }
                          className="rounded-none border-0"
                        />
                      </td>
                      <td
                        style={{
                          width: widths.status ?? DEFAULT_COL_WIDTHS.status,
                          minWidth: widths.status ?? DEFAULT_COL_WIDTHS.status,
                        }}
                        className={cn(
                          "border-r border-border/60 p-0",
                          rowBg,
                          !isSelected && "group-hover/row:bg-accent/35",
                        )}
                      >
                        <TableCell
                          fieldType="status"
                          value={obj.status}
                          onChange={(v) =>
                            patchEdit(obj.id, { status: typeof v === "string" ? v : null })
                          }
                        />
                      </td>
                      <td
                        style={{
                          width: widths.priority ?? DEFAULT_COL_WIDTHS.priority,
                          minWidth: widths.priority ?? DEFAULT_COL_WIDTHS.priority,
                        }}
                        className={cn(
                          "border-r border-border/60 p-0",
                          rowBg,
                          !isSelected && "group-hover/row:bg-accent/35",
                        )}
                      >
                        <TableCell
                          fieldType="priority"
                          value={getPriorityValue(obj)}
                          onChange={(v) =>
                            patchEdit(obj.id, { priority: typeof v === "string" ? v : "" })
                          }
                        />
                      </td>
                      <td
                        style={{
                          width: widths.assignees ?? DEFAULT_COL_WIDTHS.assignees,
                          minWidth: widths.assignees ?? DEFAULT_COL_WIDTHS.assignees,
                        }}
                        className={cn(
                          "border-r border-border/60 p-0",
                          rowBg,
                          !isSelected && "group-hover/row:bg-accent/35",
                        )}
                      >
                        <TableCell
                          fieldType="assignees"
                          value={obj.assignees ?? []}
                          readOnly
                        />
                      </td>
                      <td
                        style={{
                          width: widths.dueDate ?? DEFAULT_COL_WIDTHS.dueDate,
                          minWidth: widths.dueDate ?? DEFAULT_COL_WIDTHS.dueDate,
                        }}
                        className={cn(
                          "border-r border-border/60 p-0",
                          rowBg,
                          !isSelected && "group-hover/row:bg-accent/35",
                        )}
                      >
                        <TableCell
                          fieldType="date"
                          value={getDueDateValue(obj)}
                          onChange={(v) =>
                            patchEdit(obj.id, {
                              dueDate: v == null || v === "" ? "" : String(v),
                            })
                          }
                        />
                      </td>
                      <td
                        style={{
                          width: widths.created ?? DEFAULT_COL_WIDTHS.created,
                          minWidth: widths.created ?? DEFAULT_COL_WIDTHS.created,
                        }}
                        className={cn(
                          "border-r border-border/60 p-0",
                          rowBg,
                          !isSelected && "group-hover/row:bg-accent/35",
                        )}
                      >
                        <TableCell fieldType="created" value={obj.createdAt} readOnly />
                      </td>
                      {customCols.map((c) => {
                        const ft = mapCustomFieldType(c.fieldType);
                        const val = getPropertyValue(obj, c.id);
                        const opts = Array.from(
                          new Set(
                            baseItems
                              .map((o) => getPropertyValue(o, c.id))
                              .filter((x): x is string => typeof x === "string" && x.length > 0),
                          ),
                        );
                        const selectOpts = opts.length > 0 ? opts : ["—"];
                        return (
                          <td
                            key={c.id}
                            style={{
                              width: widths[c.id] ?? 140,
                              minWidth: widths[c.id] ?? 140,
                            }}
                            className={cn(
                              "border-r border-border/60 p-0",
                              rowBg,
                              !isSelected && "group-hover/row:bg-accent/35",
                            )}
                          >
                            <TableCell
                              fieldType={ft}
                              value={val ?? ""}
                              selectOptions={selectOpts}
                              onChange={(v) =>
                                patchEdit(obj.id, {
                                  properties: { [c.id]: v },
                                })
                              }
                            />
                          </td>
                        );
                      })}
                    </tr>
                  );
                })}
                {isCreating && (
                  <tr
                    key="__inline-create"
                    className="border-b border-border/60 bg-muted/[0.08]"
                  >
                    <td
                      style={{
                        width: widths.select ?? DEFAULT_COL_WIDTHS.select,
                        minWidth: widths.select ?? DEFAULT_COL_WIDTHS.select,
                      }}
                      className="sticky left-0 z-20 border-r border-border/60 bg-muted/[0.08] px-0"
                    />
                    <td
                      style={{
                        width: widths.title ?? DEFAULT_COL_WIDTHS.title,
                        minWidth: widths.title ?? DEFAULT_COL_WIDTHS.title,
                      }}
                      className="sticky left-9 z-10 border-r border-border/60 bg-muted/[0.08] p-0"
                    >
                      <div className="flex h-9 items-center px-2">
                        <input
                          autoFocus
                          className="min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
                          placeholder="Task title…"
                          value={newTitle}
                          onChange={(e) => setNewTitle(e.target.value)}
                          onKeyDown={(e) => {
                            if (e.key === "Enter" && newTitle.trim() && workspaceId) {
                              e.preventDefault();
                              createObject.mutate({
                                type: "task",
                                title: newTitle.trim(),
                                workspaceId,
                                parentId: parentId ?? undefined,
                              });
                            }
                            if (e.key === "Escape") {
                              setIsCreating(false);
                              setNewTitle("");
                            }
                          }}
                          onBlur={() => {
                            if (createObject.isPending) return;
                            if (newTitle.trim() && workspaceId) {
                              createObject.mutate({
                                type: "task",
                                title: newTitle.trim(),
                                workspaceId,
                                parentId: parentId ?? undefined,
                              });
                            } else {
                              setIsCreating(false);
                            }
                          }}
                        />
                      </div>
                    </td>
                    <td
                      colSpan={colCount - 2}
                      className="border-r border-border/60 bg-muted/[0.08] p-0"
                    />
                  </tr>
                )}
              </tbody>
            )}
        </table>
      </ScrollArea>

      <div className="flex shrink-0 border-t border-border/70 bg-muted/20 px-2 py-1.5">
        {!isCreating ? (
          <button
            type="button"
            className="inline-flex h-8 items-center gap-1 rounded-md border border-input bg-background px-2.5 text-xs font-medium text-foreground shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground"
            onClick={() => setIsCreating(true)}
          >
            <Plus className="h-3.5 w-3.5" />
            Add row
          </button>
        ) : null}
      </div>
    </div>
  );
}
