export interface ResolveCreateFlowDecisionInput {
  task: string;
  explicitTitle?: string;
  explicitBranchName?: string;
  localBranches: string[];
  handoffBranches: string[];
}

export interface ResolveCreateFlowDecisionResult {
  title: string;
  branchName: string;
}

function firstNonEmptyLine(input: string): string {
  const lines = input
    .split(/\r?\n/)
    .map((line) => line.trim())
    .filter((line) => line.length > 0);
  return lines[0] ?? "";
}

export function deriveFallbackTitle(task: string, explicitTitle?: string): string {
  const source = (explicitTitle && explicitTitle.trim()) || firstNonEmptyLine(task) || "update handoff";
  const explicitPrefixMatch = source.match(/^\s*(feat|fix|docs|refactor):\s+(.+)$/i);
  if (explicitPrefixMatch) {
    const explicitTypePrefix = explicitPrefixMatch[1]!.toLowerCase();
    const explicitSummary = explicitPrefixMatch[2]!
      .split("")
      .map((char) => (/^[a-zA-Z0-9 -]$/.test(char) ? char : " "))
      .join("")
      .split(/\s+/)
      .filter((token) => token.length > 0)
      .join(" ")
      .slice(0, 62)
      .trim();

    return `${explicitTypePrefix}: ${explicitSummary || "update handoff"}`;
  }

  const lowered = source.toLowerCase();

  const typePrefix =
    lowered.includes("fix") || lowered.includes("bug")
      ? "fix"
      : lowered.includes("doc") || lowered.includes("readme")
        ? "docs"
        : lowered.includes("refactor")
          ? "refactor"
          : "feat";

  const cleaned = source
    .split("")
    .map((char) => (/^[a-zA-Z0-9 -]$/.test(char) ? char : " "))
    .join("")
    .split(/\s+/)
    .filter((token) => token.length > 0)
    .join(" ");

  const summary = (cleaned || "update handoff").slice(0, 62).trim();
  return `${typePrefix}: ${summary}`.trim();
}

export function sanitizeBranchName(input: string): string {
  const normalized = input
    .toLowerCase()
    .split("")
    .map((char) => (/^[a-z0-9]$/.test(char) ? char : "-"))
    .join("");

  let result = "";
  let previousDash = false;
  for (const char of normalized) {
    if (char === "-") {
      if (!previousDash && result.length > 0) {
        result += char;
      }
      previousDash = true;
      continue;
    }

    result += char;
    previousDash = false;
  }

  const trimmed = result.replace(/-+$/g, "");
  if (trimmed.length <= 50) {
    return trimmed;
  }
  return trimmed.slice(0, 50).replace(/-+$/g, "");
}

export function resolveCreateFlowDecision(input: ResolveCreateFlowDecisionInput): ResolveCreateFlowDecisionResult {
  const explicitBranch = input.explicitBranchName?.trim();
  const title = deriveFallbackTitle(input.task, input.explicitTitle);
  const generatedBase = sanitizeBranchName(title) || "handoff";

  const branchBase = explicitBranch && explicitBranch.length > 0 ? explicitBranch : generatedBase;

  const existingBranches = new Set(input.localBranches.map((value) => value.trim()).filter((value) => value.length > 0));
  const existingHandoffBranches = new Set(input.handoffBranches.map((value) => value.trim()).filter((value) => value.length > 0));
  const conflicts = (name: string): boolean => existingBranches.has(name) || existingHandoffBranches.has(name);

  if (explicitBranch && conflicts(branchBase)) {
    throw new Error(`Branch '${branchBase}' already exists. Choose a different --name/--branch value.`);
  }

  if (explicitBranch) {
    return { title, branchName: branchBase };
  }

  let candidate = branchBase;
  let index = 2;
  while (conflicts(candidate)) {
    candidate = `${branchBase}-${index}`;
    index += 1;
  }

  return {
    title,
    branchName: candidate,
  };
}
