#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p python3
"""
Generate all-maintainers.nix using meta.maintainers as source of truth.

This script uses the meta.maintainers system to extract maintainer information
by evaluating Home Manager modules, which is much simpler and more
reliable than parsing files with regex.
"""

import argparse
import inspect
import json
import subprocess
import sys
from pathlib import Path


def get_project_root() -> Path:
    """
    Find the project root directory.

    Tries to find the git repository root. If that fails, falls back to
    locating it relative to this script file.
    """
    try:
        # Ask git for the top-level directory of the current repository.
        git_root_bytes = subprocess.check_output(
            ["git", "rev-parse", "--show-toplevel"], stderr=subprocess.DEVNULL
        )
        return Path(git_root_bytes.decode("utf-8").strip())
    except (subprocess.CalledProcessError, FileNotFoundError):
        # Fallback for when not in a git repo or git is not installed.
        print(
            "Warning: 'git rev-parse --show-toplevel' failed.",
            "Falling back to script location to determine root.",
            "This may not work correctly with flakes.",
            file=sys.stderr,
        )
        # Assumes this script is at: <root>/flake/dev/generate-all-maintainers/
        return Path(__file__).parent.parent.parent.parent.resolve()

class MetaMaintainerGenerator:
    """Generates maintainers list using meta.maintainers from Home Manager evaluation."""

    def __init__(self, hm_root: Path):
        self.hm_root = hm_root
        self.hm_maintainers_file = hm_root / "modules" / "lib" / "maintainers.nix"
        self.output_file = hm_root / "all-maintainers.nix"
        self.extractor_script = hm_root / "lib" / "nix" / "extract-maintainers-meta.nix"

    def extract_maintainers_from_meta(self) -> dict:
        """Extract maintainer information using meta.maintainers."""
        print("🔍 Extracting maintainers using meta.maintainers...")

        try:
            result = subprocess.run([
                "nix", "eval", "--file", str(self.extractor_script), "--json"
            ], capture_output=True, text=True, timeout=60)

            if result.returncode == 0:
                data = json.loads(result.stdout)
                print("✅ Successfully extracted maintainers using meta.maintainers")
                return data
            else:
                print(f"❌ Failed to extract maintainers: {result.stderr}")
                sys.exit(1)

        except subprocess.TimeoutExpired:
            print("❌ Timeout while extracting maintainers")
            sys.exit(1)
        except Exception as e:
            print(f"❌ Error extracting maintainers: {e}")
            sys.exit(1)

    def generate_maintainers_file(self) -> None:
        """Generate the complete all-maintainers.nix file."""
        print("📄 Generating all-maintainers.nix using meta.maintainers...")

        # Extract maintainers using meta.maintainers
        maintainer_data = self.extract_maintainers_from_meta()

        hm_maintainers = maintainer_data["categorized"]["home-manager"]
        nixpkgs_maintainers = maintainer_data["categorized"]["nixpkgs"]
        formatted_maintainers = maintainer_data["formatted"]

        print(f"🏠 Home Manager maintainers: {len(hm_maintainers)}")
        print(f"📦 Nixpkgs maintainers: {len(nixpkgs_maintainers)}")

        with open(self.output_file, 'w') as f:
            f.write(
                inspect.cleandoc("""
              # Home Manager all maintainers list.
              #
              # This file lists all referenced maintainers in Home Manager.
              #
              # This file is automatically generated using meta.maintainers from Home Manager evaluation
              # DO NOT EDIT MANUALLY
              #
              # To regenerate: ./lib/python/generate-all-maintainers.py
              #
            """)
            )

            # Use the formatted maintainers from Nix evaluation
            print("✨ Adding formatted maintainers using lib.generators.toPretty...")
            f.write("\n")
            f.write(formatted_maintainers)
            f.write("\n")

        self.validate_generated_file()
        self.print_statistics(maintainer_data)

    def validate_generated_file(self) -> bool:
        """Validate the generated Nix file syntax."""
        try:
            result = subprocess.run([
                'nix-instantiate', '--eval', str(self.output_file), '--strict'
            ], capture_output=True, text=True, timeout=10)

            if result.returncode == 0:
                print("✅ Generated file has valid Nix syntax")
                return True
            else:
                print("❌ Warning: Generated file has Nix syntax errors")
                print(result.stderr[:500])
                return False
        except Exception as e:
            print(f"Warning: Could not validate file: {e}")
            return False

    def print_statistics(self, maintainer_data: dict) -> None:
        """Print generation statistics."""
        stats = maintainer_data["stats"]

        print(f"✅ Generated {self.output_file}")
        print("📊 Statistics:")
        print(f"   - Total files with maintainers: {stats['totalFiles']}")
        print(f"   - Total unique maintainers: {stats['totalMaintainers']}")
        print(f"   - Home Manager maintainers: {stats['hmMaintainers']}")
        print(f"   - Nixpkgs maintainers: {stats['nixpkgsMaintainers']}")
        print()
        print("🎉 Generation completed successfully using meta.maintainers!")


def main():
    parser = argparse.ArgumentParser(
        description="Generate Home Manager all-maintainers.nix using meta.maintainers"
    )
    parser.add_argument(
        '--root',
        type=Path,
        default=None,
        help='Path to Home Manager root (default: auto-detect)'
    )
    parser.add_argument(
        '--output',
        type=Path,
        default=None,
        help='Output file path (default: <root>/all-maintainers.nix)'
    )

    args = parser.parse_args()

    if args.root:
        hm_root = args.root
    else:
        hm_root = get_project_root()

    if not (hm_root / "modules" / "lib" / "maintainers.nix").exists():
        print(f"Error: Could not find maintainers.nix in {hm_root}")
        print("Please specify --root or run from Home Manager directory")
        sys.exit(1)

    generator = MetaMaintainerGenerator(hm_root)
    if args.output:
        generator.output_file = args.output

    print("🚀 Generating maintainers using meta.maintainers approach...")

    try:
        generator.generate_maintainers_file()
    except KeyboardInterrupt:
        print("\n❌ Generation cancelled by user")
        sys.exit(1)
    except Exception as e:
        print(f"❌ Error generating maintainers file: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()
