# Copyright (c) 2025 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import uuid
from datetime import datetime
import ssl
import re

from flask import Flask, request, jsonify
from requests.adapters import HTTPAdapter
from sqlalchemy.exc import IntegrityError, DisconnectionError, OperationalError

from oslo_log import log as logging
from openstack import connection
from keystoneauth1 import loading as ks_loading

from vigie.db.sqlalchemy.database import init_database_config
from vigie.db.sqlalchemy.database import get_session as get_db_session
from vigie.db.sqlalchemy.models import VMMigration, MigrationState

# Initialize logging
LOG = logging.getLogger(__name__)

# Global config storage to avoid re-parsing
_CONFIG = None

def get_config():
    """Get configuration, parsing it only once."""
    global _CONFIG
    if _CONFIG is None:
        from vigie import config
        _CONFIG = config.init_config()
    return _CONFIG

# Create single Flask app with all routes
app = Flask(__name__)

@app.route('/healthcheck', methods=['GET'])
def health_check():
    """Health check endpoint - no authentication required"""
    return jsonify({'status': 'ok', 'service': 'vigie'}), 200

@app.route('/v2/purge-project', methods=['POST'])
@policy_checker('vigie:evacuate_compute')
def purge_project():
    """Purge a project"""
    try:
        data = request.get_json()
        
        if not data or ('project_id' not in data
                        and 'project_name' not in data):
            return jsonify({'error': 'Missing required field: project_id '
                                     'or project_name'}), 400


@app.route('/v2/evacutate-compute', methods=['POST'])
@policy_checker('vigie:evacuate_compute')
def evacuate_compute():
    """List all VM migrations - authentication required"""
    try:
        # Get query parameters
        state_filter = request.args.get('state', None)

        # Validate state parameter if provided
        if state_filter:
            # Get all valid state values from the enum
            valid_states = [state.value for state in MigrationState]
            if state_filter not in valid_states:
                return jsonify({
                    'error': f'Invalid state. Allowed: {", ".join(valid_states)}'
                }), 400

        session = get_db_session()

        # Build query with optional state filtering
        query = session.query(VMMigration)
        if state_filter:
            query = query.filter(VMMigration.state == state_filter)
        migrations = query.all()
        result = [migration.to_dict() for migration in migrations]
        return jsonify(result)
    except Exception as e:
        LOG.error(f"Error listing VMs: {e}", exc_info=True)
        return jsonify({'error': str(e)}), 500


def get_application():
    """Create WSGI application with Keystone authentication"""
    try:
        CONF = get_config()
        logging.setup(CONF, 'vigie-api')
        
        # Initialize database configuration
        init_database_config(CONF)

        # Apply Keystone middleware with delay_auth_decision=true
        from keystonemiddleware import auth_token
        middleware_conf = dict(CONF.keystone_authtoken)
        # Ensure delay_auth_decision is true for selective auth
        middleware_conf['delay_auth_decision'] = True
        application = auth_token.filter_factory(middleware_conf)(app)
        return application
    except Exception as e:
        LOG.error(f"Error creating application: {e}", exc_info=True)
        return app
