import React, { useEffect, useState, useRef } from "react";
import {
  Text,
  Input,
  Spinner,
  Button,
  Dialog,
  DialogSurface,
  DialogBody,
  DialogTitle,
  DialogActions,
  Menu,
  MenuTrigger,
  MenuPopover,
  MenuList,
  MenuItem,
} from "@fluentui/react-components";
import { DeleteRegular, SearchRegular, ChevronDownRegular } from "@fluentui/react-icons";
import type {
  GeneratedComponentProps,
  ccllc_job,
  ReadableTableRow,
  QueryTableOptions,
} from "./RuntimeTypes";

/* ──────────────────────────────── DEFAULTS ──────────────────────────────── */
const DEFAULT_COLUMN_ORDER = [
  "ccllc_jobnumber", "ccllc_jobname", "ccllc_jobaddress", "ccllc_jobtype",
  "ccllc_flagstatus", "ccllc_jobstatus", "ccllc_jobdivision", "ccllc_estimatorname",
  "ccllc_officerepresentative", "ccllc_clientcompany", "ccllc_contactperson",
  "ccllc_contactphonenumber", "ccllc_contactemail", "ccllc_duedate", "ccllc_duedatecounter",
  "ccllc_duetime", "ccllc_documentsuploaded", "ccllc_quickbookscreated", "ccllc_addedtocalendar",
  "ccllc_pswiftuploaded", "ccllc_voxercreated", "ccllc_estimatedraft", "ccllc_estimatereviewed",
  "ccllc_estimateapproved", "ccllc_notes", "ccllc_activestatus", "ccllc_jobquickbookslink",
  "ccllc_voxerlink", "ccllc_jobcodes", "ccllc_submissiondate", "ccllc_powerappsid",
  "ccllc_jobfolderlink", "ccllc_taxexemptstatus", "statecode", "statuscode", "ccllc_active",
] as const;

const DEFAULT_FRIENDLY_NAMES: Record<string, string> = {
  ccllc_jobnumber: "Job Number",
  ccllc_jobname: "Job Name",
  statecode: "State",
  statuscode: "Status",
  ccllc_active: "Key",
  ccllc_activestatus: "Active\nStatus",
  ccllc_addedtocalendar: "Added to\nCalendar",
  ccllc_clientcompany: "Client\nCompany",
  ccllc_contactemail: "Contact\nEmail",
  ccllc_contactperson: "Contact\nPerson",
  ccllc_contactphonenumber: "Contact\nPhone Number",
  ccllc_documentsuploaded: "Documents\nUploaded",
  ccllc_duedate: "Due Date",
  ccllc_duedatecounter: "Due Date\nCounter",
  ccllc_duetime: "Due Time",
  ccllc_estimateapproved: "Estimate\nApproved",
  ccllc_estimatedraft: "Estimate\nDraft",
  ccllc_estimatereviewed: "Estimate\nReviewed",
  ccllc_estimatorname: "Estimator\nName",
  ccllc_flagstatus: "Flag",
  ccllc_jobaddress: "Job\nAddress",
  ccllc_jobcodes: "Job\nCodes",
  ccllc_jobdivision: "Job\nDivision",
  ccllc_jobfolderlink: "Job Folder Link",
  ccllc_jobquickbookslink: "Job QuickBooks\nLink",
  ccllc_jobstatus: "Job\nStatus",
  ccllc_jobtype: "Job\nType",
  ccllc_notes: "Notes",
  ccllc_officerepresentative: "Office Rep",
  ccllc_powerappsid: "PowerApps\nID",
  ccllc_pswiftuploaded: "PSwift\nUploaded",
  ccllc_quickbookscreated: "QB Created",
  ccllc_submissiondate: "Submission\nDate",
  ccllc_taxexemptstatus: "Tax Exempt",
  ccllc_voxercreated: "Voxer\nCreated",
  ccllc_voxerlink: "Voxer Link",
};

