/**
 * Table Component Generator
 *
 * Generates a Table ComponentSet in Figma with a simplified static representation.
 * Tables are complex data components, so this generator creates a visual preview
 * showing the key styling elements:
 *
 * - Layout variants: auto, fixed
 * - Row variants: default, selected
 * - Header row styling
 * - Cell padding and borders
 *
 * Reads definitions from component-registry.json (the source of truth).
 *
 * @see packages/kumo/src/components/table/table.tsx
 */

import {
  createTextNode,
  bindFillToVariable,
  bindStrokeToVariable,
  bindTextColorToVariable,
  getVariableByName,
  createModeSection,
  createRowLabel,
  FONT_SIZE,
  SECTION_PADDING,
  SECTION_GAP,
  GRID_LAYOUT,
  FALLBACK_VALUES,
  SECTION_LAYOUT,
  BORDER_RADIUS,
  VAR_NAMES,
} from "./shared";
import { createIconInstance, bindIconColor } from "./icon-utils";
import themeData from "../generated/theme-data.json";
import { logInfo } from "../logger";

// Import variant data from the registry (generated by build:ai-metadata)
import registry from "@cloudflare/kumo/ai/component-registry.json";

// Extract Table component data from registry
// Use type assertion since Table exists but TypeScript strict typing doesn't include all components
const tableComponent = (registry.components as Record<string, unknown>)
  .Table as {
  name: string;
  description: string;
  props: {
    layout: {
      type: string;
      values: string[];
      default: string;
      descriptions: Record<string, string>;
    };
    variant: {
      type: string;
      values: string[];
      default: string;
      descriptions: Record<string, string>;
    };
  };
  colors: string[];
  subComponents: Record<string, unknown>;
};

/**
 * Table cell padding (p-3 = 12px)
 */
const CELL_PADDING = themeData.tailwind.spacing.scale["3"];

/**
 * Checkbox box size (h-4 w-4 = 16px)
 */
const CHECKBOX_SIZE = themeData.tailwind.spacing.scale["4"];

/**
 * Table configuration for static preview
 */
type TableConfig = {
  layout: "auto" | "fixed";
  hasSelectedRow: boolean;
};

/**
 * Row data with checkbox state
 */
type RowData = {
  cells: string[];
  checked: boolean;
};

/**
 * Sample data for the table preview
 */
const SAMPLE_DATA = {
  headers: ["Name", "Status", "Type"],
  rows: [
    { cells: ["Resource 1", "Active", "File"], checked: false },
    { cells: ["Resource 2", "Pending", "Folder"], checked: false },
    { cells: ["Resource 3", "Active", "File"], checked: false },
  ] as RowData[],
};

/**
 * Table configurations to generate
 */
const TABLE_CONFIGS: TableConfig[] = [
  { layout: "auto", hasSelectedRow: false },
  { layout: "auto", hasSelectedRow: true },
  { layout: "fixed", hasSelectedRow: false },
  { layout: "fixed", hasSelectedRow: true },
];

/**
 * TESTABLE EXPORTS - Pure functions that return intermediate data
 * These functions compute data without calling Figma APIs, enabling snapshot tests.
 */

/**
 * Get Table component configuration from registry
 */
export function getTableComponentConfig() {
  return {
    name: tableComponent.name,
    description: tableComponent.description,
    props: tableComponent.props,
    colors: tableComponent.colors,
    subComponents: Object.keys(tableComponent.subComponents),
  };
}

/**
 * Get layout variant configuration from registry
 */
export function getTableLayoutConfig() {
  const layoutProp = tableComponent.props.layout;
  return {
    values: layoutProp.values,
    default: layoutProp.default,
    descriptions: layoutProp.descriptions,
  };
}

/**
 * Get row variant configuration from registry
 */
export function getTableRowVariantConfig() {
  const variantProp = tableComponent.props.variant;
  return {
    values: variantProp.values,
    default: variantProp.default,
    descriptions: variantProp.descriptions,
  };
}

