import logging
import os

from flask import Flask, jsonify, request, url_for, session as flask_session
from werkzeug.middleware.proxy_fix import ProxyFix
import logging.config
from jinja2 import ChoiceLoader, FileSystemLoader

from common.extensions import (db, bootstrap, cors, csrf, session,
                              minio_client, simple_encryption, metrics, cache_manager, content_manager)
from common.models.user import Tenant, SpecialistMagicLinkTenant
from config.logging_config import configure_logging
from common.utils.errors import register_error_handlers
from common.utils.celery_utils import make_celery, init_celery
from common.utils.template_filters import register_filters
from config.config import get_config
from common.utils.chat_utils import get_default_chat_customisation


def create_app(config_file=None):
    app = Flask(__name__, static_url_path='/static')

    # Ensure all necessary headers are handled
    app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1)

    environment = os.getenv('FLASK_ENV', 'development')

    match environment:
        case 'development':
            app.config.from_object(get_config('dev'))
        case 'test':
            app.config.from_object(get_config('test'))
        case 'staging':
            app.config.from_object(get_config('staging'))
        case 'production':
            app.config.from_object(get_config('prod'))
        case _:
            app.config.from_object(get_config('dev'))

    app.config['SESSION_KEY_PREFIX'] = 'eveai_chat_client_'

    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    configure_logging()
    logger = logging.getLogger(__name__)

    logger.info("eveai_chat_client starting up")

    # Register extensions
    register_extensions(app)

    # Configure CSRF protection
    app.config['WTF_CSRF_CHECK_DEFAULT'] = False  # Disable global CSRF protection
    app.config['WTF_CSRF_TIME_LIMIT'] = None  # Remove time limit for CSRF tokens

    app.celery = make_celery(app.name, app.config)
    init_celery(app.celery, app)

    # Configure template loader with fallback to common/templates
    try:
        import os as _os
        common_templates_path = _os.path.normpath(_os.path.join(app.root_path, '..', 'common', 'templates'))
        app.jinja_loader = ChoiceLoader([
            app.jinja_loader,
            FileSystemLoader(common_templates_path),
        ])
        app.logger.debug(f"Added common templates path: {common_templates_path}")
    except Exception as e:
        app.logger.error(f"Failed to configure ChoiceLoader for common templates: {e}")

    # Register Blueprints
    register_blueprints(app)

    # Register Error Handlers (shared, profile-aware)
    register_error_handlers(app, profile='chat_client')

    # Register Cache Handlers
    register_cache_handlers(app)

    # Custom url_for function for templates
    @app.context_processor
    def override_url_for():
        return dict(url_for=_url_for)

    def _url_for(endpoint, **values):
        static_url = app.config.get('STATIC_URL')
        if endpoint == 'static' and static_url:
            filename = values.get('filename', '')
            return f"{static_url}/{filename}"
        return url_for(endpoint, **values)

    # Debugging settings
    if app.config['DEBUG'] is True:
        app.logger.setLevel(logging.DEBUG)

    # Register template filters
    register_filters(app)

    # Always inject chat customisation for templates (safe defaults)
    @app.context_processor
    def inject_customisation():
        try:
            tm = flask_session.get('tenant_make')
            options = None
            if tm and isinstance(tm, dict):
                options = tm.get('chat_customisation_options')
            customisation = get_default_chat_customisation(options)
        except Exception:
            customisation = get_default_chat_customisation(None)
        return {'customisation': customisation}

    app.logger.info(f"EveAI Chat Client Started Successfully (PID: {os.getpid()})")
    app.logger.info("-------------------------------------------------------------------------------------------------")

    # @app.before_request
    # def app_before_request():
    #     if request.path.startswith('/healthz'):
    #         pass
    #     app.logger.debug(f'App before request: {request.path} ===== Method: {request.method} =====')
    #     app.logger.debug(f'Full URL: {request.url}')
    #     app.logger.debug(f'Endpoint: {request.endpoint}')

    return app


def register_extensions(app):
    db.init_app(app)
    bootstrap.init_app(app)
    csrf.init_app(app)
    cors.init_app(app)
    simple_encryption.init_app(app)
    session.init_app(app)
    minio_client.init_app(app)
    cache_manager.init_app(app)
    metrics.init_app(app)
    content_manager.init_app(app)


def register_blueprints(app):
    from .views.chat_views import chat_bp
    app.register_blueprint(chat_bp)
    # Do not register local error blueprint; use shared error handlers from common
    from .views.healthz_views import healthz_bp
    app.register_blueprint(healthz_bp)


def register_cache_handlers(app):
    from common.utils.cache.config_cache import register_config_cache_handlers
    register_config_cache_handlers(cache_manager)
    from common.utils.cache.crewai_processed_config_cache import register_specialist_cache_handlers
    register_specialist_cache_handlers(cache_manager)
    from common.utils.cache.translation_cache import register_translation_cache_handlers
    register_translation_cache_handlers(cache_manager)