const DEFAULT_COLUMN_ALIGNMENTS: Record<string, "left" | "center" | "right"> = {
  ccllc_jobnumber: "center",
  ccllc_jobname: "left",
  statecode: "center",
  statuscode: "center",
  ccllc_active: "center",
  ccllc_activestatus: "center",
  ccllc_addedtocalendar: "center",
  ccllc_clientcompany: "left",
  ccllc_contactemail: "left",
  ccllc_contactperson: "left",
  ccllc_contactphonenumber: "left",
  ccllc_documentsuploaded: "center",
  ccllc_duedate: "center",
  ccllc_duedatecounter: "center",
  ccllc_duetime: "center",
  ccllc_estimateapproved: "center",
  ccllc_estimatedraft: "center",
  ccllc_estimatereviewed: "center",
  ccllc_estimatorname: "left",
  ccllc_flagstatus: "center",
  ccllc_jobaddress: "left",
  ccllc_jobcodes: "left",
  ccllc_jobdivision: "left",
  ccllc_jobfolderlink: "left",
  ccllc_jobquickbookslink: "left",
  ccllc_jobstatus: "center",
  ccllc_jobtype: "center",
  ccllc_notes: "left",
  ccllc_officerepresentative: "left",
  ccllc_powerappsid: "center",
  ccllc_pswiftuploaded: "center",
  ccllc_quickbookscreated: "center",
  ccllc_submissiondate: "center",
  ccllc_taxexemptstatus: "center",
  ccllc_voxercreated: "center",
  ccllc_voxerlink: "left",
};

const DEFAULT_COLUMN_WIDTHS: Record<string, number> = {
  ccllc_jobnumber: 100,
  ccllc_jobname: 280,
  statecode: 80,
  statuscode: 80,
  ccllc_active: 80,
  ccllc_activestatus: 100,
  ccllc_addedtocalendar: 120,
  ccllc_clientcompany: 160,
  ccllc_contactemail: 180,
  ccllc_contactperson: 140,
  ccllc_contactphonenumber: 140,
  ccllc_documentsuploaded: 120,
  ccllc_duedate: 110,
  ccllc_duedatecounter: 110,
  ccllc_duetime: 100,
  ccllc_estimateapproved: 120,
  ccllc_estimatedraft: 120,
  ccllc_estimatereviewed: 120,
  ccllc_estimatorname: 140,
  ccllc_flagstatus: 80,
  ccllc_jobaddress: 180,
  ccllc_jobcodes: 120,
  ccllc_jobdivision: 120,
  ccllc_jobfolderlink: 160,
  ccllc_jobquickbookslink: 160,
  ccllc_jobstatus: 120,
  ccllc_jobtype: 120,
  ccllc_notes: 180,
  ccllc_officerepresentative: 140,
  ccllc_powerappsid: 120,
  ccllc_pswiftuploaded: 120,
  ccllc_quickbookscreated: 120,
  ccllc_submissiondate: 120,
  ccllc_taxexemptstatus: 120,
  ccllc_voxercreated: 120,
  ccllc_voxerlink: 160,
};

const DEFAULT_COLUMN_VISIBILITY = Object.fromEntries(
  DEFAULT_COLUMN_ORDER.map(c => [c, true])
);

/* ──────────────────────────────── UTILS ──────────────────────────────── */
const getJobColumns = (row?: ReadableTableRow<ccllc_job>): string[] => {
  const sticky = ["ccllc_jobnumber", "ccllc_jobname"];
  const ignore = new Set(["ccllc_jobid", "@Odata.Etag", "@odata.etag"]);
  if (!row) return sticky;
  return [
    ...sticky,
    ...Object.keys(row).filter(
      k =>
        !sticky.includes(k) &&
        !ignore.has(k) &&
        !k.endsWith("@OData.Community.Display.V1.FormattedValue") &&
        typeof row[k as keyof typeof row] !== "function"
    ),
  ];
};

const humanize = (col: string) =>
  col.replace(/^ccllc_/, "").replace(/_/g, " ").replace(/\b\w/g, l => l.toUpperCase());

