import time
import json
import logging
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.types import ASGIApp

logger = logging.getLogger(__name__)


class APILogMiddleware(BaseHTTPMiddleware):
    """API调用日志中间件 - 记录每次API请求到 api_call_logs 表"""

    LOG_METHODS = {"GET", "POST", "PUT", "DELETE", "PATCH"}

    SKIP_PATHS = {"/health", "/docs", "/redoc", "/openapi.json"}

    async def dispatch(self, request, call_next):
        start_time = time.time()
        response = await call_next(request)
        duration_ms = int((time.time() - start_time) * 1000)

        method = request.method
        path = request.url.path

        if method not in self.LOG_METHODS or path in self.SKIP_PATHS:
            return response

        try:
            user_id = None
            authorization = request.headers.get("authorization")
            if authorization:
                from ..core.auth import verify_token
                token = authorization.replace("Bearer ", "") if authorization.startswith("Bearer ") else authorization
                user = verify_token(token)
                if user:
                    user_id = user.get("userId")

            log_data = {
                "user_id": user_id,
                "endpoint": path,
                "method": method,
                "status_code": response.status_code,
                "duration_ms": duration_ms,
                "ip_address": request.client.host if request.client else "unknown",
                "user_agent": request.headers.get("user-agent", "")[:500],
            }

            from ..core.database import get_db, _is_sqlite
            if _is_sqlite():
                # SQLite 模式：直接使用 get_db() 获取连接
                async for db in get_db():
                    conn, cur = db
                    try:
                        await cur.execute(
                            """INSERT INTO api_call_logs
                               (user_id, endpoint, method, status_code, duration_ms, ip_address, user_agent)
                               VALUES (?, ?, ?, ?, ?, ?, ?)""",
                            (
                                log_data["user_id"],
                                log_data["endpoint"],
                                log_data["method"],
                                log_data["status_code"],
                                log_data["duration_ms"],
                                log_data["ip_address"],
                                log_data["user_agent"],
                            ),
                        )
                        await conn.commit()
                    except Exception:
                        pass  # 日志写入失败不影响主流程
                    break
            else:
                # MySQL 模式：使用连接池
                from ..core.database import get_pool
                pool = await get_pool()
                if pool:
                    async with pool.acquire() as conn:
                        async with conn.cursor() as cur:
                            await cur.execute(
                                """INSERT INTO api_call_logs
                                   (user_id, endpoint, method, status_code, duration_ms, ip_address, user_agent)
                                   VALUES (%s, %s, %s, %s, %s, %s, %s)""",
                                (
                                    log_data["user_id"],
                                    log_data["endpoint"],
                                    log_data["method"],
                                    log_data["status_code"],
                                    log_data["duration_ms"],
                                    log_data["ip_address"],
                                    log_data["user_agent"],
                                ),
                            )
        except Exception as e:
            logger.warning(f"[APILog] failed to write log: {e}")

        return response