/**
 * Get cell styling configuration
 */
export function getTableCellConfig() {
  return {
    padding: CELL_PADDING, // p-3 = 12px
    borderWidth: FALLBACK_VALUES.strokeWeight, // 1px
    borderVariable: VAR_NAMES.color.line,
  };
}

/**
 * Get header cell styling configuration
 */
export function getTableHeaderConfig() {
  return {
    fontSize: FONT_SIZE.base, // 14px
    fontWeight: FALLBACK_VALUES.fontWeight.semiBold, // font-semibold = 600
    textVariable: VAR_NAMES.text.default,
    bgVariable: VAR_NAMES.color.base,
    padding: CELL_PADDING,
  };
}

/**
 * Get body cell styling configuration
 */
export function getTableBodyCellConfig() {
  return {
    fontSize: FONT_SIZE.base, // 14px
    fontWeight: FALLBACK_VALUES.fontWeight.normal, // 400
    textVariable: VAR_NAMES.text.default,
  };
}

/**
 * Get selected row styling configuration
 */
export function getTableSelectedRowConfig() {
  return {
    bgVariable: VAR_NAMES.color.tint, // bg-kumo-tint
  };
}

/**
 * Get checkbox cell styling configuration
 */
export function getTableCheckboxCellConfig() {
  return {
    boxSize: CHECKBOX_SIZE, // 16px
    borderRadius: BORDER_RADIUS.sm, // 2px (rounded-sm)
    uncheckedBgVariable: VAR_NAMES.color.base,
    checkedBgVariable: VAR_NAMES.color.contrast, // color-kumo-contrast (inverse of base)
    borderVariable: VAR_NAMES.color.line,
    iconName: "ph-check" as const,
    iconSize: 12, // Small icon inside 16px box
    iconColor: "text-kumo-inverse",
  };
}

/**
 * Get complete Table configuration
 */
export function getTableCompleteConfig(config: TableConfig) {
  return {
    layout: config.layout,
    hasSelectedRow: config.hasSelectedRow,
    cellConfig: getTableCellConfig(),
    headerConfig: getTableHeaderConfig(),
    bodyCellConfig: getTableBodyCellConfig(),
    selectedRowConfig: config.hasSelectedRow
      ? getTableSelectedRowConfig()
      : null,
    sampleData: SAMPLE_DATA,
  };
}

/**
 * Get all Table variant data (for snapshot testing)
 * Returns intermediate data before Figma API calls
 */
export function getAllTableVariantData() {
  const componentConfig = getTableComponentConfig();
  const layoutConfig = getTableLayoutConfig();
  const rowVariantConfig = getTableRowVariantConfig();
  const cellConfig = getTableCellConfig();
  const headerConfig = getTableHeaderConfig();
  const bodyCellConfig = getTableBodyCellConfig();
  const selectedRowConfig = getTableSelectedRowConfig();

  return {
    componentConfig,
    layoutConfig,
    rowVariantConfig,
    cellConfig,
    headerConfig,
    bodyCellConfig,
    selectedRowConfig,
    sampleData: SAMPLE_DATA,
    configs: TABLE_CONFIGS.map((config) => getTableCompleteConfig(config)),
  };
}

/**
 * Get variant name for a Table configuration
 */
function getVariantName(config: TableConfig): string {
  const parts: string[] = [];
  parts.push(`layout=${config.layout}`);
  parts.push(`hasSelectedRow=${config.hasSelectedRow}`);
  return parts.join(", ");
}

/**
 * Get human-readable label for row labels
 */
function getRowLabelText(config: TableConfig): string {
  const parts: string[] = [];
  parts.push(`layout=${config.layout}`);
  if (config.hasSelectedRow) parts.push("selected");
  return parts.join(", ");
}

