#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Flask 應用程式工廠

Author: PANJIT IT Team
Created: 2024-01-28
Modified: 2024-01-28
"""

import os
import redis
from flask import Flask, request, make_response
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from flask_jwt_extended import JWTManager
from celery import Celery
from app.config import config
from app.utils.logger import init_logging

# 初始化擴展
db = SQLAlchemy()
cors = CORS()
jwt = JWTManager()


def make_celery(app):
    """創建 Celery 實例"""
    celery = Celery(
        app.import_name,
        backend=app.config['CELERY_RESULT_BACKEND'],
        broker=app.config['CELERY_BROKER_URL']
    )
    celery.conf.update(app.config)
    
    class ContextTask(celery.Task):
        """在 Flask 應用上下文中執行任務"""
        def __call__(self, *args, **kwargs):
            with app.app_context():
                return self.run(*args, **kwargs)
    
    celery.Task = ContextTask
    return celery


def create_app(config_name=None):
    """應用程式工廠"""
    app = Flask(__name__)
    
    # 載入配置
    config_name = config_name or os.getenv('FLASK_ENV', 'default')
    
    # 先載入 Dify API 配置
    config[config_name].load_dify_config()
    
    # 然後載入配置到 Flask app
    app.config.from_object(config[config_name])
    
    # 初始化必要目錄
    config[config_name].init_directories()
    
    # 初始化擴展
    db.init_app(app)
    
    # 不使用 Flask-CORS 避免衝突，使用手動CORS處理
    
    # 初始化 JWT
    jwt.init_app(app)
    app.logger.info(f"🔑 [JWT Config] JWT_SECRET_KEY: {app.config.get('JWT_SECRET_KEY')[:10]}...{app.config.get('JWT_SECRET_KEY')[-10:] if app.config.get('JWT_SECRET_KEY') else 'None'}")
    app.logger.info(f"🔑 [JWT Config] JWT_ACCESS_TOKEN_EXPIRES: {app.config.get('JWT_ACCESS_TOKEN_EXPIRES')}")
    app.logger.info(f"🔑 [JWT Config] JWT_REFRESH_TOKEN_EXPIRES: {app.config.get('JWT_REFRESH_TOKEN_EXPIRES')}")
    
    app.logger.info("🔑 [JWT] Using JWT authentication")
    
    # 設定 Redis（用於Celery）
    try:
        redis_client = redis.from_url(app.config['REDIS_URL'])
        app.redis_client = redis_client
    except Exception as e:
        app.logger.warning(f"Redis initialization failed: {str(e)}")
        app.redis_client = None
    
    # 初始化日誌
    init_logging(app)
    
    # 註冊 API 路由
    from app.api import api_v1
    app.register_blueprint(api_v1)
    
    # 註冊錯誤處理器
    register_error_handlers(app)
    
    # 添加 CORS 響應headers
    @app.after_request
    def after_request(response):
        origin = request.headers.get('Origin')
        allowed_origins = ['http://localhost:3000', 'http://127.0.0.1:3000', 'http://localhost:3001', 'http://127.0.0.1:3001']
        
        if origin and origin in allowed_origins:
            response.headers['Access-Control-Allow-Origin'] = origin
            response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization, X-Requested-With'
            response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS, PATCH'
            response.headers['Access-Control-Allow-Credentials'] = 'true'
            response.headers['Access-Control-Max-Age'] = '86400'
        
        return response
    
    # 處理 OPTIONS 預檢請求
    @app.before_request
    def before_request():
        if request.method == 'OPTIONS':
            response = make_response()
            origin = request.headers.get('Origin')
            allowed_origins = ['http://localhost:3000', 'http://127.0.0.1:3000', 'http://localhost:3001', 'http://127.0.0.1:3001']
            
            if origin and origin in allowed_origins:
                response.headers['Access-Control-Allow-Origin'] = origin
                response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization, X-Requested-With'
                response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS, PATCH'
                response.headers['Access-Control-Allow-Credentials'] = 'true'
                response.headers['Access-Control-Max-Age'] = '86400'
            
            return response
    
    # 建立資料表
    with app.app_context():
        # 導入模型
        from app.models import User, TranslationJob, JobFile, TranslationCache, APIUsageStats, SystemLog
        
        db.create_all()
        
        # 創建默認管理員用戶（如果不存在）
        create_default_admin()
    
    # 創建 Celery 實例
    app.celery = make_celery(app)
    
    app.logger.info("Flask application created successfully")
    return app


def register_error_handlers(app):
    """註冊錯誤處理器"""
    
    @app.errorhandler(404)
    def not_found(error):
        return {
            'success': False,
            'error': 'NOT_FOUND',
            'message': '請求的資源不存在'
        }, 404
    
    @app.errorhandler(403)
    def forbidden(error):
        return {
            'success': False,
            'error': 'FORBIDDEN',
            'message': '權限不足'
        }, 403
    
    @app.errorhandler(401)
    def unauthorized(error):
        return {
            'success': False,
            'error': 'UNAUTHORIZED',
            'message': '需要認證'
        }, 401
    
    @app.errorhandler(500)
    def internal_server_error(error):
        return {
            'success': False,
            'error': 'INTERNAL_SERVER_ERROR',
            'message': '系統內部錯誤'
        }, 500
    
    @app.errorhandler(413)
    def request_entity_too_large(error):
        return {
            'success': False,
            'error': 'FILE_TOO_LARGE',
            'message': '檔案大小超過限制'
        }, 413


def create_default_admin():
    """創建默認管理員用戶"""
    try:
        from app.models import User
        
        admin_email = os.environ.get('ADMIN_EMAIL', 'ymirliu@panjit.com.tw')
        
        # 檢查是否已存在管理員
        admin_user = User.query.filter_by(email=admin_email).first()
        
        if not admin_user:
            # 創建管理員用戶（待 LDAP 登入時完善資訊）
            admin_user = User(
                username=admin_email.split('@')[0],
                display_name='系統管理員',
                email=admin_email,
                department='IT',
                is_admin=True
            )
            db.session.add(admin_user)
            db.session.commit()
            
            print(f"Created default admin user: {admin_email}")
    
    except Exception as e:
        print(f"Failed to create default admin: {str(e)}")


# 導入模型在需要時才進行，避免循環導入