#!/usr/bin/env node
import {
  useFocusedListItem
} from "./chunk-GG4BSB6S.js";
import {
  useSectionScroll
} from "./chunk-BNQ5O6LE.js";
import {
  CLI_COLORS
} from "./chunk-6OWHQ7HM.js";
import {
  init_esm_shims
} from "./chunk-DHET7RCE.js";

// src/cli/components/wizard/category-grid.tsx
init_esm_shims();
import { useCallback as useCallback2, useMemo, useRef as useRef2 } from "react";
import { Box, Text } from "ink";

// src/cli/components/hooks/use-category-grid-input.ts
init_esm_shims();
import { useCallback, useEffect, useRef } from "react";
import { useInput } from "ink";
var FRAMEWORK_CATEGORY_ID = "web-framework";
var isSectionLocked = (categoryId, categories) => {
  if (categoryId === FRAMEWORK_CATEGORY_ID) {
    return false;
  }
  const frameworkCategory = categories.find((cat) => cat.id === FRAMEWORK_CATEGORY_ID);
  if (!frameworkCategory) return false;
  return !frameworkCategory.options.some((opt) => opt.selected);
};
var findValidStartColumn = (_options) => {
  return 0;
};
var findNextUnlockedIndex = (processed, currentIndex, allCategories) => {
  const length = processed.length;
  if (length === 0) return currentIndex;
  let index = currentIndex;
  let attempts = 0;
  while (attempts < length) {
    index += 1;
    if (index >= length) index = 0;
    const category = processed[index];
    if (category && !isSectionLocked(category.id, allCategories)) {
      return index;
    }
    attempts++;
  }
  return currentIndex;
};
function useCategoryGridInput({
  processedCategories,
  categories,
  focusedRow,
  focusedCol,
  setFocused,
  moveFocus,
  onToggle,
  onToggleLabels
}) {
  const currentRow = processedCategories[focusedRow];
  const currentOptions = currentRow?.sortedOptions || [];
  const currentLocked = currentRow ? isSectionLocked(currentRow.id, categories) : false;
  useEffect(() => {
    if (!currentRow) return;
    const maxCol = currentOptions.length - 1;
    if (focusedCol > maxCol) {
      const newCol = Math.max(0, maxCol);
      setFocused(focusedRow, newCol);
    }
  }, [focusedRow, currentOptions, focusedCol, setFocused, currentRow]);
  useEffect(() => {
    if (currentRow && currentLocked) {
      const nextUnlocked = findNextUnlockedIndex(processedCategories, focusedRow, categories);
      if (nextUnlocked !== focusedRow) {
        const newRowOptions = processedCategories[nextUnlocked]?.sortedOptions || [];
        const newCol = findValidStartColumn(newRowOptions);
        setFocused(nextUnlocked, newCol);
      }
    }
  }, [currentRow, currentLocked, focusedRow, processedCategories, categories, setFocused]);
  const handlerRef = useRef(null);
  handlerRef.current = (input, key) => {
    if (key.tab && key.shift) {
      onToggleLabels();
      return;
    }
    if (key.tab && !key.shift) {
      const nextSection = findNextUnlockedIndex(processedCategories, focusedRow, categories);
      if (nextSection !== focusedRow) {
        const newRowOptions = processedCategories[nextSection]?.sortedOptions || [];
        const newCol = findValidStartColumn(newRowOptions);
        setFocused(nextSection, newCol);
      }
      return;
    }
    if (input === "d" || input === "D") {
      onToggleLabels();
      return;
    }
    if (input === " ") {
      if (currentLocked) return;
      const currentOption = currentOptions[focusedCol];
      if (currentOption) {
        onToggle(currentRow.id, currentOption.id);
      }
      return;
    }
    const isLeft = key.leftArrow || input === "h";
    const isRight = key.rightArrow || input === "l";
    const isUp = key.upArrow || input === "k";
    const isDown = key.downArrow || input === "j";
    if (isLeft) {
      if (currentLocked) return;
      moveFocus("left");
    } else if (isRight) {
      if (currentLocked) return;
      moveFocus("right");
    } else if (isUp) {
      moveFocus("up");
    } else if (isDown) {
      moveFocus("down");
    }
  };
  const stableHandler = useCallback((input, key) => {
    handlerRef.current?.(input, key);
  }, []);
  useInput(stableHandler);
}

