#!/usr/bin/env python
# @Project ：django_base_ai
# @File    : login_log.py
# @Author  : cx
# @Time    : 11/2/2025
# @Desc    : 登录日志查询与统计。
import logging
from collections import defaultdict

from django.db.models import Count
from django.db.models.functions import TruncDate, TruncMonth
from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny

from django_base_ai.system.models import LoginLog
from django_base_ai.utils.datetime_range_generator import get_date_range
from django_base_ai.utils.json_response import DetailResponse
from django_base_ai.utils.serializers import CustomModelSerializer
from django_base_ai.utils.viewset import CustomModelViewSet

logger = logging.getLogger(__name__)


class LoginLogSerializer(CustomModelSerializer):
    """
    登录日志权限-序列化器
    """

    class Meta:
        model = LoginLog
        fields = "__all__"
        read_only_fields = ["id"]


class ExportLoginLogSerializer(CustomModelSerializer):
    login_type = serializers.SerializerMethodField(read_only=True)

    def get_login_type(self, obj):
        if obj.login_type and obj.login_type < len(LoginLog.LOGIN_TYPE_CHOICES):
            return LoginLog.LOGIN_TYPE_CHOICES[obj.login_type][1]
        return "未知"

    class Meta:
        model = LoginLog
        fields = "__all__"
        read_only_fields = ["id"]


class LoginLogViewSet(CustomModelViewSet):
    """
    登录日志接口
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """

    queryset = LoginLog.objects.all()
    serializer_class = LoginLogSerializer
    extra_filter_backends = []
    filter_fields = ["login_type"]
    search_fields = ["username", "ip"]
    ordering_fields = ["create_datetime"]
    # 导出
    export_field_label = {
        "login_type": "登录类型",
        "username": "登录用户名",
        "ip": "登录ip",
        "agent": "agent信息",
        "browser": "浏览器名",
        "os": "操作系统",
    }
    export_serializer_class = ExportLoginLogSerializer

    @action(methods=["get"], detail=False, permission_classes=[AllowAny], authentication_classes=[])
    def statistics_day(self, request, *args, **kwargs):
        """
        用户统计分析(按天)
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        result = (
            LoginLog.objects.annotate(date_only=TruncDate("create_datetime"))  # 提取年月日
            .values("creator", "login_type", "date_only")  # 按用户、登录类型、日期分组
            .distinct()  # 每个用户每天的登录只计一次
            .annotate(total_count=Count("id"))  # 统计每个用户每种类型的登录次数
            .order_by("creator", "date_only", "login_type")
        )
        return DetailResponse(result)

    @action(methods=["get"], detail=False, permission_classes=[AllowAny], authentication_classes=[])
    def statistics(self, request, *args, **kwargs):
        """
        用户统计分析（按年月和登录类型）
        参数:
            start_month: 起始月份，格式为YYYY-MM（如2025-01）
            end_month: 结束月份，格式为YYYY-MM（如2025-12）
        返回格式: {
            "start_month": "2025-01",
            "end_month": "2025-12",
            "data": [
                {
                    "month": "2025-01",
                    "login_types": {
                        "1": {"label": "默认登录", "count": 100},
                        "2": {"label": "移动端", "count": 50},
                        "3": {"label": "SSOLOGIN登录", "count": 30}
                    }
                },
                ...
            ]
        }
        """
        # 获取查询参数
        start_month = request.query_params.get("start_month")
        end_month = request.query_params.get("end_month")
        start_date, end_date, months, start_month, end_month = get_date_range(start_month, end_month)

        # 查询登录日志
        logs = LoginLog.objects.filter(create_datetime__range=(start_date, end_date))

        # 统计每月活跃账号数（月活）
        # 假设活跃账号字段为 username，如需用 creator 可替换
        month_user_dict = defaultdict(set)
        logs_for_active = logs.annotate(month=TruncMonth("create_datetime")).values("month", "username")
        for item in logs_for_active:
            if item["month"] and item["username"]:
                month_str = item["month"].strftime("%Y-%m")
                month_user_dict[month_str].add(item["username"])

        # 按年月和登录类型分组统计
        statistics = (
            logs.annotate(month=TruncMonth("create_datetime"))
            .values("month", "login_type")
            .annotate(count=Count("id"))
            .order_by("month", "login_type")
        )

        # 将查询结果转换为嵌套字典，方便查找
        stats_dict = defaultdict(lambda: defaultdict(int))
        for item in statistics:
            month_str = item["month"].strftime("%Y-%m")  # 格式化为 "YYYY-MM"
            stats_dict[month_str][item["login_type"]] = item["count"]

        # 生成完整的月份数据（基于查询的月份范围）
        full_stats = []
        for month in months:  # 使用动态生成的月份列表
            month_data = {
                "month": month,
                "login_types": {},
                "active_users": len(month_user_dict[month]),  # 新增月活字段
            }
            # 遍历所有登录类型，确保每种类型都有数据
            for login_type, label in ((1, "默认登录"), (2, "SSOLOGIN登录"), (3, "移动端")):
                month_data["login_types"][login_type] = {
                    "label": label,
                    "count": stats_dict[month].get(login_type, 0),  # 如果类型不存在，则 count 为 0
                }
            full_stats.append(month_data)

        # 按时间顺序排序
        full_stats.sort(key=lambda x: x["month"])

        # 格式化结果
        return DetailResponse({"start_month": start_month, "end_month": end_month, "data": full_stats})
