export interface ParsedDice {
  count: number;
  sides: number;
  modifier: number;
  raw: string;
}

export interface RollResult {
  rolls: number[];
  modifier: number;
  total: number;
  expression: string;
  error?: string;
}

export function parseDice(expression: string): ParsedDice | null {
  const cleaned = expression.trim().toLowerCase().replace(/\s/g, "");
  const match = cleaned.match(/^(\d*)d(\d+)([+-]\d+)?$/);
  if (!match) return null;

  const count = match[1] ? parseInt(match[1], 10) : 1;
  const sides = parseInt(match[2], 10);
  const modifier = match[3] ? parseInt(match[3], 10) : 0;

  if (count < 1 || count > 100 || sides < 1 || sides > 100) return null;

  return { count, sides, modifier, raw: expression.trim() };
}

export function rollDice(
  expression: string,
  options?: { advantage?: boolean; disadvantage?: boolean },
): RollResult {
  const parsed = parseDice(expression);
  if (!parsed) {
    return {
      rolls: [],
      modifier: 0,
      total: 0,
      expression,
      error: `Couldn't parse: ${expression}`,
    };
  }

  const { count, sides, modifier } = parsed;

  if (
    (options?.advantage || options?.disadvantage) &&
    count === 1 &&
    sides === 20
  ) {
    const roll1 = Math.floor(Math.random() * sides) + 1;
    const roll2 = Math.floor(Math.random() * sides) + 1;
    const chosen = options.advantage
      ? Math.max(roll1, roll2)
      : Math.min(roll1, roll2);
    return {
      rolls: [roll1, roll2],
      modifier,
      total: chosen + modifier,
      expression,
    };
  }

  const rolls: number[] = [];
  for (let i = 0; i < count; i++) {
    rolls.push(Math.floor(Math.random() * sides) + 1);
  }
  const sum = rolls.reduce((a, b) => a + b, 0);

  return {
    rolls,
    modifier,
    total: sum + modifier,
    expression,
  };
}
