#!/usr/bin/env python
# @Project ：django_base_ai
# @File    : base_analyze.py
# @Author  : cx
# @Time    : 11/2/2025
# @Desc    : 登录与操作数据分析统计
import json
import logging

from django.conf import settings
from django.core.cache import cache
from django.db.models import Count, Q
from django.db.models.functions import TruncMonth
from django_redis import get_redis_connection
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet

from django_base_ai.system.models import Dept, LoginLog, OperationLog, Users
from django_base_ai.utils.datetime_range_generator import get_date_range
from django_base_ai.utils.json_response import DetailResponse

logger = logging.getLogger(__name__)


class AnalyzeView(ViewSet):
    permission_classes = [AllowAny]
    cache_timeout = getattr(settings, "DEPT_LOGIN_CACHE_TIMEOUT", 3600 * 1)

    @action(methods=["get", "post"], detail=False, permission_classes=[AllowAny], authentication_classes=[])
    def read_redis_operation_log(self, request, *args, **kwargs):
        """
        同步请求日志数据接口
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        # 获取 Redis 连接
        redis_conn = get_redis_connection("default")
        operation_log_list = list()
        for i in range(1000):
            popped_item = redis_conn.rpop("redis_operation_log")
            if not popped_item:
                break
            popped_item = json.loads(popped_item.decode("utf-8"))
            operation_log_list.append(OperationLog(**popped_item))
        if operation_log_list:
            OperationLog.objects.bulk_create(operation_log_list)
        return Response({"msg": "已完成"})

    @action(methods=["get"], detail=False, permission_classes=[AllowAny], authentication_classes=[])
    def branches_login_statistical(self, request, *args, **kwargs):
        """
        根据分行统计登录次数（按月统计）
        返回格式: [
            {
                "name": "分行名称",
                "count": 总登录次数,
                "months": {
                    "2025-01": 1月登录次数,
                    "2025-02": 2月登录次数,
                    ...
                    "2025-12": 12月登录次数
                }
            }
        ]
        """
        # 获取查询参数
        start_month = request.query_params.get("start_month", None)
        end_month = request.query_params.get("end_month", None)
        start_date, end_date, months, start_month, end_month = get_date_range(start_month, end_month)

        # 缓存设置
        cache_key = f"branches_login_statistical_{start_month}_{end_month}"

        # 尝试从缓存获取数据
        cached_data = cache.get(cache_key)
        if cached_data is not None:
            return DetailResponse(cached_data)

        # 缓存未命中，执行统计逻辑
        branches = Users.objects.values("main_department").distinct().order_by("main_department")

        result = []
        for branch in branches:
            branch_name = branch["main_department"]

            # 获取该分行下的所有部门ID（递归）
            def get_dept_ids(dept_name):
                depts = Dept.objects.filter(name=dept_name).values_list("id", flat=True)
                dept_ids = list(depts)
                children = Dept.objects.filter(parent__name=dept_name).values_list("id", flat=True)
                dept_ids.extend(children)
                return dept_ids

            dept_ids = get_dept_ids(branch_name)
            if not dept_ids:
                continue

            # 获取这些部门下的所有用户ID
            user_ids = Users.objects.filter(dept__id__in=dept_ids).values_list("id", flat=True)

            # 按月统计登录次数
            monthly_stats = (
                LoginLog.objects.filter(creator__in=user_ids, create_datetime__range=(start_date, end_date))
                .annotate(
                    month=TruncMonth("create_datetime")  # 改为使用TruncMonth获取完整的年月
                )
                .values("month")
                .annotate(count=Count("id"))
                .order_by("month")
            )

            # 初始化月份数据
            months_data = {month: 0 for month in months}  # 直接使用YYYY-MM格式

            # 填充实际数据
            for stat in monthly_stats:
                month_key = stat["month"].strftime("%Y-%m")  # 格式化为YYYY-MM
                if month_key in months_data:
                    months_data[month_key] = stat["count"]

            # 计算总登录次数
            total_count = sum(months_data.values())

            # 添加到结果集
            result.append({"name": branch_name, "count": total_count, "months": months_data})

        # 按总登录次数降序排序
        sorted_result = sorted(result, key=lambda x: x["count"], reverse=True)
        # 将结果存入缓存
        cache.set(cache_key, sorted_result, timeout=self.cache_timeout)

        return DetailResponse(sorted_result)

    @action(methods=["get"], detail=False, permission_classes=[AllowAny], authentication_classes=[])
    def dept_login_statistical(self, request, *args, **kwargs):
        """
        根据组织架构统计登录次数（树状结构按月统计）
        返回格式: {
            "start_month": "2025-01",
            "end_month": "2025-08",
            "total": {
                "name": "全部部门",
                "count": 总登录次数,
                "months": {"2025-01": 1月登录次数, ..., "2025-12": 12月登录次数}
            },
            "departments": [
                {
                    "id": 部门ID,
                    "name": "部门名称",
                    "short_name": "部门简称",
                    "count": 总登录次数,
                    "months": {"2025-01": 1月登录次数, ..., "2025-12": 12月登录次数},
                    "children": [子部门...]
                },
                ...
            ]
        }
        """
        # 获取查询参数
        start_month = request.query_params.get("start_month", None)
        end_month = request.query_params.get("end_month", None)
        start_date, end_date, months, start_month, end_month = get_date_range(start_month, end_month)

        # 缓存设置
        cache_key = f"dept_tree_login_statistical_{start_month}_{end_month}"
        cache_timeout = getattr(settings, "DEPT_LOGIN_CACHE_TIMEOUT", 3600 * 1)

        # 尝试从缓存获取数据
        cached_data = cache.get(cache_key)
        if cached_data is not None:
            return DetailResponse(cached_data)

        # 构建部门树状统计
        def build_dept_tree(dept):
            # 获取当前部门及其所有子部门的ID
            dept_ids = [dept.id]
            children = Dept.objects.filter(parent=dept).order_by("sort")

            # 递归处理子部门
            child_nodes = []
            for child in children:
                child_node = build_dept_tree(child)
                child_nodes.append(child_node)
                dept_ids.extend(child_node["all_children"])

            # 获取这些部门下的所有用户ID
            user_ids = Users.objects.filter(dept__id__in=dept_ids).values_list("id", flat=True)

            # 按月统计登录次数（使用TruncMonth获取完整的年月）
            monthly_stats = (
                LoginLog.objects.filter(creator__in=user_ids, create_datetime__range=(start_date, end_date))
                .annotate(
                    month=TruncMonth("create_datetime")  # 改为使用TruncMonth
                )
                .values("month")
                .annotate(count=Count("id"))
                .order_by("month")
            )

            # 初始化月份数据（使用YYYY-MM格式）
            months_data = {month: 0 for month in months}

            # 填充实际数据
            for stat in monthly_stats:
                month_key = stat["month"].strftime("%Y-%m")  # 格式化为YYYY-MM
                if month_key in months_data:
                    months_data[month_key] = stat["count"]

            # 计算总登录次数
            total_count = sum(months_data.values())

            # 构建返回结构
            node = {
                "id": dept.id,
                "name": dept.name,
                "short_name": dept.short_name or "",
                "count": total_count,
                "months": months_data,  # 使用YYYY-MM格式
                "children": child_nodes,
                "all_children": dept_ids,  # 包含所有子部门ID
            }

            return node

        # 从顶级部门开始构建树
        top_depts = Dept.objects.filter(parent__isnull=True).order_by("sort")
        departments = [build_dept_tree(dept) for dept in top_depts]

        # 计算系统总登录数（所有顶级部门之和）
        total_stats = {month: 0 for month in months}  # 使用YYYY-MM格式
        total_count = 0

        for dept in departments:
            total_count += dept["count"]
            for month in total_stats:
                total_stats[month] += dept["months"].get(month, 0)

        # 构建最终返回结构
        response_data = {
            "start_month": start_month,
            "end_month": end_month,
            "total": {
                "name": "全部部门",
                "count": total_count,
                "months": total_stats,  # 使用YYYY-MM格式
            },
            "departments": departments,
        }

        # 将结果存入缓存
        cache.set(cache_key, response_data, timeout=cache_timeout)

        return DetailResponse(response_data)

    @action(methods=["get"], detail=False, permission_classes=[AllowAny], authentication_classes=[])
    def operation_log_statistical(self, request, *args, **kwargs):
        """
        操作日志统计分析（支持自定义起止月份）
        返回格式: {
            "start_month": "2025-01",
            "end_month": "2025-08",
            "data": [
                {
                    "request_path": "/docs",
                    "display_name": "向日葵",
                    "months": {"2025-01": 访问次数, ...},
                    "total": 总访问次数（从高到低排序）
                },
                ...
            ]
        }
        """
        # 路径映射配置
        path_mapping = getattr(settings, "PATH_MAPPING", {})
        # 获取查询参数
        start_month = request.query_params.get("start_month", None)
        end_month = request.query_params.get("end_month", None)
        start_date, end_date, months, start_month, end_month = get_date_range(start_month, end_month)
        # 缓存设置
        cache_key = f"oplog_stats_{start_month}_{end_month}_v2"
        cache_timeout = getattr(settings, "OPLOG_STATS_CACHE_TIMEOUT", 3600 * 6)  # 默认缓存6小时
        # 尝试从缓存获取数据
        cached_data = cache.get(cache_key)
        if cached_data is not None:
            return DetailResponse(cached_data)
        # 初始化结果数据
        result_data = []
        months_template = {month: 0 for month in months}
        # 批量查询优化
        for path, display_name in path_mapping.items():
            # 按月统计该路径的访问量
            monthly_stats = (
                OperationLog.objects.filter(~Q(request_path=None))
                .filter(Q(request_path__startswith=path) & Q(create_datetime__range=(start_date, end_date)))
                .annotate(month=TruncMonth("create_datetime"))
                .values("month")
                .annotate(count=Count("id"))
                .order_by("month")
            )
            # 填充月份数据
            months_data = months_template.copy()
            total = 0
            for stat in monthly_stats:
                month_key = stat["month"].strftime("%Y-%m")
                if month_key in months_data:  # 只包含在查询范围内的月份
                    months_data[month_key] = stat["count"]
                    total += stat["count"]
            # 添加到结果集
            result_data.append(
                {"request_path": path, "display_name": display_name, "months": months_data, "total": total}
            )
        # 按total从高到低排序
        sorted_data = sorted(result_data, key=lambda x: x["total"], reverse=True)
        # 构建最终响应数据
        response_data = {"start_month": start_month, "end_month": end_month, "data": sorted_data}
        # 设置缓存
        cache.set(cache_key, response_data, timeout=cache_timeout)
        return DetailResponse(response_data)

    @action(methods=["get"], detail=False, permission_classes=[AllowAny], authentication_classes=[])
    def new_users_statistical(self, request, *args, **kwargs):
        """
        新增用户统计分析（基于首次登录时间）
        统计每个月新增的登录用户数（去重统计）
        返回格式: {
            "start_month": "2025-01",
            "end_month": "2025-08",
            "total_users": 总用户数,
            "data": [
                {
                    "month": "2025-01",
                    "new_users_count": 当月新增用户数,
                    "cumulative_count": 累计用户数
                },
                ...
            ]
        }
        """
        # 获取查询参数
        start_month = request.query_params.get("start_month", None)
        end_month = request.query_params.get("end_month", None)
        start_date, end_date, months, start_month, end_month = get_date_range(start_month, end_month)

        # 缓存设置
        cache_key = f"new_users_statistical_{start_month}_{end_month}"

        # 尝试从缓存获取数据
        cached_data = cache.get(cache_key)
        if cached_data is not None:
            return DetailResponse(cached_data)

        # 获取每个用户的首次登录时间
        # 使用子查询找出每个用户的最早登录时间
        from django.db.models import Min

        # 获取每个用户的首次登录记录
        (
            LoginLog.objects.values("creator")
            .annotate(first_login=Min("create_datetime"))
            .values("creator", "first_login")
        )

        # 统计在查询时间范围内首次登录的用户，按月分组
        monthly_new_users = (
            LoginLog.objects.filter(create_datetime__range=(start_date, end_date))
            .values("creator")
            .annotate(first_login=Min("create_datetime"))
            .annotate(month=TruncMonth("first_login"))
            .values("month")
            .annotate(new_users_count=Count("creator", distinct=True))
            .order_by("month")
        )

        # 初始化月份数据
        months_data = []
        cumulative_count = 0

        # 获取查询时间范围之前的用户总数（作为基数）
        before_start_users = (
            LoginLog.objects.filter(create_datetime__lt=start_date).values("creator").distinct().count()
        )

        cumulative_count = before_start_users

        # 创建月份统计数据字典，方便查找
        monthly_stats_dict = {}
        for stat in monthly_new_users:
            month_key = stat["month"].strftime("%Y-%m")
            monthly_stats_dict[month_key] = stat["new_users_count"]

        # 生成完整的月份数据
        for month in months:
            new_users_count = monthly_stats_dict.get(month, 0)
            cumulative_count += new_users_count
            months_data.append(
                {"month": month, "new_users_count": new_users_count, "cumulative_count": cumulative_count}
            )
        # 计算总的登录用户数（去重）
        total_users = LoginLog.objects.values("creator").distinct().count()
        # 构建返回数据
        response_data = {
            "start_month": start_month,
            "end_month": end_month,
            "total_users": total_users,
            "before_start_users": before_start_users,
            "data": months_data,
        }
        # 将结果存入缓存
        cache.set(cache_key, response_data, timeout=self.cache_timeout)
        return DetailResponse(response_data)
