import type { Connection } from "../../../types";
import { connectionSubtitle, type LocalShellOption } from "./utils";

export const QUICK_CONNECT_RECENT_LABEL_MAX_LENGTH = 40;

export function truncateQuickConnectRecentLabel(label: string): string {
  if (label.length <= QUICK_CONNECT_RECENT_LABEL_MAX_LENGTH) {
    return label;
  }
  return `${label.slice(0, QUICK_CONNECT_RECENT_LABEL_MAX_LENGTH - 3)}...`;
}

export function quickConnectRecentLabel(connection: Connection): string {
  return truncateQuickConnectRecentLabel(`${connection.name} - ${connectionSubtitle(connection)}`);
}

const DEFAULT_SSH_PORT = 22;

// Decides whether a Quick Connect target should reuse an existing saved
// connection instead of creating a new one. SSH matches by host+user+port.
// Local shells and all other types always create new saved Connections.
export function findMatchingConnection(
  connections: Connection[],
  candidate: Connection,
): Connection | undefined {
  if (candidate.type === "ssh") {
    const port = candidate.port ?? DEFAULT_SSH_PORT;
    return connections.find(
      (c) =>
        c.type === "ssh" &&
        c.host === candidate.host &&
        (c.user ?? "") === (candidate.user ?? "") &&
        (c.port ?? DEFAULT_SSH_PORT) === port &&
        (c.proxyJump ?? "") === (candidate.proxyJump ?? "") &&
        (c.sshSocksProxy ?? "") === (candidate.sshSocksProxy ?? "") &&
        (c.sshSocksProxyUsername ?? "") === (candidate.sshSocksProxyUsername ?? "") &&
        (c.sshSocksProxyInheritDefaults ?? true) === (candidate.sshSocksProxyInheritDefaults ?? true),
    );
  }
  return undefined;
}

export function nextQuickConnectName(connections: Connection[], preferredName: string): string {
  const baseName = preferredName.trim();
  const fallbackName = baseName || "Connection";
  const usedNames = new Set(connections.map((connection) => connection.name));
  if (!usedNames.has(fallbackName)) {
    return fallbackName;
  }

  for (let suffix = 1; ; suffix += 1) {
    const candidate = `${fallbackName} #${suffix}`;
    if (!usedNames.has(candidate)) {
      return candidate;
    }
  }
}

export type ElevatedLocalShellAction =
  | { mode: "embedded"; name: string; shell: string }
  | { mode: "external"; shell: string };

export function elevatedLocalShellAction({
  adminLabel,
  isAppElevated,
  option,
}: {
  adminLabel: string;
  isAppElevated: boolean;
  option: LocalShellOption;
}): ElevatedLocalShellAction {
  const shell = option.value ?? "powershell.exe";
  if (!isAppElevated) {
    return { mode: "external", shell };
  }

  const adminSuffix = ` (${adminLabel})`;
  return {
    mode: "embedded",
    name: option.label.endsWith(adminSuffix) ? option.label : `${option.label}${adminSuffix}`,
    shell,
  };
}