/* ───────────────────────────── EditableCell ───────────────────────────── */
function EditableCell({
  value,
  onSave,
  rowId,
  colKey,
  isSticky,
  width,
  disabled,
  isFirstNonSticky,
  align,
}: {
  value: string;
  onSave: (v: string) => Promise<void>;
  rowId: string;
  colKey: string;
  isSticky?: boolean;
  width?: number;
  disabled?: boolean;
  isFirstNonSticky?: boolean;
  align?: "left" | "center" | "right";
}) {
  const [editing, setEditing] = useState(false);
  const [editValue, setEditValue] = useState(value ?? "");
  const inputRef = useRef<HTMLInputElement>(null);

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

  useEffect(() => setEditValue(value ?? ""), [value]);

  const startEdit = () => !disabled && setEditing(true);
  const finishEdit = async () => {
    const final = colKey === "ccllc_jobnumber" ? editValue.replace(/,/g, "") : editValue;
    if (final !== value) await onSave(final);
    setEditing(false);
  };

  const cellStyle: React.CSSProperties = {
    minWidth: width ? `${width}px` : undefined,
    maxWidth: width ? `${width}px` : undefined,
    width: width ? `${width}px` : undefined,
    borderTop: "1px solid #000",
    borderLeft: isFirstNonSticky ? "none" : "1px solid #000",
    borderRight: colKey === "ccllc_jobnumber" ? "none" : "1px solid #000",
    borderBottom: "1px solid #000",
    boxSizing: "border-box",
    position: isSticky ? "sticky" : undefined,
    left: isSticky && colKey === "ccllc_jobnumber" ? 0 : isSticky && colKey === "ccllc_jobname" ? 100 : undefined,
    zIndex: isSticky ? 1500 : undefined,
    background: isSticky ? "#fff" : undefined,
    overflow: "hidden",
    whiteSpace: "nowrap",
    padding: "6px 10px",
    cursor: disabled ? "not-allowed" : "pointer",
    userSelect: "none",
    textAlign: align || "left",
  };

  return (
    <td style={cellStyle} onClick={startEdit} tabIndex={disabled ? -1 : 0}>
      {editing && !disabled ? (
        <input
          ref={inputRef}
          value={editValue}
          onChange={e => setEditValue(e.target.value)}
          onBlur={finishEdit}
          onKeyDown={e => {
            if (e.key === "Enter") finishEdit();
            if (e.key === "Escape") {
              setEditValue(value ?? "");
              setEditing(false);
            }
          }}
          style={{
            width: "100%",
            background: "transparent",
            border: "none",
            outline: "none",
            font: "inherit",
            padding: 0,
            margin: 0,
            textAlign: align || "left",
          }}
        />
      ) : (
        <span style={{ display: "block", width: "100%", overflow: "hidden", textOverflow: "ellipsis" }}>
          {colKey === "ccllc_jobnumber" ? (value ?? "").replace(/,/g, "") : value}
        </span>
      )}
    </td>
  );
}

