/**
 * Label Component Generator
 *
 * Generates a Label ComponentSet in Figma with various configurations:
 * - Default (text only)
 * - With optional indicator (shows "(optional)")
 * - With tooltip icon
 * - With both optional and tooltip
 *
 * Reads definitions from component-registry.json (the source of truth).
 *
 * @see packages/kumo/src/components/label/label.tsx
 */

import {
  createTextNode,
  bindTextColorToVariable,
  getVariableByName,
  createModeSection,
  createRowLabel,
  FONT_SIZE,
  SECTION_PADDING,
  SECTION_GAP,
  GRID_LAYOUT,
  FALLBACK_VALUES,
  SECTION_LAYOUT,
  SECTION_TITLE,
  SPACING,
  VAR_NAMES,
} from "./shared";
import { createIconInstance, bindIconColor } from "./icon-utils";
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 Label component data from registry
// Use type assertion since Label exists but TypeScript strict typing doesn't include all components
const labelComponent = (registry.components as Record<string, unknown>)
  .Label as {
  name: string;
  description: string;
  props: Record<string, unknown>;
  colors: string[];
};

/**
 * Label configuration options
 */
type LabelConfig = {
  showOptional: boolean;
  showTooltip: boolean;
};

/**
 * All label configurations to generate
 */
const LABEL_CONFIGS: LabelConfig[] = [
  { showOptional: false, showTooltip: false },
  { showOptional: true, showTooltip: false },
  { showOptional: false, showTooltip: true },
  { showOptional: true, showTooltip: true },
];

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

/**
 * Get Label component configuration from registry
 */
export function getLabelComponentConfig() {
  return {
    name: labelComponent.name,
    description: labelComponent.description,
    props: labelComponent.props,
    colors: labelComponent.colors,
  };
}

/**
 * Get layout configuration for Label component
 */
export function getLabelLayoutConfig() {
  return {
    layoutMode: "HORIZONTAL" as const,
    primaryAxisAlignItems: "MIN" as const,
    counterAxisAlignItems: "CENTER" as const,
    primaryAxisSizingMode: "AUTO" as const,
    counterAxisSizingMode: "AUTO" as const,
    itemSpacing: SPACING.xs, // gap-1 = 4px
  };
}

/**
 * Get text styling configuration for Label
 */
export function getLabelTextConfig() {
  return {
    // Main label text: text-base font-medium text-kumo-default
    main: {
      fontSize: FONT_SIZE.base, // 14px
      fontWeight: FALLBACK_VALUES.fontWeight.medium, // 500
      textVariable: VAR_NAMES.text.default,
    },
    // Optional indicator: font-normal text-kumo-strong
    optional: {
      fontSize: FONT_SIZE.base, // 14px
      fontWeight: FALLBACK_VALUES.fontWeight.normal, // 400
      textVariable: VAR_NAMES.text.strong,
    },
  };
}

/**
 * Get icon configuration for tooltip
 */
export function getLabelIconConfig() {
  return {
    name: "ph-info" as const,
    size: FALLBACK_VALUES.iconSize.sm, // size-4 = 16px
    colorVariable: VAR_NAMES.text.strong,
  };
}

/**
 * Get complete Label configuration for a specific variant
 */
export function getLabelCompleteConfig(config: LabelConfig) {
  return {
    showOptional: config.showOptional,
    showTooltip: config.showTooltip,
    layoutConfig: getLabelLayoutConfig(),
    textConfig: getLabelTextConfig(),
    iconConfig: config.showTooltip ? getLabelIconConfig() : null,
  };
}

/**
 * Get all Label variant data (for snapshot testing)
 * Returns intermediate data before Figma API calls
 */
export function getAllLabelVariantData() {
  const componentConfig = getLabelComponentConfig();
  const layoutConfig = getLabelLayoutConfig();
  const textConfig = getLabelTextConfig();
  const iconConfig = getLabelIconConfig();

  return {
    componentConfig,
    layoutConfig,
    textConfig,
    iconConfig,
    configs: LABEL_CONFIGS.map((config) => getLabelCompleteConfig(config)),
  };
}

/**
 * Get variant name for a Label configuration
 */
function getVariantName(config: LabelConfig): string {
  const parts: string[] = [];
  parts.push(`showOptional=${config.showOptional}`);
  parts.push(`showTooltip=${config.showTooltip}`);
  return parts.join(", ");
}

/**
 * Get human-readable label for row labels
 */