// ============================================================================
// FIGMA GENERATION FUNCTIONS (use Figma APIs)
// ============================================================================

/**
 * Create a checkbox box for table cells
 */
function createTableCheckboxBox(checked: boolean): FrameNode {
  const checkboxConfig = getTableCheckboxCellConfig();

  const box = figma.createFrame();
  box.name = "Checkbox Box";
  box.resize(checkboxConfig.boxSize, checkboxConfig.boxSize);

  // Auto-layout for centering icon
  box.layoutMode = "HORIZONTAL";
  box.primaryAxisAlignItems = "CENTER";
  box.counterAxisAlignItems = "CENTER";
  box.primaryAxisSizingMode = "FIXED";
  box.counterAxisSizingMode = "FIXED";

  // Border radius
  box.cornerRadius = checkboxConfig.borderRadius;

  // Background fill based on checked state
  const bgVariable = checked
    ? checkboxConfig.checkedBgVariable
    : checkboxConfig.uncheckedBgVariable;
  const bgVar = getVariableByName(bgVariable);
  if (bgVar) {
    bindFillToVariable(box, bgVar.id);
  }

  // Border
  const borderVar = getVariableByName(checkboxConfig.borderVariable);
  if (borderVar) {
    bindStrokeToVariable(box, borderVar.id, 1);
  }

  // Add check icon if checked
  if (checked) {
    const iconInstance = createIconInstance(
      checkboxConfig.iconName,
      checkboxConfig.iconSize,
    );
    if (iconInstance) {
      bindIconColor(iconInstance, checkboxConfig.iconColor);
      box.appendChild(iconInstance);
    }
  }

  return box;
}

/**
 * Create a checkbox cell for table header or body
 */
async function createTableCheckboxCell(
  isHeader: boolean,
  isSelected: boolean,
  checked: boolean,
  width: number,
): Promise<FrameNode> {
  const cellConfig = getTableCellConfig();
  const headerConfig = getTableHeaderConfig();
  const selectedRowConfig = getTableSelectedRowConfig();

  const cell = figma.createFrame();
  cell.name = isHeader ? "Check Head" : "Check Cell";
  cell.resize(width, isHeader ? 44 : 48);

  // Configure as horizontal auto-layout, centered
  cell.layoutMode = "HORIZONTAL";
  cell.primaryAxisAlignItems = "CENTER";
  cell.counterAxisAlignItems = "CENTER";
  cell.paddingLeft = cellConfig.padding;
  cell.paddingRight = cellConfig.padding;
  cell.paddingTop = cellConfig.padding;
  cell.paddingBottom = cellConfig.padding;

  // Apply background
  if (isHeader) {
    const bgVar = getVariableByName(headerConfig.bgVariable);
    if (bgVar) {
      bindFillToVariable(cell, bgVar.id);
    }
  } else if (isSelected) {
    const bgVar = getVariableByName(selectedRowConfig.bgVariable);
    if (bgVar) {
      bindFillToVariable(cell, bgVar.id);
    }
  } else {
    cell.fills = [];
  }

  // Apply bottom border
  const borderVar = getVariableByName(cellConfig.borderVariable);
  if (borderVar) {
    bindStrokeToVariable(cell, borderVar.id, cellConfig.borderWidth);
    cell.strokesIncludedInLayout = true;
    cell.strokeTopWeight = 0;
    cell.strokeLeftWeight = 0;
    cell.strokeRightWeight = 0;
    cell.strokeBottomWeight = cellConfig.borderWidth;
  }

  // Create checkbox box
  const checkboxBox = createTableCheckboxBox(checked);
  cell.appendChild(checkboxBox);

  return cell;
}

/**
 * Create a table cell (for header or body)
 */
