"""
Script to apply the refactoring changes to the MangoIT Chatbot codebase.
This script will:
1. Create necessary directories
2. Copy new files to their proper locations
3. Backup the original main.py file
4. Replace main.py with the refactored version
"""

import os
import shutil
import sys
from pathlib import Path


def print_status(message):
    """Print a status message with formatting"""
    print(f"\n[*] {message}")


def print_success(message):
    """Print a success message with formatting"""
    print(f"[✓] {message}")


def print_error(message):
    """Print an error message with formatting"""
    print(f"[✗] {message}")


def create_directory(directory):
    """Create a directory if it doesn't exist"""
    try:
        os.makedirs(directory, exist_ok=True)
        print_success(f"Created directory: {directory}")
        return True
    except Exception as e:
        print_error(f"Failed to create directory {directory}: {str(e)}")
        return False


def copy_file(source, destination):
    """Copy a file from source to destination"""
    try:
        shutil.copy2(source, destination)
        print_success(f"Copied {source} to {destination}")
        return True
    except Exception as e:
        print_error(f"Failed to copy {source} to {destination}: {str(e)}")
        return False


def backup_file(file_path):
    """Create a backup of a file"""
    backup_path = f"{file_path}.backup"
    try:
        if os.path.exists(file_path):
            shutil.copy2(file_path, backup_path)
            print_success(f"Created backup: {backup_path}")
            return True
        else:
            print_error(f"File not found: {file_path}")
            return False
    except Exception as e:
        print_error(f"Failed to create backup of {file_path}: {str(e)}")
        return False


def apply_refactoring():
    """Apply the refactoring changes"""
    # Get the project root directory
    project_root = Path(__file__).parent.absolute()
    
    # Create necessary directories
    print_status("Creating necessary directories...")
    directories = [
        "models",
        "routers",
        "core"
    ]
    
    for directory in directories:
        dir_path = os.path.join(project_root, directory)
        if not create_directory(dir_path):
            print_error(f"Failed to create {directory} directory. Aborting.")
            return False
    
    # Create __init__.py files in each directory
    print_status("Creating __init__.py files...")
    for directory in directories:
        init_file = os.path.join(project_root, directory, "__init__.py")
        with open(init_file, 'w') as f:
            f.write('"""\n{} package\n"""\n'.format(directory.capitalize()))
        print_success(f"Created {init_file}")
    
    # Backup main.py
    print_status("Backing up main.py...")
    main_py = os.path.join(project_root, "main.py")
    if not backup_file(main_py):
        print_error("Failed to backup main.py. Aborting.")
        return False
    
    # Copy new main.py
    print_status("Copying new main.py...")
    new_main_py = os.path.join(project_root, "main.py.new")
    if not os.path.exists(new_main_py):
        print_error(f"New main.py not found at {new_main_py}. Aborting.")
        return False
    
    if not copy_file(new_main_py, main_py):
        print_error("Failed to copy new main.py. Aborting.")
        return False
    
    # Copy model files
    print_status("Copying model files...")
    model_files = [
        ("models/__init__.py", os.path.join(project_root, "models", "__init__.py")),
        ("models/chat.py", os.path.join(project_root, "models", "chat.py")),
        ("models/embedding.py", os.path.join(project_root, "models", "embedding.py")),
        ("models/rag.py", os.path.join(project_root, "models", "rag.py")),
        ("models/user.py", os.path.join(project_root, "models", "user.py"))
    ]
    
    for source_rel, dest in model_files:
        source = os.path.join(project_root, source_rel)
        if not os.path.exists(source):
            print_error(f"Model file not found: {source}. Skipping.")
            continue
        
        if not copy_file(source, dest):
            print_error(f"Failed to copy {source} to {dest}. Skipping.")
    
    # Copy router files
    print_status("Copying router files...")
    router_files = [
        ("routers/__init__.py", os.path.join(project_root, "routers", "__init__.py")),
        ("routers/chat.py", os.path.join(project_root, "routers", "chat.py")),
        ("routers/embedding.py", os.path.join(project_root, "routers", "embedding.py")),
        ("routers/rag.py", os.path.join(project_root, "routers", "rag.py")),
        ("routers/user.py", os.path.join(project_root, "routers", "user.py"))
    ]
    
    for source_rel, dest in router_files:
        source = os.path.join(project_root, source_rel)
        if not os.path.exists(source):
            print_error(f"Router file not found: {source}. Skipping.")
            continue
        
        if not copy_file(source, dest):
            print_error(f"Failed to copy {source} to {dest}. Skipping.")
    
    # Copy core files
    print_status("Copying core files...")
    core_files = [
        ("core/__init__.py", os.path.join(project_root, "core", "__init__.py")),
        ("core/config.py", os.path.join(project_root, "core", "config.py")),
        ("core/dependencies.py", os.path.join(project_root, "core", "dependencies.py"))
    ]
    
    for source_rel, dest in core_files:
        source = os.path.join(project_root, source_rel)
        if not os.path.exists(source):
            print_error(f"Core file not found: {source}. Skipping.")
            continue
        
        if not copy_file(source, dest):
            print_error(f"Failed to copy {source} to {dest}. Skipping.")
    
    # Update documentation
    print_status("Updating documentation...")
    doc_files = [
        ("README.md.new", "README.md"),
        ("API_DOCUMENTATION.md", "API_DOCUMENTATION.md"),
        ("MIGRATION_GUIDE.md", "MIGRATION_GUIDE.md"),
        ("REFACTORING_SUMMARY.md", "REFACTORING_SUMMARY.md")
    ]
    
    for source_rel, dest_rel in doc_files:
        source = os.path.join(project_root, source_rel)
        dest = os.path.join(project_root, dest_rel)
        
        if not os.path.exists(source):
            print_error(f"Documentation file not found: {source}. Skipping.")
            continue
        
        if os.path.exists(dest) and dest_rel != "README.md.new":
            backup_file(dest)
        
        if not copy_file(source, dest):
            print_error(f"Failed to copy {source} to {dest}. Skipping.")
    
    print_status("Refactoring applied successfully!")
    print("\nNext steps:")
    print("1. Run the test script: python test_api.py")
    print("2. Start the server: uvicorn main:app --reload")
    print("3. Check the API documentation: API_DOCUMENTATION.md")
    
    return True


if __name__ == "__main__":
    print_status("Starting refactoring process...")
    
    # Ask for confirmation
    confirm = input("This will apply the refactoring changes to your codebase. Continue? (y/n): ")
    if confirm.lower() != 'y':
        print_status("Refactoring cancelled.")
        sys.exit(0)
    
    # Apply refactoring
    if apply_refactoring():
        print_status("Refactoring completed successfully!")
    else:
        print_status("Refactoring failed. Please check the errors above.")
