import time
import logging
import datetime
import jwt
from django.utils import timezone
from django.utils.deprecation import MiddlewareMixin
from django.conf import settings
from .context import TrackerContext
from .models import OperationLog
from .queue import enqueue_log
from .utils import get_client_ip, mask_sensitive_data

logger = logging.getLogger(__name__)


class RequestLogMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.trace_id = TrackerContext.start_trace()
        request.start_time = timezone.now()

    def process_view(self, request, view_func, view_args, view_kwargs):
        # 尝试从 Token 中解析用户信息
        self._set_user_context(request)
        request.view_name = view_func.__name__
        request.view_module = view_func.__module__
        return None

    def process_response(self, request, response):
        if not getattr(request, '_logged', False):
            self._log_request(request, response)
            request._logged = True
        return response

    def process_exception(self, request, exception):
        if not getattr(request, '_logged', False):
            self._log_request(request, None, exception)
            request._logged = True
        return None

    def _set_user_context(self, request):
        """
        尝试从请求头中的 Authorization Bearer Token 解析用户 ID。
        """
        # 优先使用 request.user (如果已经由其他认证中间件设置)
        if hasattr(request, 'user') and getattr(request.user, 'is_authenticated', False):
            TrackerContext.set_user(request.user)
            return

        # 如果没有 request.user，尝试手动解析 JWT
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        if not auth_header or not auth_header.startswith('Bearer '):
            return

        try:
            token = auth_header.split(' ')[1]
        except IndexError:
            return

        config = getattr(settings, 'DJANGO_OPS_LOGGER', {})

        jwt_secret_key = getattr(settings, config.get('JWT_SECRET_KEY'), None)

        if not jwt_secret_key:
            return

        try:
            # 尝试解码 JWT
            # 注意：这里默认使用 HS256 算法，如果项目使用 RS256 等需要额外配置
            # verify=False 意味着我们不验证签名，只解码内容？不，用户需要验证。
            # 如果解密失败，说明 Token 无效，我们不记录用户信息即可，不应报错。
            payload = jwt.decode(token, jwt_secret_key, algorithms=['HS256'], verify=True)

            # 假设 payload 中包含 'user_id' 或 'id' 字段
            user_id = payload.get('user_id') or payload.get('id') or payload.get('user')
            if user_id:
                # 构造一个简单的用户对象模拟
                class SimpleUser:
                    pk = user_id
                    username = payload.get('username', '')
                    is_authenticated = True

                    def get_username(self):
                        return self.username

                user = SimpleUser()
                request.dj_ops_log_user = user  # 将解析出的用户挂载到 request
                TrackerContext.set_user(user)

        except jwt.ExpiredSignatureError:
            pass  # Token 过期
        except jwt.InvalidTokenError:
            pass  # 无效 Token
        except Exception as e:
            # logger.warning(f"Failed to parse JWT token in logging middleware: {e}")
            pass

    def _log_request(self, request, response=None, exception=None):
        if not hasattr(request, 'start_time'):
            return

        # Skip logging for static files
        if request.path.startswith(getattr(settings, 'STATIC_URL', '/static/')):
            return

        end_time = timezone.now()
        duration = (end_time - request.start_time).total_seconds() * 1000

        status_code = response.status_code if response else 500

        details = {
            'method': request.method,
            'path': request.path,
            'query_params': dict(request.GET),
            'view_func': getattr(request, 'view_name', ''),
            'view_module': getattr(request, 'view_module', ''),
            'status_code': status_code,
        }

        if exception:
            details['exception'] = str(exception)
            operation_type = OperationLog.OpType.EXCEPTION
            level = 'ERROR'
        else:
            operation_type = OperationLog.OpType.REQUEST
            if status_code >= 500:
                level = 'ERROR'
            elif status_code >= 400:
                level = 'WARNING'
            else:
                level = 'INFO'

        user_id = None
        username = None

        # 此时 request.user 可能是我们手动解析构造的 SimpleUser
        if hasattr(request, 'dj_ops_log_user') and getattr(request.dj_ops_log_user, 'is_authenticated', False):
            user_id = str(request.dj_ops_log_user.pk)
            username = getattr(request.dj_ops_log_user, 'username', '')

        enqueue_log(
            trace_id=getattr(request, 'trace_id', TrackerContext.get_trace_id()),
            operation_type=operation_type,
            level=level,
            start_time=request.start_time,
            end_time=end_time,
            duration=duration,
            user_id=user_id,
            username=username,
            ip_address=get_client_ip(request),
            details=details,
        )