function getRowLabel(config: LabelConfig): string {
  const parts: string[] = [];
  if (config.showOptional) parts.push("optional");
  if (config.showTooltip) parts.push("tooltip");
  if (parts.length === 0) return "default";
  return parts.join(" + ");
}

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

/**
 * Create a single Label component
 */
async function createLabelComponent(
  config: LabelConfig,
): Promise<ComponentNode> {
  const completeConfig = getLabelCompleteConfig(config);
  const layoutConfig = completeConfig.layoutConfig;
  const textConfig = completeConfig.textConfig;

  const component = figma.createComponent();
  component.name = getVariantName(config);
  component.description = `Label with showOptional=${config.showOptional}, showTooltip=${config.showTooltip}`;

  // Configure as horizontal auto-layout
  component.layoutMode = layoutConfig.layoutMode;
  component.primaryAxisAlignItems = layoutConfig.primaryAxisAlignItems;
  component.counterAxisAlignItems = layoutConfig.counterAxisAlignItems;
  component.primaryAxisSizingMode = layoutConfig.primaryAxisSizingMode;
  component.counterAxisSizingMode = layoutConfig.counterAxisSizingMode;
  component.itemSpacing = layoutConfig.itemSpacing;
  component.fills = [];

  // Create main label text
  const mainText = await createTextNode(
    "Label",
    textConfig.main.fontSize,
    textConfig.main.fontWeight,
  );
  mainText.name = "Label Text";

  // Bind text color
  const mainTextVar = getVariableByName(textConfig.main.textVariable);
  if (mainTextVar) {
    bindTextColorToVariable(mainText, mainTextVar.id);
  }

  component.appendChild(mainText);

  // Add optional indicator if needed
  if (config.showOptional) {
    const optionalText = await createTextNode(
      "(optional)",
      textConfig.optional.fontSize,
      textConfig.optional.fontWeight,
    );
    optionalText.name = "Optional Indicator";

    // Bind text color
    const optionalTextVar = getVariableByName(textConfig.optional.textVariable);
    if (optionalTextVar) {
      bindTextColorToVariable(optionalText, optionalTextVar.id);
    }

    component.appendChild(optionalText);
  }

  // Add tooltip icon if needed
  if (config.showTooltip && completeConfig.iconConfig) {
    const iconInstance = createIconInstance(
      completeConfig.iconConfig.name,
      completeConfig.iconConfig.size,
    );
    if (iconInstance) {
      iconInstance.name = "Tooltip Icon";
      bindIconColor(iconInstance, completeConfig.iconConfig.colorVariable);
      component.appendChild(iconInstance);
    }
  }

  return component;
}

/**
 * Generate Label ComponentSet
 *
 * Layout:
 * - Row 1: Default (text only)
 * - Row 2: With optional indicator
 * - Row 3: With tooltip icon
 * - Row 4: With both optional and tooltip
 *
 * @param page - Target page for components
 * @param startY - Y position to start placing sections
 * @returns The Y position after all sections
 */
export async function generateLabelComponents(
  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.medium;
  const labelColumnWidth = GRID_LAYOUT.labelColumnWidth.medium;

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

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

    // Record row label
    rowLabels.push({ y: currentY, text: getRowLabel(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 = "Label";
  componentSet.description =
    "Label component with optional indicator and tooltip icon. Used for form field labels.";

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

  // Add contentYOffset for title space inside frame
  const contentYOffset = SECTION_TITLE.height;

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

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

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

  // Add section titles inside frames

  // Add row labels to light section
  for (const label of rowLabels) {
    const labelNode = await createRowLabel(
      label.text,
      SECTION_PADDING,
      SECTION_PADDING +
        contentYOffset +
        label.y +
        GRID_LAYOUT.labelVerticalOffset.sm,
    );
    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 + contentYOffset;
    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 +
        contentYOffset +
        label.y +
        GRID_LAYOUT.labelVerticalOffset.sm,
    );
    darkSection.frame.appendChild(labelNode);
  }

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

  lightSection.section.resizeWithoutConstraints(totalWidth, totalHeight);
  darkSection.section.resizeWithoutConstraints(totalWidth, totalHeight);

  // 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 Label ComponentSet with " +
      components.length +
      " variants (light + dark)",
  );

  return startY + totalHeight + SECTION_GAP;
}

/**
 * Exports for tests and backwards compatibility
 */
export const LABEL_CONFIGS_EXPORT = LABEL_CONFIGS;