/* ─────────────────────────── EditableHeaderCell ─────────────────────────── */
function EditableHeaderCell({
  value,
  onSave,
  colKey,
  isSticky,
  width,
  isFirstNonSticky,
  align,
}: {
  value: string;
  onSave: (newValue: string) => void;
  colKey: string;
  isSticky?: boolean;
  width?: number;
  isFirstNonSticky?: boolean;
  align?: "left" | "center" | "right";
}) {
  const [editing, setEditing] = useState(false);
  const [editValue, setEditValue] = useState(value);
  const inputRef = useRef<HTMLInputElement>(null);

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

  useEffect(() => setEditValue(value), [value]);

  const handleCellClick = (e: React.MouseEvent) => {
    if (!(e.target as HTMLElement).closest(".header-dropdown-btn")) {
      setEditing(true);
    }
  };

  const handleSave = () => {
    if (editValue !== value) onSave(editValue);
    setEditing(false);
  };

  const handleInputBlur = () => handleSave();
  const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") handleSave();
    else if (e.key === "Escape") {
      setEditValue(value);
      setEditing(false);
    }
  };

  // Sticky header cells for "Job Number" and "Job Name" should have top: 0 to stay fixed on vertical scroll
  const isStickyHeader = isSticky && (colKey === "ccllc_jobnumber" || colKey === "ccllc_jobname");

  // Always sticky at top for all header cells
  const headerStyle: React.CSSProperties = {
    minWidth: width ? `${width}px` : "60px",
    maxWidth: width ? `${width + 20}px` : undefined,
    width: width ? `${width}px` : undefined,
    borderTop: "1px solid #000",
    borderLeft: isFirstNonSticky ? "none" : "1px solid #000",
    borderRight: value === "Job Number" ? "none" : "1px solid #000",
    borderBottom: "1px solid #000",
    boxSizing: "border-box",
    position: "sticky",
    top: 0,
    left: isSticky && colKey === "ccllc_jobnumber" ? 0 : isSticky && colKey === "ccllc_jobname" ? 100 : undefined,
    zIndex: isSticky
      ? 2000 // sticky columns in header
      : 1500, // normal header
    background: "#f3f3f3",
    whiteSpace: "normal",
    padding: 0,
    fontWeight: 600,
    textAlign: align || "left",
    cursor: "pointer",
    userSelect: "none",
    minHeight: "40px",
    height: "40px",
    overflow: "visible",
  };

  const flexRowStyle: React.CSSProperties = {
    display: "flex",
    flexDirection: "row",
    alignItems: "flex-end",
    justifyContent: "space-between",
    width: "100%",
    height: "100%",
    minHeight: "40px",
    overflow: "visible",
  };

  const labelAreaStyle: React.CSSProperties = {
    flex: "1 1 0",
    minWidth: 0,
    display: "flex",
    alignItems: "center",
    padding: "8px 8px 8px 10px",
    boxSizing: "border-box",
    overflow: "hidden",
  };

  const dropdownCellStyle: React.CSSProperties = {
    width: "20px",
    minWidth: "20px",
    maxWidth: "20px",
    height: "40px",
    boxSizing: "border-box",
    overflow: "visible",
    display: "flex",
    alignItems: "flex-end",
    justifyContent: "center",
    paddingBottom: "4px",
    zIndex: 1600,
  };

  const dropdownButtonStyle: React.CSSProperties = {
    width: "16px",
    height: "16px",
    minWidth: "16px",
    minHeight: "16px",
    padding: 0,
    margin: 0,
    borderRadius: "4px",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    background: "#C0C0C0",
    zIndex: 1600,
  };

  const renderHeaderText = (text: string) => {
    const lines = text.split("\n");
    return (
      <span style={{ display: "block", width: "100%", wordBreak: "break-word", whiteSpace: "pre-line" }}>
        {lines.map((line, idx) => (
          <React.Fragment key={idx}>
            {line}
            {idx < lines.length - 1 ? <br /> : null}
          </React.Fragment>
        ))}
      </span>
    );
  };

  return (
    <th style={headerStyle} onClick={handleCellClick} tabIndex={0} aria-label={`Edit column: ${value}`}>
      <div style={flexRowStyle}>
        <div style={labelAreaStyle}>
          {editing ? (
            <input
              ref={inputRef}
              value={editValue}
              onChange={e => setEditValue(e.target.value)}
              onBlur={handleInputBlur}
              onKeyDown={handleInputKeyDown}
              style={{
                width: "100%",
                background: "transparent",
                border: "none",
                outline: "none",
                font: "inherit",
                padding: 0,
                margin: 0,
                color: "#222",
                whiteSpace: "pre-line",
                textAlign: align || "left",
              }}
            />
          ) : (
            renderHeaderText(editValue)
          )}
        </div>

        <div style={dropdownCellStyle}>
          <Menu>
            <MenuTrigger disableButtonEnhancement>
              <Button
                appearance="subtle"
                size="small"
                icon={<ChevronDownRegular fontSize="15px" />}
                aria-label="Column options"
                className="header-dropdown-btn"
                style={dropdownButtonStyle}
                tabIndex={0}
              />
            </MenuTrigger>
            <MenuPopover style={{ zIndex: 1700 }}>
              <MenuList>
                <MenuItem>Column options</MenuItem>
              </MenuList>
            </MenuPopover>
          </Menu>
        </div>
      </div>
    </th>
  );
}

