export const TEAM_COMMAND_NAME = "팀짜기";
export const TEAM_SIZE_OPTION_NAME = "인원";
export const MIN_TEAM_SIZE = 1;
export const MAX_TEAM_SIZE = 99;

export interface TeamMember {
  id: string;
}

export function shuffle<T>(items: readonly T[], random: () => number = Math.random): T[] {
  const shuffled = [...items];

  for (let index = shuffled.length - 1; index > 0; index -= 1) {
    const swapIndex = Math.floor(random() * (index + 1));
    const current = shuffled[index];
    const target = shuffled[swapIndex];

    if (current === undefined || target === undefined) {
      continue;
    }

    shuffled[index] = target;
    shuffled[swapIndex] = current;
  }

  return shuffled;
}

export function makeTeams<T>(
  members: readonly T[],
  teamSize: number,
  random: () => number = Math.random,
): T[][] {
  if (!Number.isInteger(teamSize) || teamSize < MIN_TEAM_SIZE || teamSize > MAX_TEAM_SIZE) {
    throw new RangeError(`팀 인원은 ${MIN_TEAM_SIZE}~${MAX_TEAM_SIZE} 사이의 정수여야 합니다.`);
  }

  const shuffled = shuffle(members, random);
  const teams: T[][] = [];

  for (let index = 0; index < shuffled.length; index += teamSize) {
    teams.push(shuffled.slice(index, index + teamSize));
  }

  return teams;
}

export function parseTeamSize(value: string | undefined): number | null {
  if (!value || !/^\d+$/.test(value)) {
    return null;
  }

  const teamSize = Number(value);
  return Number.isSafeInteger(teamSize) && teamSize >= MIN_TEAM_SIZE && teamSize <= MAX_TEAM_SIZE
    ? teamSize
    : null;
}

function formatMention(member: TeamMember): string {
  return `**<@${member.id}>**`;
}

/**
 * Discord의 메시지 길이 제한을 넘지 않도록 팀 목록을 여러 메시지로 나눕니다.
 */
export function formatTeamMessages(
  teams: readonly (readonly TeamMember[])[],
  maxLength = 1_900,
): string[] {
  if (maxLength < 30) {
    throw new RangeError("메시지 최대 길이가 너무 짧습니다.");
  }

  const lines: string[] = [];

  teams.forEach((team, teamIndex) => {
    const teamNumber = teamIndex + 1;
    let line = `${teamNumber}팀: `;

    team.forEach((member, memberIndex) => {
      const mention = formatMention(member);
      const separator = memberIndex === 0 ? "" : ", ";

      if (`${line}${separator}${mention}`.length > maxLength) {
        lines.push(line);
        line = `${teamNumber}팀 (계속): ${mention}`;
      } else {
        line += `${separator}${mention}`;
      }
    });

    lines.push(line);
  });

  const messages: string[] = [];
  let message = "";

  for (const line of lines) {
    if (!message) {
      message = line;
    } else if (`${message}\n${line}`.length <= maxLength) {
      message += `\n${line}`;
    } else {
      messages.push(message);
      message = line;
    }
  }

  if (message) {
    messages.push(message);
  }

  return messages;
}
