#!/usr/bin/env python3
"""
Wesal Social Media App - Installation Script
This script sets up all necessary configuration files and secrets for the Wesal app.
By Saleh Bubshait
"""

import os
import sys
import secrets
import string
import shutil
from pathlib import Path
from typing import Optional

# ANSI color codes
class Colors:
    BLUE = '\033[94m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RED = '\033[91m'
    BOLD = '\033[1m'
    END = '\033[0m'

def print_ascii_logo():
    """Print the Wesal logo in ASCII art with blue color"""
    logo = """
██╗    ██╗███████╗███████╗ █████╗ ██╗     
██║    ██║██╔════╝██╔════╝██╔══██╗██║     
██║ █╗ ██║█████╗  ███████╗███████║██║     
██║███╗██║██╔══╝  ╚════██║██╔══██║██║     
╚███╔███╔╝███████╗███████║██║  ██║███████╗
 ╚══╝╚══╝ ╚══════╝╚══════╝╚═╝  ╚═╝╚══════╝
                                          
    Installation Script
    """
    print(f"{Colors.BLUE}{Colors.BOLD}{logo}{Colors.END}")

def generate_complex_password(length: int = 20) -> str:
    """Generate a complex password with specified requirements"""
    # Define character sets
    lowercase = string.ascii_lowercase
    uppercase = string.ascii_uppercase
    digits = string.digits
    special_chars = "*@!"
    
    # Ensure at least one character from each category
    password_chars = [
        secrets.choice(lowercase),
        secrets.choice(uppercase),
        secrets.choice(digits),
        secrets.choice(special_chars)
    ]
    
    # Fill the rest randomly
    all_chars = lowercase + uppercase + digits + special_chars
    for _ in range(length - 4):
        password_chars.append(secrets.choice(all_chars))
    
    # Shuffle the password
    secrets.SystemRandom().shuffle(password_chars)
    return ''.join(password_chars)

def get_user_input(prompt: str, default: Optional[str] = None) -> str:
    """Get user input with optional default value"""
    if default:
        full_prompt = f"{Colors.YELLOW}{prompt} (default: {default}): {Colors.END}"
    else:
        full_prompt = f"{Colors.YELLOW}{prompt}: {Colors.END}"
    
    user_input = input(full_prompt).strip()
    return user_input if user_input else (default or "")

def print_success(message: str):
    """Print success message in green"""
    print(f"{Colors.GREEN}✓ {message}{Colors.END}")

def print_error(message: str):
    """Print error message in red"""
    print(f"{Colors.RED}✗ {message}{Colors.END}")

def print_info(message: str):
    """Print info message in blue"""
    print(f"{Colors.BLUE}ℹ {message}{Colors.END}")

def create_env_files(hostname: str, port: str, db_name: str, password: str):
    """Create .env and env.properties files"""
    # Create backend resources directory if it doesn't exist
    resources_dir = Path("backend/src/main/resources")
    resources_dir.mkdir(parents=True, exist_ok=True)
    
    # Prepare the environment variables content
    env_content = f"""DB_URL=jdbc:postgresql://{hostname}:{port}/{db_name}
DB_USER=wesaladmin
DB_PASSWORD={password}
DB_DB={db_name}"""
    
    # Write .env file in TOP LEVEL (root directory)
    env_file_path = Path(".env")
    with open(env_file_path, 'w') as f:
        f.write(env_content)
    print_success(f"Created {env_file_path} (top level)")
    
    # Write env.properties file in resources directory
    env_properties_path = resources_dir / "env.properties"
    with open(env_properties_path, 'w') as f:
        f.write(env_content)
    print_success(f"Created {env_properties_path}")

def setup_database_config():
    """Setup database configuration"""
    print(f"\n{Colors.BOLD}📊 Database Configuration{Colors.END}")
    print("Setting up PostgreSQL connection parameters...")
    
    hostname = get_user_input("Database hostname", "db")
    port = get_user_input("Database port", "5432")
    db_name = get_user_input("Database name", "prod")
    
    # Ask if user wants to generate password or provide their own
    generate_pass = get_user_input("Generate complex password automatically? (y/n)", "y").lower()
    
    if generate_pass in ['y', 'yes', '']:
        password = generate_complex_password()
        print_info(f"Generated password: {password}")
    else:
        password = get_user_input("Enter database password")
        if not password:
            print_error("Password cannot be empty. Generating one automatically...")
            password = generate_complex_password()
            print_info(f"Generated password: {password}")
    
    create_env_files(hostname, port, db_name, password)
    return password

def setup_server_config():
    """Setup server configuration for API base URL"""
    print(f"\n{Colors.BOLD}🌐 Server Configuration{Colors.END}")
    print("Setting up server hostname and port for API access...")
    
    server_hostname = get_user_input("Server hostname", "server")
    server_port = get_user_input("Server port", "8080")
    
    # Update the API constants file
    api_constants_path = Path("frontend/lib/constants/api_constants.dart")
    
    if not api_constants_path.exists():
        print_error(f"Could not find {api_constants_path}")
        print_info("You'll need to manually update the API base URL in your constants file")
        return
    
    # Read the existing file
    try:
        with open(api_constants_path, 'r') as f:
            content = f.read()
        
        # Find and replace the baseUrl line
        lines = content.split('\n')
        updated_lines = []
        found_base_url = False
        
        for line in lines:
            if 'static const String baseUrl' in line and '=' in line:
                # Replace the line with the new hostname and port
                indent = line[:len(line) - len(line.lstrip())]  # Preserve indentation
                new_line = f"{indent}static const String baseUrl = 'http://{server_hostname}:{server_port}';"
                updated_lines.append(new_line)
                found_base_url = True
                print_info(f"Updated baseUrl to: http://{server_hostname}:{server_port}")
            else:
                updated_lines.append(line)
        
        if not found_base_url:
            print_error("Could not find 'static const String baseUrl' line in api_constants.dart")
            print_info("You'll need to manually update the API base URL")
            return
        
        # Write the updated content back
        with open(api_constants_path, 'w') as f:
            f.write('\n'.join(updated_lines))
        
        print_success(f"Updated {api_constants_path}")
        
    except Exception as e:
        print_error(f"Error updating API constants file: {e}")
        print_info("You'll need to manually update the API base URL")

def setup_firebase_credentials():
    """Setup Firebase service account credentials"""
    print(f"\n{Colors.BOLD}🔥 Firebase Configuration{Colors.END}")
    
    # Ask if user needs guidance
    need_help = get_user_input("Do you need help finding the Firebase Service Account JSON file? (y/n)", "n").lower()
    
    if need_help in ['y', 'yes']:
        print(f"\n{Colors.BLUE}📋 Steps to get Firebase Service Account JSON:{Colors.END}")
        print("1. Go to https://console.firebase.google.com/")
        print("2. Select your project")
        print("3. Click on the gear icon (Project Settings)")
        print("4. Go to the 'Service accounts' tab")
        print("5. Click 'Generate new private key'")
        print("6. Download the JSON file")
        print("7. Save it in the current directory and name it 'firebase-service-account.json'")
        print()
    
    print_info("Please place your Firebase Service Account JSON file in the current directory")
    print_info("Name the file: 'firebase-service-account.json'")
    
    while True:
        input(f"{Colors.YELLOW}Press Enter when the file is ready...{Colors.END}")
        
        firebase_file = Path("firebase-service-account.json")
        if firebase_file.exists():
            print_success("Firebase service account file found!")
            break
        else:
            print_error("File 'firebase-service-account.json' not found in current directory.")
            retry = get_user_input("Try again? (y/n)", "y").lower()
            if retry not in ['y', 'yes', '']:
                print_error("Skipping Firebase setup...")
                return False
    
    # Copy to backend resources
    backend_resources = Path("backend/src/main/resources")
    backend_resources.mkdir(parents=True, exist_ok=True)
    backend_firebase_path = backend_resources / "firebase-service-account.json"
    
    shutil.copy2(firebase_file, backend_firebase_path)
    print_success(f"Copied Firebase credentials to {backend_firebase_path}")
    
    # Copy to frontend directory (the specified path)
    frontend_firebase_path = Path("/Users/bubshait/Desktop/My life/2025/SWA/wesal_app/frontend/firebase-service-account.json")
    
    try:
        # Create parent directories if they don't exist
        frontend_firebase_path.parent.mkdir(parents=True, exist_ok=True)
        shutil.copy2(firebase_file, frontend_firebase_path)
        print_success(f"Copied Firebase credentials to {frontend_firebase_path}")
    except Exception as e:
        print_error(f"Could not copy to frontend directory: {e}")
        print_info("You may need to manually copy the file to the frontend directory")
    
    return True

def print_summary():
    """Print installation summary"""
    print(f"\n{Colors.BOLD}{Colors.GREEN}🎉 Installation Complete!{Colors.END}")
    print(f"\n{Colors.BOLD}Files created/updated:{Colors.END}")
    print("• .env (top level)")
    print("• backend/src/main/resources/env.properties")
    print("• backend/src/main/resources/firebase-service-account.json")
    print("• frontend/lib/constants/api_constants.dart (updated)")
    print(f"\n{Colors.BOLD}Next steps:{Colors.END}")
    print("1. Run: docker-compose up --build")
    print("2. Access your app at: http://localhost:6060")
    print("3. Access Adminer (DB admin) at: http://localhost:8100")
    print("4. API will be available at: http://localhost:4044")
    print(f"\n{Colors.BLUE}Happy coding! 🚀{Colors.END}")

def main():
    """Main installation function"""
    try:
        # Print logo
        print_ascii_logo()
        
        print("Welcome to the Wesal Social Media App installer!")
        print("This script will help you set up all necessary configuration files.\n")
        
        # Setup database
        db_password = setup_database_config()
        
        # Setup server configuration
        setup_server_config()
        
        # Setup Firebase
        firebase_success = setup_firebase_credentials()
        
        # Print summary
        print_summary()
        
        if not firebase_success:
            print(f"\n{Colors.YELLOW}⚠️  Note: Firebase setup was skipped. You'll need to set it up manually later.{Colors.END}")
            
    except KeyboardInterrupt:
        print(f"\n{Colors.RED}Installation cancelled by user.{Colors.END}")
        sys.exit(1)
    except Exception as e:
        print_error(f"An error occurred: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()