import asyncio
import logging
import os
from contextlib import asynccontextmanager

from fastapi import FastAPI, UploadFile, File, Form, Depends, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles

from app.config import settings
from app.models import init_database, close_database
from app.utils.redis import init_redis, close_redis
from app.api.v1 import api_router
from app.middleware.logging import RequestLoggingMiddleware
from app.middleware.anti_crawler import AntiCrawlerMiddleware
from app.middleware.rate_limit import RateLimitMiddleware
from app.middleware.request_encrypt import RequestEncryptMiddleware
from app.services.log_config import decrypt_data

logging.basicConfig(level=logging.INFO if settings.DEBUG else logging.WARNING)


@asynccontextmanager
async def lifespan(app: FastAPI):
    from app.models import async_session
    
    # Ensure upload directory exists
    os.makedirs(settings.UPLOAD_LOCAL_PATH, exist_ok=True)
    await init_database()
    await init_redis()
    await _seed_data()

    # Start task queue (handles both video and image generation)
    from app.services.video_queue import task_queue
    await task_queue.recover()
    queue_task = asyncio.create_task(task_queue.run())

    # Background task: auto-expire pending payment orders and sync status
    async def _order_expiry_loop():
        from app.services.payment import expire_all_pending_orders, sync_pending_orders
        from logging import getLogger
        bg_logger = getLogger("payment")
        while True:
            try:
                async with async_session() as db:
                    # 同步待支付订单状态（检查支付宝实际支付状态
                    sync_count = await sync_pending_orders(db)
                    if sync_count > 0:
                        bg_logger.info(f"Synced {sync_count} pending payment order(s)")
                    
                    # 自动过期订单
                    n = await expire_all_pending_orders(db)
                    if n > 0:
                        bg_logger.info(f"Auto-expired {n} pending payment order(s)")
            except Exception as e:
                bg_logger.error(f"Order expiry loop error: {e}")
            await asyncio.sleep(60)  # check every minute

    expiry_task = asyncio.create_task(_order_expiry_loop())
    
    # 启动token刷新定时任务（每5分钟检查一次，小于800秒有效期的token进行刷新）
    from app.tasks.token_refresh_task import token_refresh_scheduler
    token_refresh_task = asyncio.create_task(token_refresh_scheduler())

    # 启动上传任务队列
    from app.services.upload_queue import upload_queue
    await upload_queue.recover()
    upload_queue_task = asyncio.create_task(upload_queue.run())
    
    # 启动素材消耗队列
    from app.services.material_consumption_queue import material_consumption_queue
    consumption_queue_task = asyncio.create_task(material_consumption_queue.run())
    
    # 启动素材消耗计划任务（每天9点自动同步）
    from app.tasks.material_consumption_task import schedule_daily_sync
    consumption_schedule_task = asyncio.create_task(schedule_daily_sync())
    
    # 启动前测结果轮询任务（每分钟检查一次）
    from app.tasks.pre_test_result_task import poll_pre_test_results
    pre_test_poll_task = asyncio.create_task(poll_pre_test_results())
    
    # 启动时立即同步一次未支付订单
    asyncio.create_task(asyncio.sleep(5))  # 等待5秒后再同步，让系统完全启动
    async def startup_sync():
        await asyncio.sleep(5)
        from app.services.payment import sync_pending_orders
        from logging import getLogger
        bg_logger = getLogger("payment")
        try:
            async with async_session() as db:
                sync_count = await sync_pending_orders(db)
                if sync_count > 0:
                    bg_logger.info(f"Startup: Synced {sync_count} pending payment order(s)")
        except Exception as e:
            bg_logger.error(f"Startup sync error: {e}")
    asyncio.create_task(startup_sync())

    app.state.db_session_factory = async_session

    yield

    task_queue.stop()
    await queue_task
    upload_queue.stop()
    await upload_queue_task
    material_consumption_queue.stop()
    await consumption_queue_task
    consumption_schedule_task.cancel()
    pre_test_poll_task.cancel()
    expiry_task.cancel()
    token_refresh_task.cancel()
    await close_database()
    await close_redis()


