"""Log Center integration — runtime error reporting + exception middleware."""

import os
import json
import logging
import traceback
import threading
from urllib.request import Request, urlopen
from urllib.error import URLError

LOG_CENTER_URL = os.getenv('LOG_CENTER_URL', 'https://qiyuan-log-center-api.airlabs.art')
LOG_CENTER_ENABLED = os.getenv('LOG_CENTER_ENABLED', 'false').lower() in ('true', '1', 'yes')
PROJECT_ID = 'video_backend'
ENVIRONMENT = os.getenv('ENVIRONMENT', 'development')

logger = logging.getLogger('log_center')


def report_error(exc, context=None):
    """Report a runtime error to Log Center (async, non-blocking)."""
    if not LOG_CENTER_ENABLED:
        return

    tb = traceback.extract_tb(exc.__traceback__)
    last_frame = tb[-1] if tb else None

    payload = {
        'project_id': PROJECT_ID,
        'environment': ENVIRONMENT,
        'level': 'ERROR',
        'error': {
            'type': type(exc).__name__,
            'message': str(exc),
            'file_path': last_frame.filename if last_frame else 'unknown',
            'line_number': last_frame.lineno if last_frame else 0,
            'stack_trace': ''.join(traceback.format_exception(exc)),
        },
        'context': context or {},
    }

    # Fire-and-forget in background thread
    threading.Thread(target=_send, args=(payload,), daemon=True).start()


def _send(payload):
    """Send payload to Log Center API."""
    try:
        data = json.dumps(payload).encode('utf-8')
        req = Request(
            f'{LOG_CENTER_URL}/api/v1/logs/report',
            data=data,
            headers={'Content-Type': 'application/json'},
            method='POST',
        )
        urlopen(req, timeout=3)
    except (URLError, Exception):
        pass  # Silent failure — never affect main business


# ──────────────────────────────────────────────
# Django Middleware: 捕获 DRF 之外的所有异常
# (模块导入失败、中间件错误、URL 解析错误等)
# ──────────────────────────────────────────────

class LogCenterMiddleware:
    """Django middleware to catch ALL unhandled exceptions and report to Log Center.

    DRF 的 custom_exception_handler 只能捕获视图内的异常。
    模块导入失败、中间件异常、URL 解析错误等发生在 DRF 之前，
    不会经过 DRF 的异常处理，需要这个中间件来兜底上报。

    异常捕获分工:
    - DRF 视图异常 → custom_exception_handler 上报 (DRF 内部 try/except 拦截,不会传播到中间件)
    - 非 DRF 视图异常 → process_exception 上报
    - 中间件/导入异常 → __call__ try/except 上报
    两层互不重复。
    """

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        try:
            response = self.get_response(request)
        except Exception as exc:
            # 捕获中间件链中的异常（如其他中间件报错、模块导入失败等）
            logger.error('Unhandled middleware exception: %s', exc, exc_info=True)
            report_error(exc, {
                'source': 'django_middleware',
                'request_path': getattr(request, 'path', 'unknown'),
                'request_method': getattr(request, 'method', 'unknown'),
                'user': str(getattr(request, 'user', 'anonymous')),
            })
            raise
        return response

    def process_exception(self, request, exception):
        """捕获非 DRF 视图的异常（普通 Django 视图、URL 解析错误等）。"""
        logger.error('Unhandled view exception: %s', exception, exc_info=True)
        report_error(exception, {
            'source': 'django_process_exception',
            'request_path': request.path,
            'request_method': request.method,
            'user': str(getattr(request, 'user', 'anonymous')),
        })
        return None  # 不处理响应，交给 Django 默认 500 handler


# ──────────────────────────────────────────────
# DRF Exception Handler: 捕获视图内异常 + 返回 JSON
# ──────────────────────────────────────────────

def custom_exception_handler(exc, context):
    """DRF custom exception handler with Log Center reporting."""
    from rest_framework.views import exception_handler
    from rest_framework.response import Response
    from rest_framework import status
    from rest_framework.exceptions import (
        MethodNotAllowed, NotAuthenticated, AuthenticationFailed,
        NotFound, PermissionDenied,
    )

    # Only report unexpected errors, skip normal HTTP client errors
    if not isinstance(exc, (MethodNotAllowed, NotAuthenticated,
                            AuthenticationFailed, NotFound,
                            PermissionDenied)):
        request = context.get('request')
        report_error(exc, {
            'source': 'drf_exception_handler',
            'view': str(context.get('view', '')),
            'request_path': getattr(request, 'path', None),
            'request_method': getattr(request, 'method', None),
            'user': str(getattr(request, 'user', 'anonymous')),
        })

    # Default DRF handling
    response = exception_handler(exc, context)

    # If DRF didn't handle it (unhandled exception), return JSON 500
    # instead of letting Django render an HTML error page
    if response is None:
        logger.error('Unhandled DRF exception: %s', exc, exc_info=True)
        response = Response(
            {'error': f'{type(exc).__name__}: {exc}'},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR,
        )

    return response
