#!/usr/bin/env python3
"""
Python entrypoint script for TimeTracker Docker container
This avoids shell script line ending issues and provides better error handling
"""

import os
import sys
import time
import subprocess
import traceback
import psycopg2
from urllib.parse import urlparse

def log(message):
    """Log message with timestamp"""
    from datetime import datetime
    timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    print(f"[{timestamp}] {message}")

def wait_for_database():
    """Wait for database to be ready"""
    log("Waiting for database to be available...")
    
    db_url = os.getenv('DATABASE_URL')
    if not db_url:
        log("✗ DATABASE_URL environment variable not set")
        return False
    
    log(f"Database URL: {db_url}")
    
    max_attempts = 30
    retry_delay = 2
    
    for attempt in range(1, max_attempts + 1):
        log(f"Attempt {attempt}/{max_attempts} to connect to database...")
        
        try:
            if db_url.startswith('postgresql'):
                # Parse connection string using urlparse for proper handling
                # Handle both postgresql:// and postgresql+psycopg2:// schemes
                if db_url.startswith('postgresql+psycopg2://'):
                    parsed_url = urlparse(db_url.replace('postgresql+psycopg2://', 'postgresql://'))
                else:
                    parsed_url = urlparse(db_url)
                
                # Extract connection parameters
                user = parsed_url.username or 'timetracker'
                password = parsed_url.password or 'timetracker'
                host = parsed_url.hostname or 'db'
                port = parsed_url.port or 5432
                # Remove leading slash from path to get database name
                database = parsed_url.path.lstrip('/') or 'timetracker'
                
                conn = psycopg2.connect(
                    host=host,
                    port=port,
                    database=database,
                    user=user,
                    password=password,
                    connect_timeout=5
                )
                conn.close()
                log("✓ PostgreSQL database is available")
                return True
                
            elif db_url.startswith('sqlite://'):
                db_file = db_url.replace('sqlite://', '')
                if os.path.exists(db_file) or os.access(os.path.dirname(db_file), os.W_OK):
                    log("✓ SQLite database is available")
                    return True
                else:
                    log("SQLite file not accessible")
            else:
                log(f"Unknown database URL format: {db_url}")
                
        except Exception as e:
            log(f"Database connection failed: {e}")
        
        if attempt < max_attempts:
            log(f"Waiting {retry_delay} seconds before next attempt...")
            time.sleep(retry_delay)
    
    log("✗ Database is not available after maximum retries")
    return False

def run_migrations():
    """Run database migrations"""
    log("Checking migrations...")
    
    try:
        # Check if migrations directory exists
        if os.path.exists("/app/migrations"):
            log("Migrations directory exists, checking status...")
            
            # Try to apply any pending migrations
            result = subprocess.run(['flask', 'db', 'upgrade'], 
                                  capture_output=True, text=True, timeout=120)
            if result.returncode == 0:
                log("✓ Migrations applied successfully")
                
                # Verify all columns from models exist and fix if missing
                log("Verifying complete database schema against models...")
                fix_result = subprocess.run(
                    ['python', '/app/scripts/verify_and_fix_schema.py'],
                    capture_output=True,
                    text=True,
                    timeout=180
                )
                if fix_result.returncode == 0:
                    # Print output to show what was fixed
                    if fix_result.stdout:
                        for line in fix_result.stdout.strip().split('\n'):
                            if line.strip() and not line.startswith('='):
                                log(line)
                    log("✓ Database schema verified and fixed")
                else:
                    log(f"⚠ Schema verification had issues: {fix_result.stderr}")
                    # Fallback to the simpler fix script
                    log("Attempting fallback column fix...")
                    fallback_result = subprocess.run(
                        ['python', '/app/scripts/fix_missing_columns.py'],
                        capture_output=True,
                        text=True,
                        timeout=60
                    )
                    if fallback_result.returncode == 0:
                        log("✓ Fallback fix completed")
                
                return True
            else:
                log(f"⚠ Migration application failed: {result.stderr}")
                # Try to fix missing columns even if migration failed
                log("Attempting to fix missing columns...")
                fix_result = subprocess.run(
                    ['python', '/app/scripts/verify_and_fix_schema.py'],
                    capture_output=True,
                    text=True,
                    timeout=180
                )
                if fix_result.returncode == 0:
                    if fix_result.stdout:
                        for line in fix_result.stdout.strip().split('\n'):
                            if line.strip() and not line.startswith('='):
                                log(line)
                    log("✓ Missing columns fixed")
                else:
                    # Fallback to simpler script
                    log("Trying fallback fix...")
                    fallback_result = subprocess.run(
                        ['python', '/app/scripts/fix_missing_columns.py'],
                        capture_output=True,
                        text=True,
                        timeout=60
                    )
                    if fallback_result.returncode == 0:
                        log("✓ Fallback fix completed")
                return False
        else:
            log("No migrations directory found, initializing...")
            
            # Initialize migrations
            result = subprocess.run(['flask', 'db', 'init'], 
                                  capture_output=True, text=True, timeout=60)
            if result.returncode == 0:
                log("✓ Migrations initialized")
                
                # Create initial migration
                result = subprocess.run(['flask', 'db', 'migrate', '-m', 'Initial schema'], 
                                      capture_output=True, text=True, timeout=60)
                if result.returncode == 0:
                    log("✓ Initial migration created")
                    
                    # Apply migration
                    result = subprocess.run(['flask', 'db', 'upgrade'], 
                                          capture_output=True, text=True, timeout=60)
                    if result.returncode == 0:
                        log("✓ Initial migration applied")
                        return True
                    else:
                        log(f"⚠ Initial migration application failed: {result.stderr}")
                        return False
                else:
                    log(f"⚠ Initial migration creation failed: {result.stderr}")
                    return False
            else:
                log(f"⚠ Migration initialization failed: {result.stderr}")
                return False
                
    except subprocess.TimeoutExpired:
        log("⚠ Migration operation timed out")
        return False
    except Exception as e:
        log(f"⚠ Migration error: {e}")
        return False

def main():
    """Main entrypoint function"""
    log("=== TimeTracker Docker Entrypoint ===")
    
    # Set environment variables
    os.environ.setdefault('FLASK_APP', '/app/app.py')
    
    # Wait for database
    if not wait_for_database():
        log("✗ Failed to connect to database")
        sys.exit(1)
    
    # Run migrations
    if not run_migrations():
        log("⚠ Migration issues detected, continuing anyway")
    
    log("=== Startup Complete ===")
    log("Starting TimeTracker application...")
    
    # Execute the command passed to the container
    if len(sys.argv) > 1:
        try:
            os.execv(sys.argv[1], sys.argv[1:])
        except Exception as e:
            log(f"✗ Failed to execute command: {e}")
            sys.exit(1)
    else:
        # Default command
        try:
            os.execv('/usr/bin/python', ['python', '/app/start.py'])
        except Exception as e:
            log(f"✗ Failed to execute default command: {e}")
            sys.exit(1)

if __name__ == "__main__":
    main()
