#!/usr/bin/env python3
"""
VNStock User Info Generator - Recovery Tool
Generates ~/.vnstock/user.json file independently
Matches installer's user.json structure exactly
"""

import os
import sys
import json
import uuid
import socket
import platform
import argparse
import subprocess
import hashlib
from pathlib import Path
from datetime import datetime

try:
    import requests
except ImportError:
    requests = None


def get_hardware_uuid() -> str:
    """Get hardware UUID from system"""
    try:
        if platform.system() == "Darwin":
            # macOS: use system_profiler
            result = subprocess.run(
                ["system_profiler", "SPHardwareDataType"],
                capture_output=True,
                text=True,
                timeout=5
            )
            for line in result.stdout.split('\n'):
                if 'UUID' in line:
                    return line.split()[-1]
        elif platform.system() == "Linux":
            # Linux: try /etc/machine-id
            try:
                with open('/etc/machine-id', 'r') as f:
                    return f.read().strip()
            except FileNotFoundError:
                pass
        elif platform.system() == "Windows":
            # Windows: use wmi
            try:
                result = subprocess.run(
                    ["wmic", "os", "get", "serialnumber"],
                    capture_output=True,
                    text=True,
                    timeout=5
                )
                return result.stdout.strip().split('\n')[1]
            except Exception:
                pass
    except Exception:
        pass
    
    # Fallback: generate consistent UUID based on hostname
    return str(uuid.uuid5(
        uuid.NAMESPACE_DNS,
        socket.gethostname()
    ))


def get_mac_address() -> str:
    """Get MAC address"""
    try:
        mac = ':'.join([
            f'{(uuid.getnode() >> elements) & 0xff:02x}'
            for elements in range(0, 2*6, 2)
        ][::-1])
        return mac
    except Exception:
        return 'unknown'


def generate_device_id() -> dict:
    """Generate unique device identifier (matches installer)"""
    try:
        hardware_uuid = get_hardware_uuid()
        mac_address = get_mac_address()
        
        system_info = {
            'platform': platform.platform(),
            'machine': platform.machine(),
            'processor': platform.processor(),
            'system': platform.system(),
            'release': platform.release(),
            'node': platform.node(),
            'python_version': (
                f"{sys.version_info.major}."
                f"{sys.version_info.minor}."
                f"{sys.version_info.micro}"
            )
        }
        
        # Combine for device ID
        device_string = (
            f"{hardware_uuid}_"
            f"{json.dumps(system_info, sort_keys=True)}"
        )
        
        device_id = hashlib.sha256(
            device_string.encode()
        ).hexdigest()[:32]
        
        return {
            'device_id': device_id,
            'hardware_uuid': hardware_uuid,
            'mac_address': mac_address,
            'system_info': system_info
        }
    except Exception as e:
        fallback_id = str(uuid.uuid4()).replace('-', '')
        return {
            'device_id': fallback_id,
            'hardware_uuid': 'unknown',
            'mac_address': 'unknown',
            'system_info': {'error': str(e)}
        }


def get_machine_identifier() -> str:
    """Get machine identifier (UUID) - matches installer"""
    try:
        return str(uuid.uuid5(
            uuid.NAMESPACE_DNS,
            socket.gethostname()
        ))
    except Exception:
        return str(uuid.uuid4())


def get_username_from_api(api_key: str) -> tuple:
    """Get username and email from vnstock API using API key"""
    if not requests:
        return "Unknown", "unknown"
    
    try:
        headers = {'Authorization': f'Bearer {api_key}'}
        url = 'https://vnstocks.com/api/vnstock/user/profile'
        response = requests.get(
            url,
            headers=headers,
            timeout=10
        )
        if response.status_code == 200:
            user_data = response.json()
            username = user_data.get('username', 'Unknown')
            email = user_data.get('email', 'unknown')
            return username, email
    except Exception:
        pass
    
    return 'Unknown', 'unknown'


def is_virtual_environment() -> bool:
    """Check if running in virtual environment"""
    return (
        hasattr(sys, 'real_prefix') or
        (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)
    )


def generate_user_info(
    python_executable: str,
    venv_path: str = None,
    device_info: dict = None,
    api_key: str = None,
    verbose: bool = False
) -> dict:
    """Generate user info dict - matches installer exactly"""
    
    if device_info is None:
        device_info = generate_device_id()
    
    # Get real user info from API if api_key provided
    username = "vnstock_cli_installer"
    email = "unknown"
    if api_key:
        username, email = get_username_from_api(api_key)
        if verbose:
            print(f"[INFO] API: username={username}, email={email}")
    
    python_info = {
        'version': (
            f"{sys.version_info.major}."
            f"{sys.version_info.minor}."
            f"{sys.version_info.micro}"
        ),
        'executable': python_executable,
        'is_virtual_env': is_virtual_environment(),
        'virtual_env_path': venv_path
    }
    
    user_info = {
        "user": username,
        "email": email,
        "uuid": get_machine_identifier(),
        "os": platform.system(),
        "os_version": platform.version(),
        "ip": "unknown",
        "cwd": os.getcwd(),
        "python": python_info,
        "time": datetime.now().isoformat(),
        "device_id": device_info['device_id'],
        "hardware_uuid": device_info['hardware_uuid'],
        "mac_address": device_info['mac_address']
    }
    
    if verbose:
        print(f"[INFO] Generated user_info keys: {list(user_info.keys())}")
    
    return user_info


