#!/usr/bin/env python3
"""
PPT Master - Batch Project Validation Tool

Checks the structural integrity and compliance of multiple projects at once.

Usage:
    python3 scripts/batch_validate.py examples
    python3 scripts/batch_validate.py projects
    python3 scripts/batch_validate.py --all
    python3 scripts/batch_validate.py examples projects
"""

import argparse
import sys
from collections import defaultdict
from pathlib import Path

from console_encoding import configure_utf8_stdio

configure_utf8_stdio()

try:
    from project_utils import (
        find_all_projects,
        get_project_info,
        validate_project_structure,
        validate_svg_viewbox,
        CANVAS_FORMATS
    )
except ImportError:
    print("Error: Unable to import project_utils module")
    print("Please ensure project_utils.py is in the same directory")
    sys.exit(1)


class BatchValidator:
    """Batch validator"""

    def __init__(self):
        self.results: list[dict[str, object]] = []
        self.summary = {
            'total': 0,
            'valid': 0,
            'has_errors': 0,
            'has_warnings': 0,
            'missing_readme': 0,
            'missing_spec': 0,
            'svg_issues': 0
        }

    def validate_directory(self, directory: str, recursive: bool = False) -> list[dict[str, object]]:
        """
        Validate all projects in a directory

        Args:
            directory: Directory path
            recursive: Whether to recursively search subdirectories

        Returns:
            List of validation results
        """
        dir_path = Path(directory)
        if not dir_path.exists():
            print(f"[ERROR] Directory does not exist: {directory}")
            return []

        print(f"\n[SCAN] Scanning directory: {directory}")
        print("=" * 80)

        projects = find_all_projects(directory)

        if not projects:
            print(f"[WARN] No projects found")
            return []

        print(f"Found {len(projects)} project(s)\n")

        for project_path in projects:
            self.validate_project(str(project_path))

        return self.results

    def validate_project(self, project_path: str) -> dict[str, object]:
        """
        Validate a single project

        Args:
            project_path: Project path

        Returns:
            Validation result dictionary
        """
        self.summary['total'] += 1

        # Get project info
        info = get_project_info(project_path)

        # Validate project structure
        is_valid, errors, warnings = validate_project_structure(project_path)

        # Validate SVG viewBox
        svg_warnings = []
        if info['svg_files']:
            project_path_obj = Path(project_path)
            svg_files = [project_path_obj / 'svg_output' /
                         f for f in info['svg_files']]
            svg_warnings = validate_svg_viewbox(svg_files, info['format'])

        # Aggregate results
        result = {
            'path': project_path,
            'name': info['name'],
            'format': info['format_name'],
            'date': info['date_formatted'],
            'svg_count': info['svg_count'],
            'is_valid': is_valid,
            'errors': errors,
            'warnings': warnings + svg_warnings,
            'has_readme': info['has_readme'],
            'has_spec': info['has_spec']
        }

        self.results.append(result)

        # Update statistics
        if is_valid and not warnings and not svg_warnings:
            self.summary['valid'] += 1
            status = "[OK]"
        elif errors:
            self.summary['has_errors'] += 1
            status = "[ERROR]"
        else:
            self.summary['has_warnings'] += 1
            status = "[WARN]"

        if not info['has_readme']:
            self.summary['missing_readme'] += 1
        if not info['has_spec']:
            self.summary['missing_spec'] += 1
        if svg_warnings:
            self.summary['svg_issues'] += 1

        # Print result
        print(f"{status} {info['name']}")
        print(f"   Path: {project_path}")
        print(
            f"   Format: {info['format_name']} | SVG: {info['svg_count']} file(s) | Date: {info['date_formatted']}")

        if errors:
            print(f"   [ERROR] Errors ({len(errors)}):")
            for error in errors:
                print(f"      - {error}")

        if warnings or svg_warnings:
            all_warnings = warnings + svg_warnings
            print(f"   [WARN] Warnings ({len(all_warnings)}):")
            for warning in all_warnings[:3]:  # Only show first 3 warnings
                print(f"      - {warning}")
            if len(all_warnings) > 3:
                print(f"      ... and {len(all_warnings) - 3} more warning(s)")

        print()

        return result

    def print_summary(self) -> None:
        """Print a summary of validation results."""
        print("\n" + "=" * 80)
        print("[Summary] Validation Summary")
        print("=" * 80)

        print(f"\nTotal projects: {self.summary['total']}")
        print(
            f"  [OK] Fully valid: {self.summary['valid']} ({self._percentage(self.summary['valid'])}%)")
        print(
            f"  [WARN] With warnings: {self.summary['has_warnings']} ({self._percentage(self.summary['has_warnings'])}%)")
        print(
            f"  [ERROR] With errors: {self.summary['has_errors']} ({self._percentage(self.summary['has_errors'])}%)")

        print(f"\nCommon issues:")
        print(f"  Missing README.md: {self.summary['missing_readme']} project(s)")
        print(f"  Missing design spec: {self.summary['missing_spec']} project(s)")
        print(f"  SVG format issues: {self.summary['svg_issues']} project(s)")

        # Group statistics by format
        format_stats = defaultdict(int)
        for result in self.results:
            format_stats[result['format']] += 1

        if format_stats:
            print(f"\nCanvas format distribution:")
            for fmt, count in sorted(format_stats.items(), key=lambda x: x[1], reverse=True):
                print(f"  {fmt}: {count} project(s)")

        # Provide fix suggestions
        if self.summary['has_errors'] > 0 or self.summary['has_warnings'] > 0:
            print(f"\n[TIP] Fix suggestions:")

            if self.summary['missing_readme'] > 0:
                print(f"  1. Create documentation for projects missing README")
                print(
                    f"     Reference: examples/google_annual_report_ppt169_20251116/README.md")

            if self.summary['svg_issues'] > 0:
                print(f"  2. Check SVG root viewBox settings")
                print(f"     The SVG root viewBox is the export canvas authority")

            if self.summary['missing_spec'] > 0:
                print(f"  3. Add design specification files")

    def _percentage(self, count: int) -> int:
        """Calculate percentage"""
        if self.summary['total'] == 0:
            return 0
        return int(count / self.summary['total'] * 100)

    def export_report(self, output_file: str = 'validation_report.txt') -> None:
        """
        Export validation report to file

        Args:
            output_file: Output file path
        """
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write("PPT Master Project Validation Report\n")
            f.write("=" * 80 + "\n\n")

            for result in self.results:
                status = "[OK] Valid" if result['is_valid'] and not result['warnings'] else \
                    "[ERROR] Error" if result['errors'] else "[WARN] Warning"

                f.write(f"{status} - {result['name']}\n")
                f.write(f"Path: {result['path']}\n")
                f.write(
                    f"Format: {result['format']} | SVG: {result['svg_count']} file(s)\n")

                if result['errors']:
                    f.write(f"\nErrors:\n")
                    for error in result['errors']:
                        f.write(f"  - {error}\n")

                if result['warnings']:
                    f.write(f"\nWarnings:\n")
                    for warning in result['warnings']:
                        f.write(f"  - {warning}\n")

                f.write("\n" + "-" * 80 + "\n\n")

            # Write summary
            f.write("\n" + "=" * 80 + "\n")
            f.write("Validation Summary\n")
            f.write("=" * 80 + "\n\n")
            f.write(f"Total projects: {self.summary['total']}\n")
            f.write(f"Fully valid: {self.summary['valid']}\n")
            f.write(f"With warnings: {self.summary['has_warnings']}\n")
            f.write(f"With errors: {self.summary['has_errors']}\n")

        print(f"\n[REPORT] Validation report exported: {output_file}")


