"""
日报查询 API 视图。

- GET /api/news/reports/   日报查询（默认最近 24 小时；传 id 返回单份详情含事件）
- GET /api/news/events/    跨日报重要事件聚合（最近 N 天 importance >= 阈值）
"""

from datetime import datetime, timedelta

from django.utils import timezone
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework.decorators import api_view
from rest_framework.response import Response

from . import query as report_query
from .serializers import (
    ImportantEventSerializer,
    ReportDetailSerializer,
    ReportListSerializer,
)

_REPORT_TYPES = ("finance", "intl")
_SECTIONS = ("xwlb", "news", "cninfo", "intl")


def _parse_date_param(request, name):
    """解析 YYYY-MM-DD 参数，非法格式抛 ValueError。"""
    raw = request.GET.get(name)
    if not raw:
        return None
    try:
        return datetime.strptime(raw, "%Y-%m-%d").date()
    except ValueError:
        raise ValueError(f"{name} 格式错误，应为 YYYY-MM-DD")


@extend_schema(
    parameters=[
        OpenApiParameter(name='report_type', type=str, required=False,
                         description='日报类型：finance | intl（默认两者）'),
        OpenApiParameter(name='start_date', type=str, required=False,
                         description='起始日期 YYYY-MM-DD（默认：当前时间往前 24 小时）'),
        OpenApiParameter(name='end_date', type=str, required=False,
                         description='结束日期 YYYY-MM-DD（默认今天）'),
        OpenApiParameter(name='id', type=int, required=False,
                         description='日报 id，指定时返回单份详情（含事件，按板块/序号排序）'),
    ],
    responses={200: ReportDetailSerializer},
    description='AI 财经日报查询：默认返回最近 24 小时的日报列表（每天每类型取最新一份）；'
                '传 id 返回单份详情含事件',
    tags=['日报'],
)
@api_view(['GET'])
def news_reports(request):
    try:
        report_id = request.GET.get('id')
        if report_id is not None:
            report_id = int(report_id)
            if report_id <= 0:
                raise ValueError("id 必须为正整数")
        report_type = request.GET.get('report_type')
        if report_type and report_type not in _REPORT_TYPES:
            raise ValueError("report_type 仅支持 finance / intl")
        start_date = _parse_date_param(request, 'start_date')
        end_date = _parse_date_param(request, 'end_date')
    except ValueError as e:
        return Response({'error': str(e)}, status=400)

    now = timezone.now()
    start_date = start_date or (now - timedelta(hours=24)).date()
    end_date = end_date or now.date()

    try:
        data = report_query.fetch_reports(
            report_type=report_type,
            start_date=start_date,
            end_date=end_date,
            report_id=report_id,
        )
    except Exception as e:
        return Response({'error': f'查询失败: {e}'}, status=500)

    if report_id is not None:
        if data is None:
            return Response({'error': f'日报 id={report_id} 不存在'}, status=404)
        return Response(data)
    return Response(data)


def _get_int_param(request, name, default, lo, hi):
    """解析整数参数并校验范围，非法抛 ValueError。"""
    raw = request.GET.get(name)
    if raw is None:
        return default
    try:
        value = int(raw)
    except ValueError:
        raise ValueError(f"{name} 必须为整数")
    if not (lo <= value <= hi):
        raise ValueError(f"{name} 需在 {lo}~{hi} 之间")
    return value


@extend_schema(
    parameters=[
        OpenApiParameter(name='days', type=int, required=False, default=7,
                         description='最近 N 天（1~365）'),
        OpenApiParameter(name='importance', type=int, required=False, default=4,
                         description='最低重要度（1~5）'),
        OpenApiParameter(name='report_type', type=str, required=False,
                         description='日报类型：finance | intl（默认两者）'),
        OpenApiParameter(name='section', type=str, required=False,
                         description='板块：xwlb | news | cninfo | intl（默认全部）'),
        OpenApiParameter(name='limit', type=int, required=False, default=100,
                         description='返回条数上限（1~500）'),
    ],
    responses={200: ImportantEventSerializer(many=True)},
    description='跨日报重要事件聚合：最近 N 天 importance >= 阈值的事件，'
                '按重要度、日期降序',
    tags=['日报'],
)
@api_view(['GET'])
def news_events(request):
    try:
        days = _get_int_param(request, 'days', 7, 1, 365)
        importance = _get_int_param(request, 'importance', 4, 1, 5)
        limit = _get_int_param(request, 'limit', 100, 1, 500)
        report_type = request.GET.get('report_type')
        if report_type and report_type not in _REPORT_TYPES:
            raise ValueError("report_type 仅支持 finance / intl")
        section = request.GET.get('section')
        if section and section not in _SECTIONS:
            raise ValueError("section 仅支持 xwlb / news / cninfo / intl")
    except ValueError as e:
        return Response({'error': str(e)}, status=400)

    try:
        data = report_query.fetch_important_events(
            days=days,
            importance=importance,
            report_type=report_type,
            section=section,
            limit=limit,
        )
    except Exception as e:
        return Response({'error': f'查询失败: {e}'}, status=500)
    return Response(data)