// src/cli/components/wizard/category-grid.tsx
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var SYMBOL_REQUIRED = "*";
var findNextValidOption = (options, currentIndex, direction, wrap = true) => {
  const length = options.length;
  if (length === 0) return currentIndex;
  let index = currentIndex + direction;
  if (wrap) {
    if (index < 0) index = length - 1;
    if (index >= length) index = 0;
  } else {
    if (index < 0) index = 0;
    if (index >= length) index = length - 1;
  }
  return index;
};
var getCompatibilityLabel = (option, isLocked) => {
  if (option.selected) return "(selected)";
  if (isLocked) return "(disabled)";
  if (option.state === "recommended") return "(recommended)";
  if (option.state === "discouraged") return "(discouraged)";
  return null;
};
var SkillTag = ({ option, isFocused, isLocked, showLabels }) => {
  const getTextColor = () => {
    if (isLocked) return CLI_COLORS.NEUTRAL;
    if (option.selected) return CLI_COLORS.PRIMARY;
    if (option.state === "recommended") return CLI_COLORS.UNFOCUSED;
    if (option.state === "discouraged") return CLI_COLORS.WARNING;
    return CLI_COLORS.NEUTRAL;
  };
  const getStateBorderColor = () => {
    if (isLocked) return CLI_COLORS.NEUTRAL;
    if (option.selected) return CLI_COLORS.PRIMARY;
    if (option.state === "recommended") return CLI_COLORS.UNFOCUSED;
    if (option.state === "discouraged") return CLI_COLORS.WARNING;
    return CLI_COLORS.UNFOCUSED;
  };
  const textColor = getTextColor();
  const compatibilityLabel = showLabels ? getCompatibilityLabel(option, isLocked) : null;
  return /* @__PURE__ */ jsx(
    Box,
    {
      marginRight: 1,
      borderColor: isFocused ? getStateBorderColor() : CLI_COLORS.NEUTRAL,
      borderStyle: "single",
      flexShrink: 0,
      children: /* @__PURE__ */ jsxs(Fragment, { children: [
        /* @__PURE__ */ jsxs(Text, { color: textColor, bold: true, children: [
          " ",
          option.label,
          " "
        ] }),
        option.scope === "global" && /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WARNING, children: "G " }),
        compatibilityLabel && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
          compatibilityLabel,
          " "
        ] })
      ] })
    }
  );
};
var CategorySection = ({
  isFirst,
  category,
  options,
  isLocked,
  isFocused,
  focusedOptionIndex,
  showLabels
}) => {
  const selectedCount = options.filter((o) => o.selected).length;
  const selectionCounter = category.exclusive ? `(${selectedCount} of 1)` : `(${selectedCount} selected)`;
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: isFirst ? 0 : 1, children: [
    /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
      /* @__PURE__ */ jsx(Text, { dimColor: isLocked, color: isFocused ? "#fff" : "gray", children: category.displayName }),
      category.required && /* @__PURE__ */ jsxs(Text, { color: isLocked ? CLI_COLORS.NEUTRAL : CLI_COLORS.ERROR, dimColor: isLocked, children: [
        " ",
        SYMBOL_REQUIRED
      ] }),
      selectionCounter && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
        " ",
        selectionCounter
      ] })
    ] }),
    /* @__PURE__ */ jsx(Box, { flexDirection: "row", flexWrap: "wrap", marginTop: 0, children: options.map((option, index) => /* @__PURE__ */ jsx(
      SkillTag,
      {
        option,
        isFocused: isFocused && index === focusedOptionIndex && !isLocked,
        isLocked,
        showLabels
      },
      option.id
    )) })
  ] });
};
var CategoryGrid = ({
  categories,
  availableHeight = 0,
  showLabels,
  onToggle,
  onToggleLabels,
  defaultFocusedRow = 0,
  defaultFocusedCol = 0,
  onFocusChange,
  onFocusedSkillChange
}) => {
  const processedCategories = useMemo(
    () => categories.map((category) => ({ ...category, sortedOptions: category.options })),
    [categories]
  );
  const getColCount = useCallback2(
    (row) => processedCategories[row]?.sortedOptions.length ?? 0,
    [processedCategories]
  );
  const isRowLocked = useCallback2(
    (row) => {
      const cat = processedCategories[row];
      return cat ? isSectionLocked(cat.id, categories) : false;
    },
    [processedCategories, categories]
  );
  const findValidCol = useCallback2(
    (row, currentCol, direction) => {
      const options = processedCategories[row]?.sortedOptions || [];
      const catId = processedCategories[row]?.id;
      if (catId && isSectionLocked(catId, categories)) return currentCol;
      return findNextValidOption(options, currentCol, direction, true);
    },
    [processedCategories, categories]
  );
  const handleFocusChange = useCallback2(
    (row, col) => {
      onFocusChange?.(row, col);
      const skill = processedCategories[row]?.sortedOptions[col];
      onFocusedSkillChange?.(skill?.id ?? null);
    },
    [onFocusChange, processedCategories, onFocusedSkillChange]
  );
  const { focusedRow, focusedCol, setFocused, moveFocus } = useFocusedListItem(
    processedCategories.length,
    getColCount,
    {
      wrap: true,
      isRowLocked,
      findValidCol,
      onChange: handleFocusChange,
      initialRow: defaultFocusedRow,
      initialCol: defaultFocusedCol
    }
  );
  const mountedRef = useRef2(false);
  if (!mountedRef.current) {
    mountedRef.current = true;
    const skill = processedCategories[defaultFocusedRow]?.sortedOptions[defaultFocusedCol];
    onFocusedSkillChange?.(skill?.id ?? null);
  }
  useCategoryGridInput({
    processedCategories,
    categories,
    focusedRow,
    focusedCol,
    setFocused,
    moveFocus,
    onToggle,
    onToggleLabels
  });
  const { setSectionRef, scrollEnabled, scrollTopPx } = useSectionScroll({
    sectionCount: processedCategories.length,
    focusedIndex: focusedRow,
    availableHeight
  });
  if (categories.length === 0) {
    return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No categories to display." }) });
  }
  const noShrink = scrollEnabled ? { flexShrink: 0 } : {};
  const sectionElements = processedCategories.map((category, index) => {
    const isLocked = isSectionLocked(category.id, categories);
    return /* @__PURE__ */ jsx(Box, { ref: (el) => setSectionRef(index, el), ...noShrink, children: /* @__PURE__ */ jsx(
      CategorySection,
      {
        category,
        options: category.sortedOptions,
        isLocked,
        isFocused: index === focusedRow,
        focusedOptionIndex: focusedCol,
        showLabels,
        isFirst: index === 0
      }
    ) }, category.id);
  });
  return /* @__PURE__ */ jsx(
    Box,
    {
      flexDirection: "column",
      ...scrollEnabled ? { height: availableHeight, overflow: "hidden" } : { flexGrow: 1 },
      children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: scrollTopPx > 0 ? -scrollTopPx : 0, ...noShrink, children: sectionElements })
    }
  );
};

export {
  CategoryGrid
};
//# sourceMappingURL=chunk-H7WJK7NJ.js.map