/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

export interface CommitMessage {
  subject: string;
  body: string[];
  footer: string[];
  hasTrailingBlankLine: boolean;
}

export interface FormattingError {
  type: ErrorType;
  line?: number;
  message: string;
}

export enum ErrorType {
  SUBJECT_TOO_LONG,
  LINE_TOO_LONG,
  MISSING_BLANK_LINE,
  EXTRA_BLANK_LINE,
  INVALID_INDENTATION,
  TRAILING_SPACES,
  COMMENT_LINE,
  LEADING_SPACES,
}

const MAX_SUBJECT_LENGTH = 72;
const MAX_LINE_LENGTH = 72;
const INDENTATION_THRESHOLD = 4;
const BULLET_POINT_REGEX = /^\s*[-+*#]\s/;
const FOOTER_REGEX = /^([\w-]+):[ \t]+(.+)$/;

/*
 * Check if last line of "Body" follows the "footer" format and if yes, then transfer it to the "footer section"
 * So if the commit message is
 * Foo
 *
 * Footer1: val1
 *
 * Footer2: val2
 *
 * Current message.footer will only contain val2 and the rest will be considered in the body
 * Note: This does not support multi-line footers.
 */

function portFootersFromBody(message: CommitMessage): CommitMessage {
  const footersToPortOver = [];
  for (let i = message.body.length - 1; i >= 0; i--) {
    const line = message.body[i];
    const match = line.match(FOOTER_REGEX);
    // If it's a footer line or an empty blank line, then we remove it from the body
    if (match || line.trim() === '') {
      if (line.trim() !== '') {
        footersToPortOver.push(line);
      }
      message.body.pop();
    } else {
      break;
    }
  }
  if (footersToPortOver.length > 0) {
    message.footer.unshift(...footersToPortOver.reverse());
  }
  return message;
}

function formatCommitMessage(message: CommitMessage): CommitMessage {
  const formattedSubject = formatSubject(message.subject);
  message = portFootersFromBody(message);
  const formattedBody = formatBody(message.body);
  const formattedFooter = formatFooter(message.footer);

  return {
    subject: formattedSubject,
    body: formattedBody,
    footer: formattedFooter,
    hasTrailingBlankLine: message.hasTrailingBlankLine,
  };
}

function formatSubject(subject: string): string {
  return subject.trim();
}

function formatBody(body: string[]): string[] {
  let inCodeBlock = false;
  let paragraphLines: string[] = [];
  const formattedBody: string[] = [];
  let previousWasBulletPoint = false;
  let previousWasEmpty = true; // Track if previous line was empty

  for (const line of body) {
    if (line.trim().startsWith('```')) {
      inCodeBlock = !inCodeBlock;
      formattedBody.push(line.trimEnd());
      previousWasEmpty = false;
      continue;
    }

    if (inCodeBlock || isUntouchedLine(line, previousWasEmpty)) {
      if (!inCodeBlock) {
        previousWasBulletPoint = BULLET_POINT_REGEX.test(line);
      }
      if (paragraphLines.length > 0) {
        formattedBody.push(...splitParagraph(paragraphLines.join(' ')));
      }
      paragraphLines = []; // Reset paragraph
      formattedBody.push(line.trimEnd());
      previousWasEmpty = false;
      continue;
    }

    if (previousWasBulletPoint && line.startsWith('  ')) {
      formattedBody.push(line.trimEnd());
      previousWasEmpty = false;
      continue;
    }

    if (line.trim() === '') {
      if (paragraphLines.length > 0) {
        formattedBody.push(...splitParagraph(paragraphLines.join(' ')));
        paragraphLines = [];
      }
      formattedBody.push('');
      previousWasBulletPoint = false;
      previousWasEmpty = true;
    } else {
      paragraphLines.push(line.trim());
      previousWasEmpty = false;
    }
  }

  if (paragraphLines.length > 0) {
    formattedBody.push(...splitParagraph(paragraphLines.join(' ')));
  }

  return removeConsecutiveBlankLines(formattedBody);
}

function formatFooter(footer: string[]): string[] {
  const formattedFooter = footer.map(line => line.trim());
  return removeConsecutiveBlankLines(formattedFooter);
}
/**
 * Returns true if the line will not be modified by the formatter.
 * For example, quotes, bullet points, and indented lines are untouched.
 */
function isUntouchedLine(line: string, previousWasEmpty: boolean): boolean {
  return (
    line.trimStart().startsWith('> ') ||
    (line.length >= INDENTATION_THRESHOLD &&
      line.substring(0, INDENTATION_THRESHOLD).trim() === '') ||
    BULLET_POINT_REGEX.test(line) ||
    // Check if line is part of a list by looking for any indentation,
    // but only if not first line in paragraph
    (!previousWasEmpty &&
      line.trimStart().length > 0 &&
      line !== line.trimStart())
  );
}

function splitParagraph(paragraph: string): string[] {
  const words = paragraph.split(/\s+/);
  const lines: string[] = [];
  let currentLine = '';

  for (const word of words) {
    if (word.length > MAX_LINE_LENGTH) {
      if (currentLine.length > 0) {
        lines.push(currentLine);
        currentLine = '';
      }
      lines.push(word);
    } else if (
      currentLine.length > 0 &&
      currentLine.length + word.length + 1 > MAX_LINE_LENGTH
    ) {
      lines.push(currentLine);
      currentLine = word;
    } else {
      currentLine += (currentLine ? ' ' : '') + word;
    }
  }

  if (currentLine) {
    lines.push(currentLine);
  }

  return lines;
}

function removeConsecutiveBlankLines(lines: string[]): string[] {
  const filteredLines: string[] = [];
  let previousLineBlank = false;

  for (const line of lines) {
    const isBlank = line.trim() === '';
    if (!isBlank || !previousLineBlank) {
      filteredLines.push(line);
    }
    previousLineBlank = isBlank;
  }

  // Remove leading and trailing blank lines
  while (filteredLines.length > 0 && filteredLines[0].trim() === '') {
    filteredLines.shift();
  }
  while (
    filteredLines.length > 0 &&
    filteredLines[filteredLines.length - 1].trim() === ''
  ) {
    filteredLines.pop();
  }
  return filteredLines;
}

function detectFormattingErrors(
  message: CommitMessage,
  messageString: string
): FormattingError[] {
  const errors: FormattingError[] = [];

  // Check subject
  if (message.subject.length > MAX_SUBJECT_LENGTH) {
    errors.push({
      type: ErrorType.SUBJECT_TOO_LONG,
      line: 1,
      message: `Subject exceeds ${MAX_SUBJECT_LENGTH} characters`,
    });
  }

  if (message.subject.startsWith(' ')) {
    errors.push({
      type: ErrorType.LEADING_SPACES,
      line: 1,
      message: 'Subject should not start with spaces',
    });
  }

  if (message.subject.endsWith(' ')) {
    errors.push({
      type: ErrorType.TRAILING_SPACES,
      line: 1,
      message: 'Subject should not end with spaces',
    });
  }

  const lines = messageString.split('\n');
  for (let i = 0; i < lines.length; i++) {
    if (lines[i].trim().startsWith('#')) {
      errors.push({
        type: ErrorType.COMMENT_LINE,
        line: i + 1, // Line numbers are 1-based
        message:
          "'#' at line start is a comment marker in Git. Line will be ignored",
      });
    }
  }

  // Check for extra blank lines using the raw messageString
  for (let i = 0; i < lines.length; i++) {
    if (i > 0 && lines[i].trim() === '' && lines[i - 1].trim() === '') {
      const isBetweenSubjectAndBody = i === 1 && message.body.length > 0;
      const isBetweenBodyAndFooter =
        i === message.body.length + (message.subject ? 1 : 0) &&
        message.footer.length > 0;
      const isAtEndOfFooter =
        i === lines.length - 1 && message.footer.length > 0;

      if (
        !isBetweenSubjectAndBody &&
        !isBetweenBodyAndFooter &&
        !isAtEndOfFooter
      ) {
        errors.push({
          type: ErrorType.EXTRA_BLANK_LINE,
          line: i + 1, // Line numbers are 1-based
          message: 'Consecutive blank lines are not allowed',
        });
      }
    }
  }

  // Check body
  let lineNumber = 3;
  let inCodeBlock = false;

  for (const line of message.body) {
    if (line.trim().startsWith('```')) {
      inCodeBlock = !inCodeBlock;
    }

    if (
      !inCodeBlock &&
      !isUntouchedLine(line, false) &&
      line.length > MAX_LINE_LENGTH &&
      !line.includes('://') // Don't flag long URLs
    ) {
      errors.push({
        type: ErrorType.LINE_TOO_LONG,
        line: lineNumber,
        message: `Line exceeds ${MAX_LINE_LENGTH} characters`,
      });
    }
    if (line.endsWith(' ')) {
      errors.push({
        type: ErrorType.TRAILING_SPACES,
        line: lineNumber,
        message: 'Line should not end with spaces',
      });
    }
    lineNumber++;
  }

  // Check footer
  lineNumber = message.body.length + 4;
  for (const line of message.footer) {
    if (line.trim().startsWith('```')) {
      inCodeBlock = !inCodeBlock;
    }

    if (
      !inCodeBlock &&
      !isUntouchedLine(line, false) &&
      line.length > MAX_LINE_LENGTH &&
      !line.includes('://') // Don't flag long URLs
    ) {
      errors.push({
        type: ErrorType.LINE_TOO_LONG,
        line: lineNumber,
        message: `Line exceeds ${MAX_LINE_LENGTH} characters`,
      });
    }
    if (line.endsWith(' ')) {
      errors.push({
        type: ErrorType.TRAILING_SPACES,
        line: lineNumber,
        message: 'Line should not end with spaces',
      });
    }
    if (line.startsWith(' ')) {
      errors.push({
        type: ErrorType.LEADING_SPACES,
        line: lineNumber,
        message: 'Line should not start with spaces',
      });
    }
    lineNumber++;
  }

  return errors;
}

export function parseCommitMessageString(messageString: string): CommitMessage {
  const lines = messageString.split('\n');
  // Remove leading blank lines
  while (lines.length > 0 && lines[0].trim() === '') {
    lines.shift();
  }

  let subject = '';
  let body: string[] = [];
  let footer: string[] = [];
  let hasTrailingBlankLine = false;

  if (lines.length === 0) {
    return {subject, body, footer, hasTrailingBlankLine}; // Handle empty input
  }

  if (lines.length === 1) {
    subject = lines[0];
    return {subject, body, footer, hasTrailingBlankLine}; // Single line case
  }

  subject = lines[0]; // Subject is always the first line
  hasTrailingBlankLine =
    lines.length > 0 && lines[lines.length - 1].trim() === '';

  const footerStartIndex = findStartOfParagraph(
    lines,
    hasTrailingBlankLine ? lines.length - 2 : lines.length - 1
  );

  footer = lines.slice(footerStartIndex, lines.length);
  if (hasTrailingBlankLine) {
    footer.pop();
  }

  // Extract body lines, removing all leading/trailing blank lines
  body = lines.slice(
    firstNonEmptyLineIndex(lines, 1, /* direction */ 1),
    firstNonEmptyLineIndex(lines, footerStartIndex - 1, /* direction */ -1) + 1
  );

  // Check if footer contains any lines in the format "key: value"
  // If not, move footer lines to body and make footer empty
  // This is typically the case when creating a new commit message and the footer is not yet formatted
  const hasFormattedFooterLine = footer.some(line =>
    FOOTER_REGEX.test(line.trim())
  );
  if (!hasFormattedFooterLine && footer.length > 0) {
    // If body is not empty, add a blank line before appending footer
    if (body.length > 0) {
      body.push('');
    }
    body = body.concat(footer);
    footer = [];
  }

  return {subject, body, footer, hasTrailingBlankLine};
}

function findStartOfParagraph(
  lines: string[],
  lastLineInParagraph: number
): number {
  for (let i = lastLineInParagraph; i >= 0; i--) {
    if (lines[i].trim() === '') {
      return i + 1;
    }
  }
  // on line 0 is subject
  return 1;
}

/**
 * Returns the index of the first non-empty line in the given direction.
 *
 * @param lines The lines of the commit message.
 * @param index The starting index.
 * @param direction The direction to search in (1 for forward, -1 for backward).
 * @return The index of the first non-empty line, or the index of the last line if no non-empty lines are found.
 */
function firstNonEmptyLineIndex(
  lines: string[],
  index: number,
  direction: number
): number {
  while (index >= 0 && index < lines.length && lines[index].trim() === '') {
    index += direction;
  }
  return index;
}

function formatCommitMessageToString(message: CommitMessage): string {
  let result = message.subject;
  if (message.body.length > 0) {
    result += '\n\n' + message.body.join('\n');
  }
  if (message.footer.length > 0) {
    result += '\n\n' + message.footer.join('\n');
  }
  if (message.hasTrailingBlankLine) {
    result += '\n';
  }
  return result;
}

export function formatCommitMessageString(messageString: string): string {
  const commitMessage = parseCommitMessageString(messageString);
  const formattedMessage = formatCommitMessage(commitMessage);
  return formatCommitMessageToString(formattedMessage);
}

export function detectFormattingErrorsInString(
  messageString: string
): FormattingError[] {
  const commitMessage = parseCommitMessageString(messageString);
  return detectFormattingErrors(commitMessage, messageString);
}

export const TEST_ONLY = {parseCommitMessageString};