async def _seed_data():
    """Insert initial data on first run."""
    from app.models import async_session
    from app.models.user import User
    from app.models.system_config import SystemConfig
    from app.models.video_engine import VideoEngine
    from app.models.image_engine import ImageEngine
    from app.models.credit_ratio import CreditRatio
    from app.models.model_config import ModelConfig
    from app.services.auth import hash_password
    from app.utils.id_gen import generate_id
    from sqlalchemy import select, func

    async with async_session() as db:
        # Check if admin exists
        result = await db.execute(select(User).where(User.is_admin == True).limit(1))
        admin = result.scalar_one_or_none()
        if not admin:
            admin_user = User(
                id=generate_id(),
                username="admin",
                email="admin@videogen.ai",
                phone="13800000000",
                hashed_password=hash_password("123456"),
                credits=10000,
                is_admin=True,
                user_type="admin",
            )
            db.add(admin_user)

        # Seed demo user
        result = await db.execute(select(User).where(User.username == "demo").limit(1))
        demo = result.scalar_one_or_none()
        if not demo:
            demo_user = User(
                id=generate_id(),
                username="demo",
                email="demo@videogen.ai",
                phone="13888888888",
                hashed_password=hash_password("123456"),
                credits=2680,
                is_admin=False,
                user_type="frontend",
            )
            db.add(demo_user)

        # Seed system configs
        configs = [
            ("site_name", "民众智创", "网站名称"),
            ("site_logo", "", "网站Logo URL"),
            ("seo_title", "民众智创 - AI视频生成平台", "SEO标题"),
            ("seo_description", "专业的AI视频生成服务", "SEO描述"),
            ("seo_keywords", "AI视频,视频生成,人工智能", "SEO关键词"),
            # Agreement configs
            ("user_agreement_url", "", "用户协议PDF"),
            ("privacy_policy_url", "", "隐私政策PDF"),
            # Payment configs
            ("payment_wechat_enabled", "false", "微信支付启用"),
            ("payment_wechat_mch_id", "", "微信商户号"),
            ("payment_wechat_api_key", "", "微信API密钥"),
            ("payment_alipay_enabled", "false", "支付宝启用"),
            ("payment_alipay_app_id", "", "支付宝AppID"),
            ("payment_alipay_private_key", "", "支付宝私钥"),
            # Text credit config
            ("text_credits_per_1000_tokens", "1", "每1000 token消耗文本积分"),
            # User credits config
            ("user_register_credits", "100", "用户注册赠送积分"),
            ("user_login_credits", "0", "用户每日登录赠送积分"),
            ("user_login_credits_enabled", "false", "启用每日登录赠送积分"),
        ]
        for key, value, desc in configs:
            existing = await db.execute(
                select(SystemConfig).where(SystemConfig.key == key).limit(1)
            )
            if not existing.scalar_one_or_none():
                db.add(
                    SystemConfig(
                        id=generate_id(), key=key, value=value, description=desc
                    )
                )

        # Seed video engine
        existing_engine = await db.execute(
            select(VideoEngine).where(VideoEngine.provider == "ark")
        )
        if not existing_engine.scalars().first():
            db.add(
                VideoEngine(
                    id=generate_id(),
                    name="Seedance 2.0",
                    provider="ark",
                    api_base="https://ark.cn-beijing.volces.com/api/v3",
                    api_key="",
                    model_name="doubao-seedance-2-0-260128",
                    supported_ratios='["16:9","4:3","1:1","3:4","9:16","21:9"]',
                    supported_resolutions='["480p","720p","1080p"]',
                    supported_durations='[4,5,6,7,8,9,10,11,12,13,14,15]',
                    max_duration=15,
                    is_active=True,
                    priority=10,
                )
            )
        existing_fast_engine = await db.execute(
            select(VideoEngine).where(VideoEngine.model_name == "doubao-seedance-2-0-fast-260128")
        )
        if not existing_fast_engine.scalars().first():
            db.add(
                VideoEngine(
                    id=generate_id(),
                    name="Seedance 2.0 fast",
                    provider="ark",
                    api_base="https://ark.cn-beijing.volces.com/api/v3",
                    api_key="",
                    model_name="doubao-seedance-2-0-fast-260128",
                    supported_ratios='["16:9","4:3","1:1","3:4","9:16","21:9"]',
                    supported_resolutions='["480p","720p","1080p"]',
                    supported_durations='[4,5,6,7,8,9,10,11,12,13,14,15]',
                    max_duration=15,
                    is_active=True,
                    priority=10,
                )
            )

        # Seed image engine
        existing_img_engine = await db.execute(
            select(ImageEngine).where(ImageEngine.provider == "ark").limit(1)
        )
        if not existing_img_engine.scalar_one_or_none():
            db.add(
                ImageEngine(
                    id=generate_id(),
                    name="豆包文生图",
                    provider="ark",
                    api_base="https://ark.cn-beijing.volces.com/api/v3",
                    api_key="",
                    model_name="doubao-seedream-5-0-260128",
                    supported_models='["doubao-seedream-5-0-260128"]',
                    supported_sizes='{"2K":{"1:1":"2048×2048","4:3":"2304×1728","3:4":"1728×2304","16:9":"2560×1440","9:16":"1600×2848","3:2":"2496×1664","2:3":"1664×2496","21:9":"3024×1296"},"4K":{"1:1":"4096×4096","4:3":"4608×3456","3:4":"3520×4704","16:9":"5404×3040","9:16":"3040×5504","3:2":"4992×3328","2:3":"3328×4992","21:9":"6197×2656"}}',
                    default_size="2K",
                    generate_url="https://ark.cn-beijing.volces.com/api/v3/images/generations",
                    is_active=True,
                    priority=10,
                )
            )

        # Seed default Ark model config
        existing_sdk_model = await db.execute(
            select(ModelConfig).where(ModelConfig.provider == "sdk").limit(1)
        )
        if not existing_sdk_model.scalar_one_or_none():
            db.add(
                ModelConfig(
                    id=generate_id(),
                    name="火山引擎 Ark",
                    provider="sdk",
                    api_base="https://ark.cn-beijing.volces.com/api/v3",
                    api_key="",
                    model_name="doubao-seed-2-0-lite-260215",
                    weight=1,
                    max_tokens=4096,
                    temperature=0.7,
                    is_active=True,
                    priority=10,
                )
            )

        # Seed credit ratios - model_config_id is kept as a compatible field name,
        # but now stores the actual engine id:
        # - gen_type=video -> video_engines.id
        # - gen_type=image -> image_engines.id
        await db.flush()

        default_video_engine_result = await db.execute(
            select(VideoEngine)
            .where(VideoEngine.is_active == True)
            .order_by(VideoEngine.priority.desc(), VideoEngine.id.desc())
            .limit(1)
        )
        default_video_engine = default_video_engine_result.scalar_one_or_none()
        if default_video_engine:
            for resolution, ratio_val, base, per_sec in [
                ("480p", 1.0, 60, 2),
                ("720p", 1.0, 80, 2),
                ("1080p", 1.5, 120, 3),
            ]:
                existing_ratio = await db.execute(
                    select(CreditRatio)
                    .where(CreditRatio.model_config_id == default_video_engine.id)
                    .where(CreditRatio.gen_type == "video")
                    .where(CreditRatio.resolution == resolution)
                    .limit(1)
                )
                if not existing_ratio.scalar_one_or_none():
                    db.add(
                        CreditRatio(
                            id=generate_id(),
                            model_config_id=default_video_engine.id,
                            gen_type="video",
                            resolution=resolution,
                            ratio=ratio_val,
                            base_credits=base,
                            per_second_credits=per_sec,
                        )
                    )

        default_image_engine_result = await db.execute(
            select(ImageEngine)
            .where(ImageEngine.is_active == True)
            .order_by(ImageEngine.priority.desc(), ImageEngine.id.desc())
            .limit(1)
        )
        default_image_engine = default_image_engine_result.scalar_one_or_none()
        if default_image_engine:
            for resolution, ratio_val, base, per_sec in [
                ("2K", 1.0, 4, 0),
                ("4K", 1.0, 6, 0),
            ]:
                existing_ratio = await db.execute(
                    select(CreditRatio)
                    .where(CreditRatio.model_config_id == default_image_engine.id)
                    .where(CreditRatio.gen_type == "image")
                    .where(CreditRatio.resolution == resolution)
                    .limit(1)
                )
                if not existing_ratio.scalar_one_or_none():
                    db.add(
                        CreditRatio(
                            id=generate_id(),
                            model_config_id=default_image_engine.id,
                            gen_type="image",
                            resolution=resolution,
                            ratio=ratio_val,
                            base_credits=base,
                            per_second_credits=per_sec,
                        )
                    )

        # Seed menu configs
        from app.models.menu_config import MenuConfig

        menu_count = await db.execute(select(func.count(MenuConfig.id)))
        menu_count_result = menu_count.scalar_one()
        
        logging.info(f"Menu config count: {menu_count_result}")
        
        if menu_count_result == 0:
            logging.info("Inserting default menu configs...")
            frontend_menus = [
                {"id": "0019eca2549ba477069", "label": "制作素材", "path": "", "icon": "PlayCircleOutlined", "sort_order": 1, "is_active": True, "parent_id": None, "menu_type": "group", "menu_target": "frontend", "is_default": True},
                {"id": "0019f01914a66279ec0", "label": "灵感参考", "path": "", "icon": "HomeOutlined", "sort_order": 2, "is_active": True, "parent_id": None, "menu_type": "group", "menu_target": "frontend", "is_default": True},
                {"id": "0019eca2735b9f3d944", "label": "我的资产", "path": "", "icon": "HomeOutlined", "sort_order": 3, "is_active": True, "parent_id": None, "menu_type": "group", "menu_target": "frontend", "is_default": True},
                {"id": "0019eca27ec59922048", "label": "广告素材管理", "path": "", "icon": "HomeOutlined", "sort_order": 4, "is_active": True, "parent_id": None, "menu_type": "group", "menu_target": "frontend", "is_default": True},
                {"id": "0019f01b5717017792f", "label": "首页", "path": "/home", "icon": "HomeOutlined", "sort_order": 0, "is_active": True, "parent_id": None, "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019f01b445f51dee00", "label": "我的项目", "path": "/projects", "icon": "AppstoreOutlined", "sort_order": 0, "is_active": True, "parent_id": "0019eca2549ba477069", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019f01b445f854a14a", "label": "AI创作", "path": "/conversation", "icon": "StarOutlined", "sort_order": 1, "is_active": True, "parent_id": "0019eca2549ba477069", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019e49af896982b070", "label": "爆款开头复刻", "path": "/initial", "icon": "CodeOutlined", "sort_order": 2, "is_active": True, "parent_id": "0019eca2549ba477069", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019e4f26a8c4c0de5a", "label": "拆镜复刻", "path": "/removelens", "icon": "CameraOutlined", "sort_order": 3, "is_active": True, "parent_id": "0019eca2549ba477069", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019f01b7bb6e147445", "label": "爆款榜单", "path": "/popular", "icon": "FireOutlined", "sort_order": 0, "is_active": True, "parent_id": "0019f01914a66279ec0", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019f019267a4de06a0", "label": "创意广场", "path": "/creativeplaza", "icon": "BulbOutlined", "sort_order": 1, "is_active": True, "parent_id": "0019f01914a66279ec0", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019e80aff6d0ea5843", "label": "素材云", "path": "/generated", "icon": "CloudOutlined", "sort_order": 0, "is_active": True, "parent_id": "0019eca2735b9f3d944", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019f01b44606cc4c81", "label": "投放平台授权", "path": "/authorization", "icon": "UserOutlined", "sort_order": 0, "is_active": True, "parent_id": "0019eca27ec59922048", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019ef924a3521924ab", "label": "素材ID列表", "path": "/materials", "icon": "FileTextOutlined", "sort_order": 1, "is_active": True, "parent_id": "0019eca27ec59922048", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019eb61d6fc2c14ebd", "label": "消耗列表", "path": "/consume", "icon": "FileTextOutlined", "sort_order": 1, "is_active": True, "parent_id": "0019eca27ec59922048", "menu_type": "page", "menu_target": "frontend", "is_default": True},
                {"id": "0019ed36864f343d347", "label": "素材前测", "path": "/pretest", "icon": "DatabaseOutlined", "sort_order": 2, "is_active": True, "parent_id": "0019eca27ec59922048", "menu_type": "page", "menu_target": "frontend", "is_default": True},
            ]
            
            for menu in frontend_menus:
                db.add(MenuConfig(**menu))

            admin_groups = [
                ("模型设置", "RobotOutlined", 98),
                ("模型配置", "RobotOutlined", 6),
                ("系统设置", "SettingOutlined", 99),
            ]
            admin_group_ids: dict[str, str] = {}
            for label, icon, order in admin_groups:
                gid = generate_id()
                admin_group_ids[label] = gid
                db.add(
                    MenuConfig(
                        id=gid,
                        path="",
                        label=label,
                        icon=icon,
                        sort_order=order,
                        is_active=True,
                        menu_type="group",
                        menu_target="admin",
                    )
                )

            admin_pages = [
                ("/", "数据概览", "DashboardOutlined", 0, None),
                ("/users", "用户管理", "UserOutlined", 1, None),
                ("/credit-records", "交易流水", "WalletOutlined", 2, None),
                ("/generation-ai", "创作记录", "BulbOutlined", 3, None),
                ("/generation-records", "项目记录", "VideoCameraOutlined", 3, None),
                ("/recharge-packages", "充值套餐", "GiftOutlined", 4, None),
                ("/notifications", "消息推送", "BellOutlined", 5, None),
                ("/payment-stats", "支付统计", "LineChartOutlined", 6, None),
                ("/video-engines", "视频引擎", "PlayCircleOutlined", 0, "模型设置"),
                ("/models", "模型配置", "RobotOutlined", 1, "模型设置"),
                ("/image-engines", "图片模型", "PictureOutlined", 2, "模型设置"),
                ("/credit-ratios", "积分比例", "CalculatorOutlined", 3, "模型设置"),
                ("/payment", "支付配置", "DollarOutlined", 1, "系统设置"),
                ("/industries", "行业配置", "AppstoreOutlined", 2, "系统设置"),
                ("/menu-configs", "菜单配置", "SettingOutlined", 3, "系统设置"),
                ("/settings", "系统设置", "SettingOutlined", 4, "系统设置"),
                ("/operation-logs", "操作日志", "DatabaseOutlined", 5, "系统设置"),
                ("/oauthapp-list", "授权应用", "MenuOutlined", 28, "系统设置"),
                ("/contact-requests", "联系请求", "MessageCircleOutlined", 29, "系统设置"),
            ]
            for path, label, icon, order, parent_group in admin_pages:
                db.add(
                    MenuConfig(
                        id=generate_id(),
                        path=path,
                        label=label,
                        icon=icon,
                        sort_order=order,
                        is_active=True,
                        menu_type="page",
                        menu_target="admin",
                        parent_id=admin_group_ids.get(parent_group),
                    )
                )
            
            logging.info("Default menu configs inserted successfully")

        # Seed recharge packages
        from app.models.recharge_package import RechargePackage

        default_packages = [
            ("体验包", 500, 49, 0, "首次体验推荐", "normal", 0),
            ("进阶包", 2000, 168, 200, "最受欢迎", "normal", 1),
            ("专业包", 5000, 388, 500, "高性价比", "normal", 2),
            ("企业包", 20000, 1280, 2000, "团队首选", "normal", 3),
        ]
        for name, credits, price, bonus, desc, ptype, order in default_packages:
            existing = await db.execute(
                select(RechargePackage).where(RechargePackage.name == name).limit(1)
            )
            if not existing.scalar_one_or_none():
                db.add(
                    RechargePackage(
                        id=generate_id(),
                        name=name,
                        credits=credits,
                        price=price,
                        bonus_credits=bonus,
                        description=desc,
                        package_type=ptype,
                        is_gift=False,
                        is_active=True,
                        sort_order=order,
                    )
                )

        # Seed industry configs
        from app.models.industry_config import IndustryConfig

        default_industries = [
            ("ecommerce", "电商", "ShoppingCartOutlined", "电商行业的视频生成模板", 0),
            ("social", "社交", "TeamOutlined", "社交行业的视频生成模板", 1),
        ]
        for key, label, icon, desc, order in default_industries:
            existing = await db.execute(
                select(IndustryConfig).where(IndustryConfig.key == key).limit(1)
            )
            if not existing.scalar_one_or_none():
                db.add(
                    IndustryConfig(
                        id=generate_id(),
                        key=key,
                        label=label,
                        icon=icon,
                        description=desc,
                        skills="[]",
                        is_active=True,
                        sort_order=order,
                    )
                )

        await db.commit()


def create_app() -> FastAPI:
    application = FastAPI(
        title=settings.APP_NAME,
        version=settings.APP_VERSION,
        lifespan=lifespan,
        docs_url="/internal/api-docs",
        redoc_url="/internal/api-redoc",
    )

    # Middleware (outermost first)
    application.add_middleware(RequestLoggingMiddleware)
    application.add_middleware(AntiCrawlerMiddleware)
    application.add_middleware(RateLimitMiddleware)
    application.add_middleware(RequestEncryptMiddleware)
    application.add_middleware(
        CORSMiddleware,
        allow_origins=settings.CORS_ORIGINS,
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
        expose_headers=["X-Encrypted"],
    )

    # Routes
    application.include_router(api_router, prefix="/api")

    # Static files for uploads
    upload_dir = os.path.abspath(settings.UPLOAD_LOCAL_PATH)
    os.makedirs(upload_dir, exist_ok=True)
    application.mount("/uploads", StaticFiles(directory=upload_dir), name="uploads")

    @application.get("/internal/health")
    async def health():
        return {"status": "ok"}

    @application.get("/internal/status", response_class=HTMLResponse)
    async def status_page():
        from app.tasks.celery_app import celery_app
        from app.config import settings
        
        celery_status = "unknown"
        celery_error = ""
        redis_status = "unknown"
        redis_error = ""
        
        try:
            if celery_app:
                inspect = celery_app.control.inspect()
                try:
                    workers = inspect.stats()
                    if workers:
                        celery_status = "running"
                    else:
                        celery_status = "no_workers"
                except Exception as e:
                    celery_status = "error"
                    celery_error = str(e)
            else:
                celery_status = "disabled"
        except Exception as e:
            celery_status = "error"
            celery_error = str(e)
        
        try:
            if settings.REDIS_URL:
                import redis
                r = redis.from_url(settings.REDIS_URL)
                r.ping()
                redis_status = "connected"
            else:
                redis_status = "disabled"
        except Exception as e:
            redis_status = "disconnected"
            redis_error = str(e)
        
        def get_celery_text(status):
            if status == 'running':
                return '运行中'
            elif status == 'no_workers':
                return '无可用 Worker'
            elif status == 'disabled':
                return '已禁用'
            elif status == 'error':
                return '连接失败'
            else:
                return '未知'
        
        def get_redis_text(status):
            if status == 'connected':
                return '已连接'
            elif status == 'disabled':
                return '已禁用'
            elif status == 'disconnected':
                return '未连接'
            else:
                return '未知'
        
        celery_text = get_celery_text(celery_status)
        redis_text = get_redis_text(redis_status)
        
        celery_error_html = f'<div class="error-message">错误: {celery_error}</div>' if celery_error else ''
        redis_error_html = f'<div class="error-message">错误: {redis_error}</div>' if redis_error else ''
        
        html_content = f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <title>服务状态监控</title>
    <style>
        body {{ font-family: system-ui, -apple-system, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; background: #f5f6fa; }}
        h1 {{ color: #1a1a2e; font-size: 28px; margin-bottom: 8px; }}
        h1 span {{ color: #6366f1; }}
        .status-card {{ background: #fff; border: 1px solid #e2e8f0; border-radius: 12px; padding: 20px; margin-bottom: 16px; }}
        .status-card h3 {{ margin: 0 0 12px; font-size: 16px; color: #1e293b; }}
        .status-indicator {{ display: inline-flex; align-items: center; gap: 8px; }}
        .status-dot {{ width: 10px; height: 10px; border-radius: 50%; }}
        .status-dot.running {{ background: #22c55e; box-shadow: 0 0 8px rgba(34, 197, 94, 0.5); }}
        .status-dot.connected {{ background: #22c55e; box-shadow: 0 0 8px rgba(34, 197, 94, 0.5); }}
        .status-dot.error {{ background: #dc2626; box-shadow: 0 0 8px rgba(220, 38, 38, 0.5); }}
        .status-dot.disabled {{ background: #94a3b8; }}
        .status-dot.unknown {{ background: #f59e0b; }}
        .status-dot.no_workers {{ background: #f59e0b; }}
        .status-dot.disconnected {{ background: #dc2626; }}
        .status-text {{ font-weight: 600; }}
        .status-text.running, .status-text.connected {{ color: #16a34a; }}
        .status-text.error, .status-text.disconnected {{ color: #dc2626; }}
        .status-text.disabled {{ color: #64748b; }}
        .status-text.unknown, .status-text.no_workers {{ color: #d97706; }}
        .error-message {{ margin-top: 8px; padding: 8px 12px; background: #fef2f2; border-radius: 6px; font-size: 13px; color: #dc2626; word-break: break-all; }}
        .info-box {{ margin-top: 12px; padding: 12px; background: #f1f5f9; border-radius: 8px; font-size: 13px; color: #64748b; }}
        .back-link {{ display: inline-block; margin-top: 20px; color: #6366f1; text-decoration: none; font-weight: 600; }}
        .back-link:hover {{ text-decoration: underline; }}
        .version {{ font-size: 13px; color: #94a3b8; margin-top: 4px; }}
    </style>
</head>
<body>
    <h1>服务状态<span>.</span></h1>
    <p class="version">版本 v{settings.APP_VERSION}</p>
    
    <div class="status-card">
        <h3>Celery 任务队列</h3>
        <div class="status-indicator">
            <div class="status-dot {celery_status}"></div>
            <span class="status-text {celery_status}">{celery_text}</span>
        </div>
        {celery_error_html}
        <div class="info-box">
            <strong>说明:</strong> Celery 用于异步处理 AI 生成任务、轮询任务和下载任务。如果显示"无可用 Worker"，请启动 Celery worker。
        </div>
    </div>
    
    <div class="status-card">
        <h3>Redis 缓存</h3>
        <div class="status-indicator">
            <div class="status-dot {redis_status}"></div>
            <span class="status-text {redis_status}">{redis_text}</span>
        </div>
        {redis_error_html}
        <div class="info-box">
            <strong>说明:</strong> Redis 用于 Celery 消息队列、任务状态存储和缓存。
        </div>
    </div>
    
    <div class="status-card">
        <h3>数据库连接</h3>
        <div class="status-indicator">
            <div class="status-dot connected"></div>
            <span class="status-text connected">已连接</span>
        </div>
        <div class="info-box">
            <strong>说明:</strong> PostgreSQL 数据库已连接。
        </div>
    </div>
    
    <a href="/internal/" class="back-link">← 返回首页</a>
</body>
</html>"""
        return HTMLResponse(content=html_content)

    @application.get("/internal/decrypt-data", response_class=HTMLResponse)
    async def decrypt_data_page():
        html_content = """
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>数据解密工具</title>
    <style>
        body { font-family: system-ui, -apple-system, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; }
        h1 { color: #1a1a2e; }
        textarea { width: 100%; height: 150px; padding: 12px; border: 1px solid #e2e8f0; border-radius: 8px; font-family: monospace; font-size: 14px; }
        button { background: #6366f1; color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-size: 16px; }
        button:hover { background: #4f46e5; }
        .result { margin-top: 20px; padding: 16px; background: #f8fafc; border-radius: 8px; }
        .result pre { white-space: pre-wrap; word-break: break-all; font-size: 14px; color: #334155; }
        .error { color: #dc2626; }
    </style>
</head>
<body>
    <h1>数据解密工具</h1>
    <p>用于解密日志中的加密数据</p>
    <textarea id="encryptedInput" placeholder="请输入加密的数据..."></textarea>
    <br><br>
    <button onclick="decrypt()">解密</button>
    <div class="result" id="result"></div>
    <script>
        async function decrypt() {
            const input = document.getElementById('encryptedInput').value.trim();
            const resultDiv = document.getElementById('result');
            
            if (!input) {
                resultDiv.innerHTML = '<p class="error">请输入加密数据</p>';
                return;
            }
            
            try {
                const response = await fetch('/api/decrypt', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ encrypted_data: input })
                });
                const data = await response.json();
                if (data.success) {
                    resultDiv.innerHTML = '<pre>' + JSON.stringify(data.decrypted_data, null, 2) + '</pre>';
                } else {
                    resultDiv.innerHTML = '<p class="error">解密失败: ' + data.error + '</p>';
                }
            } catch (e) {
                resultDiv.innerHTML = '<p class="error">请求失败: ' + e.message + '</p>';
            }
        }
    </script>
</body>
</html>
        """
        return HTMLResponse(content=html_content)

    @application.post("/api/decrypt")
    async def api_decrypt(encrypted_data: dict):
        try:
            data = encrypted_data.get("encrypted_data", "")
            if not data:
                return {"success": False, "error": "缺少加密数据"}
            
            decrypted = decrypt_data(data)
            if decrypted == {} and data:
                return {"success": False, "error": "解密失败，数据格式不正确"}
            
            return {"success": True, "decrypted_data": decrypted}
        except Exception as e:
            return {"success": False, "error": str(e)}

    @application.get("/internal/", response_class=HTMLResponse)
    async def index():
        return """<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><title>民众普康</title>
<style>
body{font-family:system-ui,-apple-system,sans-serif;max-width:600px;margin:80px auto;text-align:center;color:#1a1a2e;background:#f5f6fa}
h1{font-size:28px;margin-bottom:8px}
h1 span{color:#6366f1}
p{color:#64748b;margin:4px 0}
a{color:#6366f1;text-decoration:none;font-weight:600}
a:hover{text-decoration:underline}
.cards{display:flex;gap:16px;justify-content:center;margin-top:32px}
.card{background:#fff;border:1px solid #e2e8f0;border-radius:12px;padding:20px 28px;text-align:center}
.card h3{margin:0 0 4px;font-size:16px}
.card p{font-size:13px;margin:0}
.badge{display:inline-block;background:#6366f1;color:#fff;font-size:11px;padding:2px 8px;border-radius:6px;margin-bottom:12px}
</style></head>
<body>
<div class="badge">Backend Running</div>
<h1>民众普康<span>.AI</span></h1>
<p>后端 API 服务</p>
<p style="font-size:13px;margin-top:12px">版本 v""" + settings.APP_VERSION + """</p>
<div class="cards">
<div class="card"><h3><a href="/internal/api-docs">API 文档</a></h3><p>Swagger UI 交互式文档</p></div>
<div class="card"><h3><a href="/internal/api-redoc">ReDoc</a></h3><p>ReDoc 格式文档</p></div>
<div class="card"><h3><a href="/internal/status">服务状态</a></h3><p>Celery/Redis 监控</p></div>
<div class="card"><h3><a href="/internal/decrypt-data">解密数据</a></h3><p>数据解密</p></div>
</div>
</body></html>"""

    return application


app = create_app()