/* ─────────────────────────────── MAIN COMPONENT ─────────────────────────────── */
const BATCH_SIZE = 50; // Show 50 records at a time
const DEFAULT_SEARCH_BATCH_SIZE = 10;
const SEARCH_ALL_PAGE_SIZE = 100;

const GeneratedComponent: React.FC<GeneratedComponentProps> = ({ dataApi }) => {
  const [mainRows, setMainRows] = useState<ReadableTableRow<ccllc_job>[]>([]);
  const [searchRows, setSearchRows] = useState<ReadableTableRow<ccllc_job>[]>([]);
  const [searchText, setSearchText] = useState("");
  const [searchAll, setSearchAll] = useState(false);
  const [loading, setLoading] = useState(true);
  const [searchLoading, setSearchLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [headerNames, setHeaderNames] = useState({ ...DEFAULT_FRIENDLY_NAMES });
  const [deleting, setDeleting] = useState(false);
  const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
  const [rowToDelete, setRowToDelete] = useState<ReadableTableRow<ccllc_job> | null>(null);
  const scrollRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    let mounted = true;
    const load = async () => {
      try {
        setLoading(true);
        const { rows } = await dataApi.queryTable("ccllc_job", {
          select: DEFAULT_COLUMN_ORDER,
          pageSize: BATCH_SIZE,
          orderBy: "ccllc_jobnumber desc",
        });
        const clean = rows.map(r => {
          const { ["@Odata.Etag"]: _, ...rest } = r;
          return rest;
        });
        if (mounted) setMainRows(clean);
      } catch {
        if (mounted) setError("Failed to load jobs.");
      } finally {
        if (mounted) setLoading(false);
      }
    };
    load();
    return () => { mounted = false; };
  }, [dataApi]);