async function createTableCell(
  text: string,
  isHeader: boolean,
  isSelected: boolean,
  width: number,
): Promise<FrameNode> {
  const cellConfig = getTableCellConfig();
  const headerConfig = getTableHeaderConfig();
  const bodyCellConfig = getTableBodyCellConfig();
  const selectedRowConfig = getTableSelectedRowConfig();

  const cell = figma.createFrame();
  cell.name = isHeader ? "Header Cell" : "Body Cell";
  cell.resize(width, isHeader ? 44 : 48);

  // Configure as horizontal auto-layout
  cell.layoutMode = "HORIZONTAL";
  cell.primaryAxisAlignItems = "MIN";
  cell.counterAxisAlignItems = "CENTER";
  cell.paddingLeft = cellConfig.padding;
  cell.paddingRight = cellConfig.padding;
  cell.paddingTop = cellConfig.padding;
  cell.paddingBottom = cellConfig.padding;

  // Apply background
  if (isHeader) {
    const bgVar = getVariableByName(headerConfig.bgVariable);
    if (bgVar) {
      bindFillToVariable(cell, bgVar.id);
    }
  } else if (isSelected) {
    const bgVar = getVariableByName(selectedRowConfig.bgVariable);
    if (bgVar) {
      bindFillToVariable(cell, bgVar.id);
    }
  } else {
    cell.fills = [];
  }

  // Apply bottom border
  const borderVar = getVariableByName(cellConfig.borderVariable);
  if (borderVar) {
    bindStrokeToVariable(cell, borderVar.id, cellConfig.borderWidth);
    cell.strokesIncludedInLayout = true;
    // Only bottom border
    cell.strokeTopWeight = 0;
    cell.strokeLeftWeight = 0;
    cell.strokeRightWeight = 0;
    cell.strokeBottomWeight = cellConfig.borderWidth;
  }

  // Create text
  const fontSize = isHeader ? headerConfig.fontSize : bodyCellConfig.fontSize;
  const fontWeight = isHeader
    ? headerConfig.fontWeight
    : bodyCellConfig.fontWeight;
  const textVar = isHeader
    ? headerConfig.textVariable
    : bodyCellConfig.textVariable;

  const textNode = await createTextNode(text, fontSize, fontWeight);
  textNode.name = "Cell Text";

  const textVariable = getVariableByName(textVar);
  if (textVariable) {
    bindTextColorToVariable(textNode, textVariable.id);
  }

  cell.appendChild(textNode);

  return cell;
}

/**
 * Create a table header row with checkbox
 */
async function createTableHeaderRow(
  headers: string[],
  columnWidths: number[],
  checkboxWidth: number,
  checkboxChecked: boolean,
): Promise<FrameNode> {
  const row = figma.createFrame();
  row.name = "Header Row";

  // Configure as horizontal auto-layout
  row.layoutMode = "HORIZONTAL";
  row.primaryAxisAlignItems = "MIN";
  row.counterAxisAlignItems = "MIN";
  row.primaryAxisSizingMode = "AUTO";
  row.counterAxisSizingMode = "AUTO";
  row.itemSpacing = 0;
  row.fills = [];

  // Add checkbox cell first
  const checkboxCell = await createTableCheckboxCell(
    true, // isHeader
    false, // isSelected (header never selected)
    checkboxChecked,
    checkboxWidth,
  );
  row.appendChild(checkboxCell);

  // Add text cells
  for (let i = 0; i < headers.length; i++) {
    const cell = await createTableCell(
      headers[i],
      true, // isHeader
      false, // isSelected
      columnWidths[i],
    );
    row.appendChild(cell);
  }

  return row;
}

/**
 * Create a table body row with checkbox
 */
