#!/usr/bin/env python3
"""
Calculate Go test coverage and generate reports.

This script parses the coverage.out file generated by `go test -coverprofile`,
extracts coverage statistics, and generates formatted reports.
"""

import sys
import re
import os
from typing import Dict, List, Tuple


def parse_coverage_file(coverage_file: str) -> Tuple[float, Dict[str, float]]:
    """
    Parse coverage output file and extract coverage data.

    Args:
        coverage_file: Path to coverage.out file

    Returns:
        Tuple of (total_coverage, package_coverage_dict)
    """
    if not os.path.exists(coverage_file):
        print(f"Error: Coverage file {coverage_file} not found", file=sys.stderr)
        sys.exit(1)

    # Run go tool cover to get coverage data
    import subprocess

    try:
        result = subprocess.run(
            ['go', 'tool', 'cover', '-func', coverage_file],
            capture_output=True,
            text=True,
            check=True
        )
    except subprocess.CalledProcessError as e:
        print(f"Error running go tool cover: {e}", file=sys.stderr)
        sys.exit(1)

    lines = result.stdout.strip().split('\n')
    package_coverage = {}
    total_coverage = 0.0

    for line in lines:
        # Skip empty lines
        if not line.strip():
            continue

        # Check for total coverage line
        if line.startswith('total:'):
            # Extract percentage from "total: (statements) XX.X%"
            match = re.search(r'(\d+\.\d+)%', line)
            if match:
                total_coverage = float(match.group(1))
            continue

        # Parse package/file coverage
        # Format: "package/file.go:function statements coverage%"
        parts = line.split()
        if len(parts) >= 3:
            file_path = parts[0]
            coverage_str = parts[-1]

            # Extract package name from file path
            package = file_path.split(':')[0]
            package_name = '/'.join(package.split('/')[:-1]) if '/' in package else package

            # Extract coverage percentage
            match = re.search(r'(\d+\.\d+)%', coverage_str)
            if match:
                coverage_pct = float(match.group(1))

                # Aggregate by package
                if package_name not in package_coverage:
                    package_coverage[package_name] = []
                package_coverage[package_name].append(coverage_pct)

    # Calculate average coverage per package
    package_avg = {
        pkg: sum(coverages) / len(coverages)
        for pkg, coverages in package_coverage.items()
    }

    return total_coverage, package_avg


def get_coverage_status(coverage: float) -> Tuple[str, str, str]:
    """
    Get coverage status based on percentage.

    Args:
        coverage: Coverage percentage

    Returns:
        Tuple of (emoji, status_text, badge_color)
    """
    if coverage >= 80:
        return '🟢', 'excellent', 'brightgreen'
    elif coverage >= 60:
        return '🟡', 'good', 'yellow'
    elif coverage >= 40:
        return '🟠', 'fair', 'orange'
    else:
        return '🔴', 'needs improvement', 'red'


def generate_coverage_report(coverage_file: str, output_file: str) -> None:
    """
    Generate a detailed coverage report in markdown format.

    Args:
        coverage_file: Path to coverage.out file
        output_file: Path to output markdown file
    """
    import subprocess

    try:
        result = subprocess.run(
            ['go', 'tool', 'cover', '-func', coverage_file],
            capture_output=True,
            text=True,
            check=True
        )
    except subprocess.CalledProcessError as e:
        print(f"Error generating coverage report: {e}", file=sys.stderr)
        sys.exit(1)

    with open(output_file, 'w') as f:
        f.write("## Coverage by Package\n\n")
        f.write("```\n")
        f.write(result.stdout)
        f.write("```\n")


def set_github_output(name: str, value: str) -> None:
    """
    Set GitHub Actions output variable.

    Args:
        name: Output variable name
        value: Output variable value
    """
    github_output = os.environ.get('GITHUB_OUTPUT')
    if github_output:
        with open(github_output, 'a') as f:
            f.write(f"{name}={value}\n")
    else:
        print(f"::set-output name={name}::{value}")


def main():
    """Main entry point."""
    if len(sys.argv) < 2:
        print("Usage: calculate_coverage.py <coverage_file> [output_file]", file=sys.stderr)
        sys.exit(1)

    coverage_file = sys.argv[1]
    output_file = sys.argv[2] if len(sys.argv) > 2 else 'coverage_report.md'

    # Parse coverage data
    total_coverage, package_coverage = parse_coverage_file(coverage_file)

    # Get coverage status
    emoji, status, badge_color = get_coverage_status(total_coverage)

    # Generate detailed report
    generate_coverage_report(coverage_file, output_file)

    # Output results
    print(f"Total Coverage: {total_coverage}%")
    print(f"Status: {status}")
    print(f"Badge Color: {badge_color}")

    # Set GitHub Actions outputs
    set_github_output('coverage', f'{total_coverage}%')
    set_github_output('coverage_num', str(total_coverage))
    set_github_output('status', status)
    set_github_output('emoji', emoji)
    set_github_output('badge_color', badge_color)

    # Print package breakdown
    if package_coverage:
        print("\nCoverage by Package:")
        for package, coverage in sorted(package_coverage.items()):
            print(f"  {package}: {coverage:.1f}%")


if __name__ == '__main__':
    main()