useEffect(() => {
  if (!searchText.trim()) {
    setSearchRows([]);
    setSearchLoading(false);
    return;
  }

  let cancelled = false;
  const run = async () => {
    setSearchLoading(true);
    const cols = [
      "ccllc_jobname", "ccllc_jobnumber", "ccllc_jobaddress", "ccllc_clientcompany",
      "ccllc_contactperson", "ccllc_contactemail", "ccllc_notes", "ccllc_estimatorname",
      "ccllc_officerepresentative",
    ];
    const filter = cols
      .map(c => `contains(${c},'${searchText.replace(/'/g, "''")}')`)
      .join(" or ");

    const allResults: ReadableTableRow<ccllc_job>[] = [];
    const pageSize = searchAll ? 100 : DEFAULT_SEARCH_BATCH_SIZE; // 100 or 10
    let skip = 0;
    let hasMore = searchAll; // Only paginate if "Show All"

    try {
      // Initial request
      let opts: QueryTableOptions<ccllc_job> = {
        select: DEFAULT_COLUMN_ORDER,
        pageSize,
        orderBy: "ccllc_jobnumber desc",
        filter,
        skip,
      };

      let { rows, nextLink } = await dataApi.queryTable("ccllc_job", opts);

      // Clean and store first page
      const clean = rows.map(r => {
        const { ["@Odata.Etag"]: _, ...rest } = r;
        return rest;
      });
      allResults.push(...clean);

      // Only continue if "Show All" and there's more
      while (!cancelled && searchAll && nextLink && clean.length === pageSize) {
        skip += pageSize;
        opts = { ...opts, skip };
        const result = await dataApi.queryTable("ccllc_job", opts);
        rows = result.rows;
        nextLink = result.nextLink;

        const cleanPage = rows.map(r => {
          const { ["@Odata.Etag"]: _, ...rest } = r;
          return rest;
        });
        allResults.push(...cleanPage);
      }

      if (!cancelled) setSearchRows(allResults);
    } catch (err) {
      if (!cancelled) setError("Search failed.");
    } finally {
      if (!cancelled) setSearchLoading(false);
    }
  };

  run();
  return () => { cancelled = true; };
}, [searchText, searchAll, dataApi]);

  const handleCellSave = async (rowId: string, colKey: string, newValue: string) => {
    try {
      const all = [...searchRows, ...mainRows];
      const row = all.find(r => r.ccllc_jobid === rowId);
      if (!row) return;
      const final = colKey === "ccllc_jobnumber" ? newValue.replace(/,/g, "") : newValue;
      if ((row as any)[colKey] === final) return;

      await dataApi.updateRow("ccllc_job", rowId, { [colKey]: final });

      const update = (list: typeof all) =>
        list.map(r => (r.ccllc_jobid === rowId ? { ...r, [colKey]: final } : r));

      setSearchRows(update);
      setMainRows(update);
    } catch {
      setError("Update failed.");
    }
  };

  const handleHeaderSave = (col: string, name: string) => {
    setHeaderNames(p => ({ ...p, [col]: name }));
  };

  const openDelete = (row: ReadableTableRow<ccllc_job>) => {
    setRowToDelete(row);
    setDeleteDialogOpen(true);
  };

  const confirmDelete = async () => {
    if (!rowToDelete) return;
    setDeleting(true);
    try {
      await dataApi.deleteRow("ccllc_job", rowToDelete.ccllc_jobid);
      const id = rowToDelete.ccllc_jobid;
      setSearchRows(p => p.filter(r => r.ccllc_jobid !== id));
      setMainRows(p => p.filter(r => r.ccllc_jobid !== id));
    } catch {
      setError("Delete failed.");
    } finally {
      setDeleting(false);
      setDeleteDialogOpen(false);
      setRowToDelete(null);
    }
  };

  const visibleCols = (mainRows.length
    ? getJobColumns(mainRows[0])
    : DEFAULT_COLUMN_ORDER
  ).filter(c => c !== "@Odata.Etag" && DEFAULT_COLUMN_VISIBILITY[c] !== false);

  const firstNonStickyIdx = visibleCols.findIndex(
    c => c !== "ccllc_jobnumber" && c !== "ccllc_jobname"
  );

  const rows = searchText.trim() ? searchRows : mainRows;
  const isShowAllSearch = searchText.trim() && searchAll;
  const displayedRows = isShowAllSearch ? rows : rows.slice(0, 50);

  return (
    <div
      style={{
        height: "100%",
        display: "flex",
        flexDirection: "column",
        boxSizing: "border-box",
        padding: 20,
      }}
    >
      {/* Header */}
      <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 12, gap: 12, flexShrink: 0, minHeight: 36 }}>
        <div style={{ border: "2px solid #000", background: "#f3f3f3", borderRadius: 8, padding: "0px 16px",display: "flex", height: 36, }}>
          <Text as="h1" size={700} weight="semibold">Job List</Text>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <Input
            value={searchText}
            onChange={(_, d) => setSearchText(d.value)}
            placeholder="Search jobs..."
            contentBefore={<SearchRegular />}
            style={{ height: 36 }}
          />
          <Button
            appearance="subtle"
            onClick={() => setSearchAll(a => !a)}
            style={{ background: searchAll ? "#e5ffe5" : "#f3f3f3", border: "1px solid #000", }}
          >
            {searchAll ? "Top 10" : "Show All"}
          </Button>
        </div>
      </div>

      {error && <Text style={{ color: "#b00", marginBottom: 8, flexShrink: 0 }}>{error}</Text>}

      {/* TABLE CONTAINER */}
      <div
        style={{
          flex: 1,
          minHeight: 0,
          border: "1px solid #000",
          borderRadius: 6,
          overflow: "hidden",
          position: "relative",
          display: "flex",
          flexDirection: "column",
        }}
      >
        {(loading || searchLoading) && displayedRows.length === 0 ? (
          <div style={{ flex: 1, display: "flex", justifyContent: "center", alignItems: "center" }}>
            <Spinner size="medium" label="Loading…" />
          </div>
        ) : (
          <div
            ref={scrollRef}
            style={{
              flex: 1,
              minHeight: 0,
              maxHeight: 600, // Force vertical scroll for more than 50 rows
              overflowY: "auto",
              overflowX: "auto",
              WebkitOverflowScrolling: "touch",
              boxSizing: "border-box",
            }}
          >
            <table
              style={{
                borderCollapse: "separate",
                borderSpacing: 0,
                width: "max-content",
                minWidth: "100%",
                tableLayout: "fixed",
              }}
            >
              <thead>
                <tr>
                  {visibleCols.map((col, idx) => (
                    <EditableHeaderCell
                      key={col}
                      colKey={col}
                      value={headerNames[col] || humanize(col)}
                      onSave={v => handleHeaderSave(col, v)}
                      isSticky={col === "ccllc_jobnumber" || col === "ccllc_jobname"}
                      width={DEFAULT_COLUMN_WIDTHS[col]}
                      isFirstNonSticky={idx === firstNonStickyIdx}
                      align={DEFAULT_COLUMN_ALIGNMENTS[col]}
                    />
                  ))}
                  <th
                    style={{
                      minWidth: 60,
                      width: 60,
                      border: "1px solid #000",
                      background: "#f3f3f3",
                      position: "sticky",
                      top: 0,
                      right: undefined,
                      zIndex: 1500,
                      transform: "none",
                    }}
                  >
                    Delete
                  </th>
                </tr>
              </thead>

              <tbody>
                {displayedRows.map(row => (
                  <tr key={row.ccllc_jobid}>
                    {visibleCols.map((col, idx) => (
                      <EditableCell
                        key={col}
                        value={row[col as keyof typeof row]?.toString() ?? ""}
                        onSave={v => handleCellSave(row.ccllc_jobid, col, v)}
                        rowId={row.ccllc_jobid}
                        colKey={col}
                        isSticky={col === "ccllc_jobnumber" || col === "ccllc_jobname"}
                        width={DEFAULT_COLUMN_WIDTHS[col]}
                        disabled={col === "ccllc_jobid"}
                        isFirstNonSticky={idx === firstNonStickyIdx}
                        align={DEFAULT_COLUMN_ALIGNMENTS[col]}
                      />
                    ))}

                    <td
                      style={{
                        minWidth: 60,
                        width: 60,
                        borderTop: "1px solid #000",
                        borderBottom: "1px solid #000",
                        borderLeft: "1px solid #000",
                        background: "#fff",
                        position: "static",
                        right: undefined,
                        zIndex: undefined,
                        transform: "none",
                        textAlign: "center",
                      }}
                    >
                      <Button
                        appearance="subtle"
                        icon={<DeleteRegular />}
                        onClick={() => openDelete(row)}
                        disabled={deleting}
                      />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {/* Delete Dialog */}
      <Dialog open={deleteDialogOpen} onOpenChange={(_, { open }) => !open && setDeleteDialogOpen(false)}>
        <DialogSurface>
          <DialogBody>
            <DialogTitle>Confirm Delete</DialogTitle>
            <Text block size={400} style={{ marginBottom: 16 }}>
              Are you sure you want to delete this job record?
            </Text>
            <DialogActions>
              <Button appearance="secondary" onClick={() => setDeleteDialogOpen(false)} disabled={deleting}>
                Cancel
              </Button>
              <Button
                appearance="primary"
                style={{ backgroundColor: "#b00", color: "#fff" }}
                onClick={confirmDelete}
                disabled={deleting}
              >
                {deleting ? "Deleting…" : "Delete"}
              </Button>
            </DialogActions>
          </DialogBody>
        </DialogSurface>
      </Dialog>
    </div>
  );
};

export const TablePage = GeneratedComponent;
export default TablePage;