async function createTableBodyRow(
  rowData: RowData,
  isSelected: boolean,
  columnWidths: number[],
  checkboxWidth: number,
): Promise<FrameNode> {
  const row = figma.createFrame();
  row.name = "Body Row";

  // Configure as horizontal auto-layout
  row.layoutMode = "HORIZONTAL";
  row.primaryAxisAlignItems = "MIN";
  row.counterAxisAlignItems = "MIN";
  row.primaryAxisSizingMode = "AUTO";
  row.counterAxisSizingMode = "AUTO";
  row.itemSpacing = 0;
  row.fills = [];

  // Add checkbox cell first
  const checkboxCell = await createTableCheckboxCell(
    false, // isHeader
    isSelected,
    rowData.checked,
    checkboxWidth,
  );
  row.appendChild(checkboxCell);

  // Add text cells
  for (let i = 0; i < rowData.cells.length; i++) {
    const cell = await createTableCell(
      rowData.cells[i],
      false, // isHeader
      isSelected,
      columnWidths[i],
    );
    row.appendChild(cell);
  }

  return row;
}

/**
 * Create a single Table component
 */
async function createTableComponent(
  config: TableConfig,
): Promise<ComponentNode> {
  const completeConfig = getTableCompleteConfig(config);
  const { sampleData } = completeConfig;

  const component = figma.createComponent();
  component.name = getVariantName(config);
  component.description = `Table with layout=${config.layout}, hasSelectedRow=${config.hasSelectedRow}`;

  // Configure as vertical auto-layout
  component.layoutMode = "VERTICAL";
  component.primaryAxisAlignItems = "MIN";
  component.counterAxisAlignItems = "MIN";
  component.primaryAxisSizingMode = "AUTO";
  component.counterAxisSizingMode = "AUTO";
  component.itemSpacing = 0;
  component.fills = [];

  // Add outer border (matches LayerCard.Primary: ring ring-kumo-fill rounded-lg)
  component.cornerRadius = BORDER_RADIUS.lg;
  component.clipsContent = true; // Clip content to rounded corners
  const outerBorderVar = getVariableByName(VAR_NAMES.color.line);
  if (outerBorderVar) {
    bindStrokeToVariable(
      component,
      outerBorderVar.id,
      FALLBACK_VALUES.strokeWeight,
    );
  }

  // Checkbox column width (w-12 = 48px in Storybook, but we use smaller for compact display)
  const checkboxWidth = 40;

  // Column widths based on layout (excluding checkbox column)
  const columnWidths =
    config.layout === "fixed"
      ? [100, 100, 100] // Equal widths for fixed layout
      : [120, 80, 80]; // Variable widths for auto layout

  // Create header row with checkbox
  const headerRow = await createTableHeaderRow(
    sampleData.headers,
    columnWidths,
    checkboxWidth,
    false, // Header checkbox unchecked (not "select all" in this preview)
  );
  component.appendChild(headerRow);

  // Create body rows with checkboxes
  for (let i = 0; i < sampleData.rows.length; i++) {
    const isSelected = config.hasSelectedRow && i === 1; // Second row is selected

    // Create row data with checkbox state matching selection
    const rowData: RowData = {
      cells: sampleData.rows[i].cells,
      checked: isSelected, // Checkbox checked when row is selected
    };

    const bodyRow = await createTableBodyRow(
      rowData,
      isSelected,
      columnWidths,
      checkboxWidth,
    );

    // Remove bottom border from last row
    if (i === sampleData.rows.length - 1) {
      for (const child of bodyRow.children) {
        if (child.type === "FRAME") {
          (child as FrameNode).strokeBottomWeight = 0;
        }
      }
    }

    component.appendChild(bodyRow);
  }

  return component;
}

/**
 * Generate Table ComponentSet
 *
 * Layout:
 * - Row 1: layout=auto (no selection)
 * - Row 2: layout=auto (with selected row)
 * - Row 3: layout=fixed (no selection)
 * - Row 4: layout=fixed (with selected row)
 *
 * @param page - Target page for components
 * @param startY - Y position to start placing sections
 * @returns The Y position after all sections
 */
