#!/usr/bin/env python3
"""
Version synchronization script for Text Texture Generator.
Updates version information from git tags across all template files.
"""

import os
import sys
import json
import re
import subprocess
from pathlib import Path
from typing import Dict, Tuple, Optional

def get_project_root() -> Path:
    """Get the project root directory."""
    return Path(__file__).parent.parent

def load_config() -> Dict:
    """Load build configuration."""
    config_path = get_project_root() / "build" / "config.json"
    with open(config_path, 'r') as f:
        return json.load(f)

def get_latest_git_tag() -> Optional[str]:
    """Get the latest git tag that matches the version pattern."""
    try:
        # Get all tags sorted by version
        result = subprocess.run(['git', 'tag', '-l', '--sort=-version:refname'], 
                              capture_output=True, text=True, check=True)
        tags = result.stdout.strip().split('\n')
        
        config = load_config()
        pattern = config['versions']['git_tag_pattern']
        version_regex = re.compile(pattern)
        
        for tag in tags:
            if version_regex.match(tag):
                # Extract version number, removing 'v' prefix if present
                match = version_regex.match(tag)
                return match.group(1) if match else None
        
        return None
    except subprocess.CalledProcessError:
        print("Warning: Could not get git tags. Using fallback version.")
        return None

def get_version_info(version_string: str) -> Tuple[str, int, int, int]:
    """Parse version string into components."""
    parts = version_string.split('.')
    if len(parts) != 3:
        raise ValueError(f"Invalid version format: {version_string}")
    
    major, minor, patch = map(int, parts)
    return version_string, major, minor, patch

def create_template_variables(config: Dict, version: str, version_type: str = "full") -> Dict[str, str]:
    """Create template variables for file generation."""
    version_str, major, minor, patch = get_version_info(version)
    
    # Load exclusions configuration for version limits
    exclusions_path = get_project_root() / "build" / "file_exclusions.json"
    with open(exclusions_path, 'r') as f:
        exclusions_config = json.load(f)
    
    # Get version-specific configuration
    version_config = exclusions_config['version_configs'][version_type]
    
    # Define features based on version type
    if version_type == "free":
        enabled_features = ["basic", "preview"]
    else:  # full version
        enabled_features = ["basic", "preview", "image_overlays", "basic_utilities", "advanced_styling", "normal_maps", "presets", "batch_processing", "advanced_utilities", "text_fitting"]
    
    # Parse Blender version
    blender_version = config['project']['blender_version_min']
    blender_parts = blender_version.split('.')
    blender_major, blender_minor = int(blender_parts[0]), int(blender_parts[1])
    blender_patch = int(blender_parts[2]) if len(blender_parts) > 2 else 0
    
    # Format dependencies for TOML
    deps = []
    for dep, version_spec in config['dependencies'].items():
        deps.append(f'{dep} = "{version_spec}"')
    dependencies_str = '\n'.join(deps)
    
    variables = {
        'PROJECT_ID': config['project']['id'],
        'PROJECT_NAME': config['project']['name'],
        'PROJECT_AUTHOR': config['project']['author'],
        'PROJECT_DESCRIPTION': config['project']['description'],
        'PROJECT_CATEGORY': config['project']['category'],
        'PROJECT_LOCATION': config['project']['location'],
        'PROJECT_SUPPORT': config['project']['support'],
        'PROJECT_TAGS': json.dumps(config['project']['tags']),
        'PROJECT_LICENSE': json.dumps(config['project']['license']),
        'VERSION': version_str,
        'VERSION_MAJOR': str(major),
        'VERSION_MINOR': str(minor),
        'VERSION_PATCH': str(patch),
        'VERSION_TYPE': version_type,
        'BLENDER_VERSION_MIN': blender_version,
        'BLENDER_VERSION_MAJOR': str(blender_major),
        'BLENDER_VERSION_MINOR': str(blender_minor),
        'BLENDER_VERSION_PATCH': str(blender_patch),
        'DEPENDENCIES': dependencies_str,
        'ENABLED_FEATURES': json.dumps(enabled_features),
        'MAX_CONCURRENT_OPERATIONS': str(version_config['max_concurrent_operations'])
    }
    
    return variables

def process_template(template_path: Path, output_path: Path, variables: Dict[str, str]):
    """Process a template file and write the output."""
    print(f"Processing template: {template_path} -> {output_path}")
    
    # Read template
    with open(template_path, 'r') as f:
        content = f.read()
    
    # Replace variables
    for key, value in variables.items():
        content = content.replace(f'{{{{{key}}}}}', value)
    
    # Ensure output directory exists
    output_path.parent.mkdir(parents=True, exist_ok=True)
    
    # Write output
    with open(output_path, 'w') as f:
        f.write(content)
    
    print(f"Generated: {output_path}")

def sync_version(version: Optional[str] = None, version_type: str = "full"):
    """Synchronize version across all template files."""
    config = load_config()
    
    # Get version from git tag if not provided
    if version is None:
        version = get_latest_git_tag()
        if version is None:
            print("Warning: No valid git tag found. Using version from current blender_manifest.toml")
            # Fallback to current version
            manifest_path = get_project_root() / "src" / "blender_manifest.toml"
            if manifest_path.exists():
                with open(manifest_path, 'r') as f:
                    for line in f:
                        if line.startswith('version = '):
                            version = line.split('=')[1].strip().strip('"')
                            break
            if version is None:
                version = "1.0.0"  # Ultimate fallback
    
    print(f"Synchronizing version: {version} (type: {version_type})")
    
    # Create template variables
    variables = create_template_variables(config, version, version_type)
    
    # Add edition-specific variables for __init__.py template
    if version_type == "free":
        variables.update({
            "EDITION_SUFFIX": " (Free)",
            "VERSION_PATCH_FINAL": variables['VERSION_PATCH'],
        })
    else:  # full version
        variables.update({
            "EDITION_SUFFIX": " Pro",
            "VERSION_PATCH_FINAL": variables['VERSION_PATCH'],
        })
    
    # Process each template file
    templates_dir = get_project_root() / "build" / "templates"
    for template_file in templates_dir.glob("*.template"):
        # Determine output path
        relative_name = template_file.stem  # Remove .template extension
        if relative_name == "blender_manifest.toml":
            output_path = get_project_root() / "src" / relative_name
        elif relative_name == "constants.py":
            output_path = get_project_root() / "src" / "utils" / relative_name
        else:
            # For other templates, maintain directory structure
            output_path = get_project_root() / "src" / relative_name
        
        process_template(template_file, output_path, variables)
    
    print(f"Version synchronization complete: {version}")

if __name__ == "__main__":
    import argparse
    
    parser = argparse.ArgumentParser(description="Synchronize version information")
    parser.add_argument("--version", help="Version to set (defaults to latest git tag)")
    parser.add_argument("--type", choices=["free", "full"], default="full", 
                       help="Version type (free or full)")
    
    args = parser.parse_args()
    
    try:
        sync_version(args.version, args.type)
    except Exception as e:
        print(f"Error: {e}")
        sys.exit(1)
