#!/usr/bin/env python3
"""
Project progress tracker that generates status documentation from Git history.
"""
import os
import sys
import argparse
from datetime import datetime
from typing import Dict, Any, List, Optional

# Add the current directory to the Python path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

# Import our modules
from config import Config
from code_stats import analyze_code_stats
from git_analyzer import GitAnalyzer
from feature_markdown import (
    enrich_features,
    emoji_status,
    extract_features,
    generate_features_md,
)
from template_engine import TemplateEngine
from changelog_generator import update_changelog_file
from roadmap_generator import generate_roadmap


def load_features(features_file: str) -> Dict[str, Dict[str, Any]]:
    """Load features from a Markdown file."""
    # Use the improved extraction function
    return extract_features(features_file)


def update_features(
    features: Dict[str, Dict[str, Any]],
    feature_updates: Dict[str, Dict[str, Any]],
    new_features: Dict[str, Dict[str, Any]],
) -> Dict[str, Dict[str, Any]]:
    """Update features with new information from Git history."""
    updated_features = features.copy()

    # Update existing features
    for feature_key, update in feature_updates.items():
        if feature_key in updated_features:
            updated_features[feature_key].update(update)

    # Add new features
    for feature_key, feature_data in new_features.items():
        if feature_key not in updated_features:
            updated_features[feature_key] = feature_data

    return updated_features


def format_changelog_entries(git_data: Dict[str, Any]) -> List[str]:
    """Format changelog entries from Git data."""
    entries = []

    # Add changelog entries
    for entry in git_data.get("changelog_entries", []):
        entries.append(
            f"- {entry['date']}: {entry['message']} ({entry['commit']})"
        )

    # Add fix entries
    for fix in git_data.get("fixes", []):
        entries.append(
            f"- {fix['date']}: Fixed: {fix['message']} ({fix['commit']})"
        )

    # Add untagged commits
    for commit in git_data.get("untagged_commits", []):
        entries.append(
            f"- {commit['date']}: {commit['message']} ({commit['commit']})"
        )

    return entries


def extract_known_issues(git_data: Dict[str, Any]) -> List[Dict[str, Any]]:
    """Extract known issues from Git data."""
    issues = []

    # Look for issues in the Git data
    for issue in git_data.get("issues", []):
        issues.append(
            {"description": issue.get("message", ""), "status": "open"}
        )

    return issues


def enrich_features(
    features: Dict[str, Dict[str, Any]]
) -> Dict[str, Dict[str, Any]]:
    """Add additional information to features for display purposes."""
    enriched = {}

    for key, data in features.items():
        enriched[key] = data.copy()
        status = data.get("status", "unknown")
        enriched[key]["status_emoji"] = emoji_status(status)

        # Add title-cased key for display
        enriched[key]["display_name"] = key.replace("_", " ").title()

    return enriched


