#!/usr/bin/env python3
"""Format mypy output to be more blind-friendly.

Converts multi-line mypy output to single-line format:
module.py, function_name, line 123: complete error message including continuation lines
"""

import re
import sys

def format_mypy_output(lines):
    """Format mypy output to single-line entries.

    Captures complete error messages including continuation lines.

    Args:
        lines: Iterable of mypy output lines (from subprocess or stdin).

    Returns:
        Tuple of (formatted_errors, summary_info) where:
        - formatted_errors: List of formatted error strings
        - summary_info: String with "checked N source files" or None
    """
    formatted = []
    current_context = None
    current_error = None
    summary_info = None

    for line in lines:
        line = line.rstrip()

        # Skip empty lines
        if not line:
            continue

        # Match summary line: "Found 56 errors in 5 files (checked 38 source files)"
        summary_match = re.match(r'^Found \d+ errors? in \d+ files? \(checked \d+ source files?\)', line)
        if summary_match:
            summary_info = line  # Capture entire summary line
            continue

        # Match success summary: "Success: no issues found in 38 source files"
        success_match = re.match(r'^Success: no issues found in \d+ source files?', line)
        if success_match:
            summary_info = line  # Capture entire summary line
            continue

        # Match error lines: path/file.py:123:45: error: message [code]
        error_match = re.match(r'^([^:]+):(\d+):\d+: error: (.+)$', line)
        if error_match:
            # Save previous error if any
            if current_error:
                formatted.append(current_error)

            filepath, linenum, message = error_match.groups()
            # Normalize path separators and extract relative path from winston/
            # E.g., "winston/applets/diary.py" -> "applets/diary.py"
            #       "c:/repos/winston/winston/dialog.py" -> "dialog.py"
            normalized_path = filepath.replace('\\', '/')

            # Try to extract path after last occurrence of "/winston/"
            if '/winston/' in normalized_path:
                # Split on last occurrence and take everything after
                parts = normalized_path.rsplit('/winston/', 1)
                module = parts[1] if len(parts) > 1 else parts[0]
            elif normalized_path.startswith('winston/'):
                # Remove "winston/" prefix
                module = normalized_path[8:]  # len('winston/') = 8
            else:
                # Fallback: use just the filename
                module = normalized_path.split('/')[-1]

            # Build context string
            context = current_context if current_context else "module level"

            # Start building current error (may have continuation lines)
            current_error = f"{module}, {context}, line {linenum}: {message}"
            continue

        # Match context lines: file.py: note: In member "method_name" of class "ClassName":
        context_match = re.match(r'^[^:]+: note: In (?:member|function) "([^"]+)"', line)
        if context_match:
            # Save previous error before changing context
            if current_error:
                formatted.append(current_error)
                current_error = None
            current_context = context_match.group(1)
            continue

        # Match class context: file.py: note: In class "ClassName":
        class_match = re.match(r'^[^:]+: note: In class "([^"]+)"', line)
        if class_match:
            # Save previous error before changing context
            if current_error:
                formatted.append(current_error)
                current_error = None
            current_context = f"class {class_match.group(1)}"
            continue

        # Check if this is a continuation line (starts with whitespace or is a bare message continuation)
        # Continuation lines don't start with a file path
        if current_error and not re.match(r'^[^:]+:\d+:', line):
            # This is a continuation of the current error message
            # Skip lines that are just context (^, note:, etc.)
            if line.strip() and not line.strip().startswith('^') and 'note:' not in line:
                # Append to current error, removing leading whitespace
                current_error += " " + line.strip()

    # Save final error if any
    if current_error:
        formatted.append(current_error)

    return formatted, summary_info

if __name__ == '__main__':
    # Print formatted output when run as script
    formatted_errors, summary_info = format_mypy_output(sys.stdin)
    for formatted_line in formatted_errors:
        print(formatted_line)
    if summary_info:
        print(f"\n# {summary_info}", file=sys.stderr)
