import os
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_cors import CORS
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from config import get_config

# Initialize extensions
db = SQLAlchemy()
migrate = Migrate()
limiter = Limiter(
    key_func=get_remote_address,
    default_limits=[]
)


def create_app(config_name=None):
    """Application factory pattern for creating Flask app."""
    
    app = Flask(__name__)
    
    # Load configuration
    if config_name:
        from config import config as config_dict
        app.config.from_object(config_dict[config_name])
    else:
        app.config.from_object(get_config())
    
    # Initialize extensions with app
    db.init_app(app)
    migrate.init_app(app, db)

    from .commands import register_commands
    register_commands(app)
    
    # Setup CORS
    CORS(app, 
         origins=app.config['CORS_ORIGINS'],
         supports_credentials=True,
         allow_headers=['Content-Type', 'Authorization'],
         methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])
    
    # Setup Rate Limiting
    if app.config.get('RATE_LIMIT_ENABLED', True):
        limiter.init_app(app)
        app.logger.info('Rate limiting enabled')
    else:
        app.logger.info('Rate limiting disabled')
    
    # Setup logging
    setup_logging(app)
    
    # Register blueprints
    register_blueprints(app)
    
    # Register error handlers
    register_error_handlers(app)
    
    # Create database context
    with app.app_context():
        # Import models here to avoid circular imports
        from app import models
        
    
    app.logger.info(f'Flask app initialized with {app.config["SQLALCHEMY_DATABASE_URI"]}')
    
    return app


def setup_logging(app):
    """Configure application logging with file and console handlers."""
    
    # Create logs directory if it doesn't exist
    log_dir = os.path.dirname(app.config['LOG_FILE'])
    if log_dir and not os.path.exists(log_dir):
        os.makedirs(log_dir)
    
    # Set log level
    log_level = getattr(logging, app.config['LOG_LEVEL'].upper(), logging.INFO)
    app.logger.setLevel(log_level)
    
    # Remove default handlers
    app.logger.handlers.clear()
    
    # File handler with rotation
    file_handler = RotatingFileHandler(
        app.config['LOG_FILE'],
        maxBytes=10 * 1024 * 1024,  # 10MB
        backupCount=10
    )
    file_handler.setLevel(log_level)
    
    # Console handler
    console_handler = logging.StreamHandler()
    console_handler.setLevel(log_level)
    
    # Create formatters
    detailed_formatter = logging.Formatter(
        '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
    )
    simple_formatter = logging.Formatter('%(levelname)s: %(message)s')
    
    file_handler.setFormatter(detailed_formatter)
    console_handler.setFormatter(simple_formatter)
    
    # Add handlers
    app.logger.addHandler(file_handler)
    app.logger.addHandler(console_handler)
    
    # Log startup info
    app.logger.info('='*50)
    app.logger.info('Application starting...')
    app.logger.info(f'Environment: {app.config.get("ENV", "development")}')
    app.logger.info(f'Debug mode: {app.debug}')
    app.logger.info('='*50)


def register_blueprints(app):
    """Register all application blueprints."""
    
    # Import blueprints (relative import to avoid circular reference)
    from .routes import auth_bp,  uploads_bp, houses_bp,  images_bp, profile_bp, admin_users_bp
    
    # Register auth routes
    app.register_blueprint(auth_bp)
    
    # Register property routes
    app.register_blueprint(uploads_bp)
    app.register_blueprint(houses_bp)
    app.register_blueprint(images_bp)
    app.register_blueprint(profile_bp)
    app.register_blueprint(admin_users_bp)
    
    # Simple welcome endpoint for initial setup
    @app.route('/')
    def welcome():
        return jsonify({
            'message': 'Welcome to the Rental Platform API',
            'version': '1.0.0',
            'status': 'running'
        }), 200
    
    @app.route('/api')
    def api_welcome():
        return jsonify({
            'message': 'Welcome to the Rental Platform API',
            'version': '1.0.0',
            'endpoints': {
                'auth': '/auth',
                'protected': '/protected',
                'houses': '/houses',
                'cars': '/cars',
                'uploads': '/uploads',
                'health': '/health'
            }
        }), 200
    
    @app.route('/health')
    def health_check():
        return jsonify({
            'status': 'healthy',
            'database': 'connected'
        }), 200
    
    app.logger.info('Blueprints registered successfully')
    


def register_error_handlers(app):
    """Register global error handlers."""
    
    @app.errorhandler(404)
    def not_found(error):
        app.logger.warning(f'404 error: {error}')
        return jsonify({
            'error': 'Not Found',
            'message': 'The requested resource was not found'
        }), 404
    
    @app.errorhandler(500)
    def internal_error(error):
        app.logger.error(f'500 error: {error}')
        db.session.rollback()
        return jsonify({
            'error': 'Internal Server Error',
            'message': 'An unexpected error occurred'
        }), 500
    
    @app.errorhandler(429)
    def ratelimit_handler(error):
        app.logger.warning(f'Rate limit exceeded: {error}')
        return jsonify({
            'error': 'Rate Limit Exceeded',
            'message': 'Too many requests. Please try again later.'
        }), 429
    
    @app.errorhandler(400)
    def bad_request(error):
        app.logger.warning(f'400 error: {error}')
        return jsonify({
            'error': 'Bad Request',
            'message': 'The request could not be understood or was missing required parameters'
        }), 400
    
    app.logger.info('Error handlers registered successfully')