def main():
    parser = argparse.ArgumentParser(
        description="Generate VNStock user.json file (matches installer format)",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  # Generate user.json (will prompt for API key)
  python3 generate_user_info.py
  
  # Generate with API key
  python3 generate_user_info.py --api-key "your_api_key"
  
  # Generate with venv path
  python3 generate_user_info.py --venv "/path/to/venv"
  
  # Verbose output
  python3 generate_user_info.py --verbose
  
  # Display only (no save)
  python3 generate_user_info.py --display-only
        """
    )
    
    parser.add_argument(
        "--api-key",
        type=str,
        default=None,
        help="API key for fetching user info from server"
    )
    
    parser.add_argument(
        "--venv",
        type=str,
        default=None,
        help="Path to virtual environment"
    )
    
    parser.add_argument(
        "--verbose",
        action="store_true",
        help="Show verbose output"
    )
    
    parser.add_argument(
        "--display-only",
        action="store_true",
        help="Display info without saving"
    )
    
    parser.add_argument(
        "--output",
        type=str,
        default=None,
        help="Custom output path for user.json"
    )
    
    args = parser.parse_args()
    
    # Determine venv path
    venv_path = args.venv or os.environ.get('VIRTUAL_ENV')
    if venv_path:
        venv_path = Path(venv_path)
    
    # Determine output path
    output_path = args.output
    if not output_path:
        config_dir = Path.home() / ".vnstock"
        output_path = config_dir / "user.json"
    else:
        output_path = Path(output_path)
    
    if args.verbose:
        print("\n" + "="*70)
        print("VNStock User Info Generator")
        print("="*70)
    
    # Get API key
    api_key = args.api_key
    
    # Prompt for API key if not provided and not display-only
    if not api_key and not args.display_only:
        print("\nTo fetch accurate user info from VNStock API:")
        print("1. Get API key from: https://vnstocks.com/account")
        print("2. Paste it below (or press Enter to skip)\n")
        
        api_key_input = input(
            "Enter your API key (optional): "
        ).strip()
        if api_key_input:
            api_key = api_key_input
        else:
            print("(Skipping API fetch - will use local info only)")
    
    # Generate device info
    device_info = generate_device_id()
    if args.verbose:
        print(f"[INFO] Device ID: {device_info['device_id']}")
    
    # Fetch API data if API key provided
    if api_key:
        if args.verbose:
            print(f"[INFO] Fetching user data from VNStock API...")
    
    # Generate user info
    if args.verbose:
        print(f"[INFO] Generating user information...")
    
    user_info = generate_user_info(
        python_executable=sys.executable,
        venv_path=str(venv_path) if venv_path else None,
        device_info=device_info,
        api_key=api_key,
        verbose=args.verbose
    )
    
    # Display info
    print("\n" + "="*70)
    print("📋 User Information Generated")
    print("="*70)
    print(f"\nUser: {user_info['user']}")
    print(f"Email: {user_info['email']}")
    print(f"UUID: {user_info['uuid']}")
    print(f"Device ID: {user_info['device_id']}")
    print(f"Hardware UUID: {user_info['hardware_uuid']}")
    print(f"MAC Address: {user_info['mac_address']}")
    print(f"\nOS: {user_info['os']}")
    print(f"OS Version: {user_info['os_version']}")
    print(f"CWD: {user_info['cwd']}")
    
    print(f"\nPython Information:")
    print(f"   Version: {user_info['python']['version']}")
    print(f"   Executable: {user_info['python']['executable']}")
    print(f"   Virtual Env: {user_info['python']['virtual_env_path'] or 'Not set'}")
    print(f"   Is Virtual: {user_info['python']['is_virtual_env']}")
    
    print(f"\nTime: {user_info['time']}")
    print("="*70)
    
    # Save if not display-only
    if not args.display_only:
        # Create config directory
        output_path.parent.mkdir(parents=True, exist_ok=True)
        
        # Save to file
        with open(output_path, 'w') as f:
            json.dump(user_info, f, indent=2)
        
        # Set permissions (owner read-write only)
        output_path.chmod(0o600)
        
        print(f"\n✅ Saved to: {output_path}")
    else:
        print(f"\n⚠️  Display-only mode: File not saved")
        print(f"   To save, run without --display-only flag")
    
    print()


if __name__ == '__main__':
    main()