def build_parser() -> argparse.ArgumentParser:
    """Build the command-line parser."""
    parser = argparse.ArgumentParser(
        description="Validate one or more PPT Master project directories.",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""Examples:
  python3 scripts/batch_validate.py examples
  python3 scripts/batch_validate.py projects
  python3 scripts/batch_validate.py examples projects
  python3 scripts/batch_validate.py --all
""",
    )
    parser.add_argument("directories", nargs="*", help="Directories to scan")
    parser.add_argument("--all", action="store_true", help="Validate examples and projects")
    parser.add_argument("--export", action="store_true", help="Write a validation report")
    parser.add_argument(
        "--output",
        default="validation_report.txt",
        help="Report path when --export is used",
    )
    return parser


def main(argv: list[str] | None = None) -> int:
    """Run the CLI entry point."""
    parser = build_parser()
    args = parser.parse_args(argv)

    validator = BatchValidator()

    if args.all:
        directories = ['examples', 'projects']
    else:
        directories = args.directories

    if not directories:
        parser.print_help()
        return 0

    # Validate each directory
    for directory in directories:
        if Path(directory).exists():
            validator.validate_directory(directory)
        else:
            print(f"[WARN] Skipping non-existent directory: {directory}\n")

    # Print summary
    validator.print_summary()

    # Export report (if specified)
    if args.export:
        validator.export_report(args.output)

    # Return exit code
    if validator.summary['has_errors'] > 0:
        return 1
    elif validator.summary['has_warnings'] > 0:
        return 2
    return 0


if __name__ == '__main__':
    raise SystemExit(main())