def main():
    """Main function to run the progress tracker."""
    parser = argparse.ArgumentParser(
        description="Track project progress and generate status documentation."
    )
    parser.add_argument(
        "--config",
        default="scripts/track_progress/progress_config.json",
        help="Path to configuration file",
    )
    parser.add_argument("--project", help="Project name (overrides config)")
    parser.add_argument(
        "--output-dir", help="Output directory (overrides config)"
    )
    parser.add_argument("--repo", default=".", help="Repository path")
    parser.add_argument(
        "--verbose", "-v", action="store_true", help="Enable verbose output"
    )
    args = parser.parse_args()

    verbose = args.verbose

    # Load configuration
    config = Config(args.config)

    # Override config with command-line arguments
    if args.project:
        config.set("project_name", args.project)
    if args.output_dir:
        config.set("output_dir", args.output_dir)

    # Ensure output directory exists
    output_dir = config.get("output_dir")
    os.makedirs(output_dir, exist_ok=True)

    # Initialize components
    git_analyzer = GitAnalyzer(args.repo)
    template_engine = TemplateEngine()

    # Get repository information
    repo_info = git_analyzer.get_repo_info()

    # Analyze Git history
    git_data = git_analyzer.analyze_commits(
        limit=config.get("git_log_limit"),
        untagged_limit=config.get("untagged_commit_limit"),
    )

    # Analyze code statistics
    code_stats = analyze_code_stats(
        root_dir=args.repo,
        exclude_dirs=config.get("exclude_dirs"),
        source_extensions=config.get("source_extensions"),
        top_files_limit=config.get("top_files_limit"),
    )

    # Load existing features
    features_file = config.get("features_file")
    if not os.path.isabs(features_file):
        # If it's not an absolute path, make it relative to the repo root, not the output dir
        features_file = os.path.join(args.repo, features_file)

    if verbose:
        print(f"Loading features from: {features_file}")

    features = load_features(features_file)

    if verbose:
        print(f"Loaded {len(features)} features")

    # Update features with Git data
    features = update_features(
        features,
        git_data.get("feature_updates", {}),
        git_data.get("new_features", {}),
    )

    if verbose:
        print(f"Updated features count: {len(features)}")

    # Enrich features with emojis and other display information
    enriched_features = enrich_features(features)

    # Format changelog entries
    changelog_entries = format_changelog_entries(git_data)

    # Extract known issues
    known_issues = extract_known_issues(git_data)

    # Generate roadmap
    roadmap = generate_roadmap(
        git_data.get("milestones", {}), git_data.get("roadmap_items", {})
    )

    # Prepare template context
    context = {
        "project_name": config.get("project_name"),
        "current_date": datetime.now().strftime("%Y-%m-%d"),
        "repo_info": repo_info,
        "stats": code_stats,
        "features": enriched_features,
        "changelog_entries": changelog_entries,
        "known_issues": known_issues,
        "roadmap": roadmap,
    }

    # Generate status document
    status_template = config.get("templates", {}).get(
        "status", "status_template.md"
    )
    status_content = template_engine.render(status_template, context)

    status_file = os.path.join(args.repo, output_dir, config.get("status_doc"))
    os.makedirs(os.path.dirname(status_file), exist_ok=True)
    with open(status_file, "w", encoding="utf-8") as f:
        f.write(status_content)

    # Generate features document using the improved function
    features_content = generate_features_md(
        features, config.get("project_name")
    )

    # Ensure directory exists for features file
    os.makedirs(os.path.dirname(features_file), exist_ok=True)

    # Create backup of original features file
    if os.path.exists(features_file):
        backup_file = (
            f"{features_file}.bak.{datetime.now().strftime('%Y%m%d%H%M%S')}"
        )
        with open(features_file, "r", encoding="utf-8") as src:
            with open(backup_file, "w", encoding="utf-8") as dst:
                dst.write(src.read())
        if verbose:
            print(f"Created backup: {backup_file}")

    # Write the new features file
    with open(features_file, "w", encoding="utf-8") as f:
        f.write(features_content)

    # Update changelog
    changelog_file = config.get(
        "changelog_file", "CHANGELOG.md"
    )  # Default to CHANGELOG.md

    if not os.path.isabs(changelog_file):
        # If it's a relative path, make it relative to the repo root, not the output dir
        changelog_file = os.path.join(args.repo, changelog_file)

    if verbose:
        print(f"Updating changelog file: {changelog_file}")

    # Ensure the directory exists
    changelog_dir = os.path.dirname(changelog_file)
    if changelog_dir:  # Only create directory if there is one
        os.makedirs(changelog_dir, exist_ok=True)

    update_changelog_file(
        git_data.get("changelog_entries", []),
        changelog_file,
        max_entries=config.get("git_log_limit"),
        verbose=verbose,
    )

    print(f"Progress tracking updated:")
    print(f"- Status document: {status_file}")
    print(f"- Features document: {features_file}")
    print(f"- Changelog: {changelog_file}")

    return 0


if __name__ == "__main__":
    sys.exit(main())