export async function generateTableComponents(
  page: PageNode,
  startY: number = 100,
): Promise<number> {
  figma.currentPage = page;

  const components: ComponentNode[] = [];

  // Track row labels: { y, text }
  const rowLabels: { y: number; text: string }[] = [];

  // Layout spacing
  const rowGap = GRID_LAYOUT.rowGap.spacious; // 60px - tables are tall
  const labelColumnWidth = GRID_LAYOUT.labelColumnWidth.wide;

  // Track position for laying out components vertically
  let currentY = 0;

  for (let i = 0; i < TABLE_CONFIGS.length; i++) {
    const config = TABLE_CONFIGS[i];
    const component = await createTableComponent(config);

    // Record row label
    rowLabels.push({ y: currentY, text: getRowLabelText(config) });

    // Position each component vertically with label offset
    component.x = labelColumnWidth;
    component.y = currentY;
    currentY += component.height + rowGap;
    components.push(component);
  }

  // Combine all variants into a single ComponentSet
  const componentSet = figma.combineAsVariants(components, page);
  componentSet.name = "Table";
  componentSet.description =
    "Table component showing layout variants (auto/fixed) and row selection state. This is a simplified static preview of the Table component.";

  // Calculate content dimensions (add label column width)
  const contentWidth = componentSet.width + labelColumnWidth;
  const contentHeight = componentSet.height;

  // Create light mode section
  const lightSection = createModeSection(page, "Table", "light");
  lightSection.frame.resize(
    contentWidth + SECTION_PADDING * 2,
    contentHeight + SECTION_PADDING * 2,
  );

  // Create dark mode section
  const darkSection = createModeSection(page, "Table", "dark");
  darkSection.frame.resize(
    contentWidth + SECTION_PADDING * 2,
    contentHeight + SECTION_PADDING * 2,
  );

  // Move ComponentSet into light section frame
  lightSection.frame.appendChild(componentSet);
  componentSet.x = SECTION_PADDING + labelColumnWidth;
  componentSet.y = SECTION_PADDING;

  // Add row labels to light section
  for (const label of rowLabels) {
    const labelNode = await createRowLabel(
      label.text,
      SECTION_PADDING,
      SECTION_PADDING + label.y + GRID_LAYOUT.labelVerticalOffset.lg,
    );
    lightSection.frame.appendChild(labelNode);
  }

  // Create instances for dark section
  for (const component of components) {
    const instance = component.createInstance();
    instance.x = component.x + SECTION_PADDING + labelColumnWidth;
    instance.y = component.y + SECTION_PADDING;
    darkSection.frame.appendChild(instance);
  }

  // Add row labels to dark section
  for (const label of rowLabels) {
    const labelNode = await createRowLabel(
      label.text,
      SECTION_PADDING,
      SECTION_PADDING + label.y + GRID_LAYOUT.labelVerticalOffset.lg,
    );
    darkSection.frame.appendChild(labelNode);
  }

  // Resize sections to fit content with padding
  const totalWidth = contentWidth + SECTION_PADDING * 2;
  const totalHeight = contentHeight + SECTION_PADDING * 2;

  lightSection.frame.resize(totalWidth, totalHeight);
  darkSection.frame.resize(totalWidth, totalHeight);

  // Add title inside each frame

  // Position sections side by side
  lightSection.frame.x = SECTION_LAYOUT.startX;
  lightSection.frame.y = startY;

  darkSection.frame.x =
    lightSection.frame.x + totalWidth + SECTION_LAYOUT.modeGap;
  darkSection.frame.y = startY;

  logInfo(
    "✅ Generated Table ComponentSet with " +
      components.length +
      " variants (light + dark)",
  );

  return startY + totalHeight + SECTION_GAP;
}

/**
 * Exports for tests and backwards compatibility
 */
export const TABLE_CONFIGS_EXPORT = TABLE_CONFIGS;
export const TABLE_LAYOUT_VALUES = tableComponent.props.layout.values;
export const TABLE_VARIANT_VALUES = tableComponent.props.variant.values;
