// src/lib/updo/interactiveSelect.ts
import {
  createPrompt,
  ExitPromptError,
  isDownKey,
  isEnterKey,
  isSpaceKey,
  isUpKey,
  useKeypress,
  useRef,
  useState
} from "@inquirer/core";
import chalk from "chalk";
var ORANGE = chalk.hex("#ff8800");
var COLOR = {
  gray: chalk.gray,
  green: chalk.green,
  orange: ORANGE,
  red: chalk.red,
  yellow: chalk.yellow
};
function classifyCell(prefix, column, hasValue) {
  if (!hasValue) return "gray";
  if (column === "next") return "orange";
  if (column === "downgrade") return "red";
  if (prefix === "^") {
    if (column === "patch" || column === "minor") return "green";
    return "yellow";
  }
  if (prefix === "~") {
    if (column === "patch") return "green";
    if (column === "minor") return "yellow";
    return "red";
  }
  if (column === "patch") return "yellow";
  return "red";
}
function pad(raw, colored, width) {
  return colored + " ".repeat(Math.max(0, width - raw.length));
}
function dot(isSelected) {
  return isSelected ? chalk.green("\u25CF") : chalk.dim("\u25CB");
}
function valueOf(dep, column) {
  if (column === "patch") return dep.patch;
  if (column === "minor") return dep.minor;
  if (column === "major") return dep.major;
  if (column === "downgrade") return dep.downgrade;
  return dep.next;
}
function selectionFor(column) {
  if (column === "patch") return 0;
  if (column === "minor") return 1;
  if (column === "major") return 2;
  if (column === "next") return 3;
  return 4;
}
function renderCell(dep, column, selection, width) {
  const value = valueOf(dep, column);
  const raw = value ?? "-";
  const cls = classifyCell(dep.preferredRangePrefix, column, value != null && value.length > 0);
  const colored = COLOR[cls](raw);
  const sel = value != null && value.length > 0 ? dot(selection === selectionFor(column)) : " ";
  return `${sel} ${pad(raw, colored, width)}`;
}
function renderHeader(w, shouldIncludeNext, shouldIncludeDowngrade) {
  const parts = [
    "  ",
    chalk.bold("Package".padEnd(w.name)),
    chalk.bold("Current".padEnd(w.current)),
    chalk.bold("  Patch".padEnd(w.patch + 2)),
    chalk.bold("  Minor".padEnd(w.minor + 2)),
    chalk.bold("  Major".padEnd(w.major + 2))
  ];
  if (shouldIncludeNext) parts.push(chalk.bold("  Next".padEnd(w.next + 2)));
  if (shouldIncludeDowngrade) parts.push(chalk.bold("  Down".padEnd(w.downgrade + 2)));
  const header = parts.join("  ");
  const totalWidth = w.name + w.current + w.patch + w.minor + w.major + (shouldIncludeNext ? w.next + 2 : 0) + (shouldIncludeDowngrade ? w.downgrade + 2 : 0) + 24;
  return `${header}
${chalk.gray("\u2500".repeat(totalWidth))}`;
}
function renderRow(dep, selection, isActive, w, shouldIncludeNext, shouldIncludeDowngrade) {
  const pointer = isActive ? chalk.cyan("\u276F") : " ";
  const rawName = dep.name;
  const name = chalk[isActive ? "white" : "gray"](rawName);
  const rawCurrent = dep.current;
  const current = chalk.gray(rawCurrent);
  const patch = renderCell(dep, "patch", selection, w.patch);
  const minor = renderCell(dep, "minor", selection, w.minor);
  const major = renderCell(dep, "major", selection, w.major);
  const next = shouldIncludeNext ? `  ${renderCell(dep, "next", selection, w.next)}` : "";
  const downgrade = shouldIncludeDowngrade ? `  ${renderCell(dep, "downgrade", selection, w.downgrade)}` : "";
  return `${pointer} ${pad(rawName, name, w.name)}  ${pad(rawCurrent, current, w.current)}  ${patch}  ${minor}  ${major}${next}${downgrade}`;
}
function getAvailableSelections(dep) {
  const available = [-1];
  if (dep.patch != null && dep.patch.length > 0) available.push(0);
  if (dep.minor != null && dep.minor.length > 0) available.push(1);
  if (dep.major != null && dep.major.length > 0) available.push(2);
  if (dep.next != null && dep.next.length > 0) available.push(3);
  if (dep.downgrade != null && dep.downgrade.length > 0) available.push(4);
  return available;
}
var RISK_RANK = {
  green: 0,
  yellow: 1,
  red: 2
};
var CLASS_RANK = {
  green: 0,
  yellow: 1,
  red: 2
};
function defaultSelection(dep, options = {}) {
  const candidates = [
    {
      column: "patch",
      selection: 0,
      value: dep.patch
    },
    {
      column: "minor",
      selection: 1,
      value: dep.minor
    },
    {
      column: "major",
      selection: 2,
      value: dep.major
    }
  ];
  const maxRisk = RISK_RANK[options.risk ?? "green"];
  const eligible = candidates.filter((c) => c.value !== void 0).map((c) => {
    const cls = classifyCell(dep.preferredRangePrefix, c.column, true);
    return { ...c, cls: cls === "orange" || cls === "gray" ? "green" : cls };
  }).filter((c) => CLASS_RANK[c.cls] <= maxRisk);
  if (eligible.length === 0) {
    if (dep.downgrade != null && dep.downgrade.length > 0 && maxRisk >= CLASS_RANK.red) return 4;
    return -1;
  }
  if (options.latest ?? false) {
    return eligible.toSorted((a, b) => b.selection - a.selection)[0].selection;
  }
  const sorted = eligible.toSorted((a, b) => {
    if (a.cls !== b.cls) return CLASS_RANK[a.cls] - CLASS_RANK[b.cls];
    return a.selection - b.selection;
  });
  return sorted[0].selection;
}
function getTargetVersion(dep, selection) {
  if (selection === 0) return dep.patch;
  if (selection === 1) return dep.minor;
  if (selection === 2) return dep.major;
  if (selection === 3) return dep.next;
  if (selection === 4) return dep.downgrade;
  return void 0;
}
function computeWidths(rows) {
  let name = 7;
  let current = 7;
  let patch = 5;
  let minor = 5;
  let major = 5;
  let next = 4;
  let downgrade = 4;
  for (const dep of rows) {
    name = Math.max(name, dep.name.length);
    current = Math.max(current, dep.current.length);
    patch = Math.max(patch, (dep.patch ?? "-").length);
    minor = Math.max(minor, (dep.minor ?? "-").length);
    major = Math.max(major, (dep.major ?? "-").length);
    next = Math.max(next, (dep.next ?? "-").length);
    downgrade = Math.max(downgrade, (dep.downgrade ?? "-").length);
  }
  return {
    current,
    downgrade,
    major,
    minor,
    name,
    next,
    patch
  };
}
function renderPage(rows, cursor, selections, w, pageSize, shouldIncludeNext, shouldIncludeDowngrade) {
  const total = rows.length;
  const start = total > pageSize ? Math.max(0, Math.min(cursor - Math.floor(pageSize / 2), total - pageSize)) : 0;
  const end = Math.min(start + pageSize, total);
  const lines = [];
  for (let i = start; i < end; i++) {
    lines.push(renderRow(rows[i], selections[i], i === cursor, w, shouldIncludeNext, shouldIncludeDowngrade));
  }
  if (total > pageSize) {
    if (start > 0) lines.unshift(chalk.dim("  \u2191 more"));
    if (end < total) lines.push(chalk.dim("  \u2193 more"));
  }
  return lines.join("\n");
}
var updoPrompt = createPrompt((config, done) => {
  const {
    rows,
    shouldIncludeNext: isIncludeNext,
    latest: isLatest,
    risk
  } = config;
  const [cursor, setCursor] = useState(0);
  const [tick, setTick] = useState(0);
  const availableSelectionsRef = useRef(rows.map((r) => getAvailableSelections(r)));
  const selectionsRef = useRef(rows.map((r) => defaultSelection(r, { latest: isLatest, risk })));
  const widthsRef = useRef(computeWidths(rows));
  useKeypress((key) => {
    if (key.name === "escape" || key.ctrl && key.name === "c") {
      done([]);
      return;
    }
    if (isEnterKey(key)) {
      const results = [];
      for (const [i, dep] of rows.entries()) {
        const version = getTargetVersion(dep, selectionsRef.current[i]);
        if (version != null && version.length > 0) {
          results.push({
            name: dep.name,
            targetRange: version,
            workspaces: dep.workspaces
          });
        }
      }
      done(results);
      return;
    }
    if (isUpKey(key)) {
      setCursor(Math.max(0, cursor - 1));
    } else if (isDownKey(key)) {
      setCursor(Math.min(rows.length - 1, cursor + 1));
    } else if (isSpaceKey(key)) {
      const available = availableSelectionsRef.current[cursor];
      const currentSel = selectionsRef.current[cursor];
      const currentIdx = available.indexOf(currentSel);
      const nextIdx = (currentIdx + 1) % available.length;
      selectionsRef.current[cursor] = available[nextIdx];
      setTick(tick + 1);
    }
  });
  const w = widthsRef.current;
  const isIncludeDowngrade = rows.some((r) => r.downgrade !== void 0);
  const header = renderHeader(w, isIncludeNext, isIncludeDowngrade);
  const page = renderPage(rows, cursor, selectionsRef.current, w, 20, isIncludeNext, isIncludeDowngrade);
  const selectedCount = selectionsRef.current.filter((s) => s >= 0).length;
  const status = chalk.gray(`  ${selectedCount} isSelected  \u2191/\u2193 navigate  space cycle version  enter confirm`);
  return `${header}
${page}
${status}`;
});
async function interactiveSelect(deps, options = {}) {
  const updatable = deps.filter((d) => d.updateAvailable);
  if (updatable.length === 0) {
    console.log(chalk.green("\nAll packages are up to date!"));
    return [];
  }
  if (!process.stdout.isTTY) {
    console.log(chalk.yellow("Non-interactive environment detected, skipping selection."));
    return [];
  }
  try {
    return await updoPrompt({
      shouldIncludeNext: options.shouldIncludeNext ?? false,
      latest: options.latest ?? false,
      risk: options.risk ?? "green",
      rows: updatable
    });
  } catch (error) {
    if (error instanceof ExitPromptError) {
      return [];
    }
    throw error;
  }
}
export {
  classifyCell,
  defaultSelection,
  interactiveSelect
};
//# sourceMappingURL=interactiveSelect.mjs.map
