#!/usr/bin/env python
# @Project ：django_base_ai
# @File    : apps.py
# @Author  : cx
# @Time    : 11/2/2025
# @Desc    : 应用与消息任务管理接口
import json
import logging
import uuid
from datetime import datetime

from django.core.cache import cache
from django.shortcuts import HttpResponse
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny, IsAdminUser

from django_base_ai.system.models import (
    Apps,
    MessageCenter,
    MessageCenterTargetUser,
    OperationLog,
    SendMessageTask,
    Users,
)
from django_base_ai.utils import xss_cleaned
from django_base_ai.utils.json_response import DetailResponse, ErrorResponse, SuccessResponse
from django_base_ai.utils.message import client, smtp_email
from django_base_ai.utils.permission import OpenApiPermission
from django_base_ai.utils.serializers import CustomModelSerializer
from django_base_ai.utils.viewset import CustomModelViewSet

logger = logging.getLogger(__name__)


class AppsSerializer(CustomModelSerializer):
    class Meta:
        model = Apps
        exclude = [
            "secret",
        ]
        read_only_fields = ["id"]


class AppsCreateSerializer(CustomModelSerializer):
    """
    地区管理 创建/更新时的列化器
    """

    def save(self, **kwargs):
        data = super().save(**kwargs)
        data.agent_id = data.agent_id if data.agent_id else f"agent_{uuid.uuid4()}"
        data.secret = data.secret if data.secret else f"secret_{uuid.uuid1() + uuid.uuid4()}"
        data.creator = self.request.user.id
        data.modifier = self.request.user.id
        data.dept_belong_id = self.request.user.dept.id if self.request.user and self.request.user.dept else 1
        data.save()
        return data

    class Meta:
        model = Apps
        exclude = ["secret"]
        read_only_fields = ["id"]


class AppsUpdateSerializer(CustomModelSerializer):
    """
    地区管理 创建/更新时的列化器
    """

    class Meta:
        model = Apps
        exclude = ["secret"]
        read_only_fields = ["id"]


class AppsViewSet(CustomModelViewSet):
    """
    应用管理接口
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """

    queryset = Apps.objects.all()
    serializer_class = AppsSerializer
    create_serializer_class = AppsCreateSerializer
    update_serializer_class = AppsUpdateSerializer
    search_fields = ["title"]

    # extra_filter_backends = []

    @action(methods=["get"], detail=False, permission_classes=[IsAdminUser])
    def agent_info(self, request, *args, **kwargs):
        """
        查看应用密钥
        :param request:
        :return:
        """
        nid = request.GET.get("nid", 0)
        if nid == 0:
            return ErrorResponse(msg="参数错误")
        app_info = Apps.objects.filter(id=nid, creator=request.user.id).first()
        if app_info is None:
            return ErrorResponse(msg="您无权访问或应用不存在")
        return DetailResponse({"agent_id": app_info.agent_id, "secret": app_info.secret})

    @action(methods=["post"], detail=False, permission_classes=[AllowAny], authentication_classes=[])
    def get_suite_token(self, request, *args, **kwargs):
        """
        第三方应用登录
        :param request:
        :return:
        """
        agent_id = str(request.data.get("agent_id", "")).strip()
        secret = str(request.data.get("secret", "")).strip()
        if agent_id == "" or secret == "":
            return ErrorResponse(msg="参数错误,应用id或密钥不能为空")
        app_info = Apps.objects.filter(agent_id=agent_id).first()
        if app_info is None or secret != app_info.secret:
            return ErrorResponse(msg="参数错误,请检查参数是否合法")
        ticket = f"{uuid.uuid1().hex + uuid.uuid4().hex}{int(datetime.now().timestamp())}"
        cache.set(ticket, app_info.id, timeout=1800)
        return DetailResponse(data=ticket)

    @action(methods=["post"], detail=False, permission_classes=[OpenApiPermission], authentication_classes=[])
    def async_send_email(self, request, *args, **kwargs):
        """
        异步发送邮件
        :param request:
        :param args:
        :param kwargs:
        {
        "subject":"测试",
        "content":"邮件内容",
        "to_mails":["2262511449@qq.com"],
        "file_list":[]
        }
        :return:
        """
        from celery_tasks.tasks import send_email_message

        apps_id = cache.get(request.META.get("HTTP_AUTHORIZATION", None))
        apps_info = Apps.objects.filter(id=apps_id).first()
        # 邮件标题
        subject = request.data.get("subject", None)
        # 邮件内容
        content = request.data.get("content", None)
        # 收件人
        to_mails = request.data.get("to_mails", [])
        # 附件
        file_list = request.data.get("file_list", [])
        if not subject or not content or not to_mails:
            return ErrorResponse(msg=f"参数错误,邮件标题:{subject},收件人:{to_mails},邮件内容不能为空")
        app_user = Users.objects.filter(id=apps_info.creator).first()
        send_message_task = SendMessageTask.objects.create(
            apps_id=apps_id, creator=apps_info.creator, modifier=apps_info.modifier
        )
        result = send_email_message.apply_async(
            args=[
                send_message_task.id,
                subject,
                content,
                str(apps_info.creator),
                app_user.dept.id if app_user.dept else "",
                to_mails,
                file_list,
            ]
        )
        send_message_task.task_name = result.status
        send_message_task.task_id = result.task_id
        send_message_task.save()
        return DetailResponse(msg="后台任务已启动,请稍后刷新当前页面,重新加载数据", data=result.task_id)

    @action(methods=["post"], detail=False, permission_classes=[OpenApiPermission], authentication_classes=[])
    def sync_send_email(self, request, *args, **kwargs):
        """
        同步发送邮件
        :param request:
        :param args:
        :param kwargs:
        {
        "subject":"测试",
        "content":"邮件内容",
        "to_mails":["2262511449@qq.com"],
        "file_list":[]
        }
        :return:
        """
        apps_id = cache.get(request.META.get("HTTP_AUTHORIZATION", None))
        # 邮件标题
        subject = xss_cleaned.cleaned_string(request.data.get("subject", ""))
        # 简要描述
        short_content = request.data.get("short_content", "")
        # 邮件内容
        content = request.data.get("content", "")
        # 收件人
        to_mails = list(set(request.data.get("to_mails", [])))
        # 附件
        file_list = request.data.get("file_list", [])
        if not subject or not content or not to_mails:
            return ErrorResponse(msg=f"参数错误,邮件标题:{subject},收件人:{to_mails},邮件内容不能为空")
        apps_info = Apps.objects.filter(id=apps_id).first()
        smtp_email_obj = smtp_email.SmtpEmail()
        user_info = Users.objects.filter(email__in=to_mails).values("id", "email", "dept_id")
        user_info_dict = {
            item.get("email"): {"id": item.get("id"), "dept_id": item.get("dept_id")} for item in user_info
        }
        for to_mail in to_mails:
            send_user_dict = user_info_dict.get(to_mail, 0)
            if send_user_dict:
                user_id = send_user_dict.get("id", None)
                send_mails_result = smtp_email_obj.send(to_mail, subject, content, file_list)
                message_center = MessageCenter.objects.create(
                    title=subject,
                    short_content=short_content,
                    content=content,
                    message_type=1,
                    file_list=file_list,
                    ext_kwargs={
                        "msg_type": 1,
                        "user_info": {"uid": 2, "name": apps_info.title, "username": None, "avatar": apps_info.icon},
                    },
                    dept_belong_id=send_user_dict.get("dept_id", ""),
                    creator=user_id,
                    modifier=user_id,
                )
                MessageCenterTargetUser.objects.create(
                    users_id=user_id,
                    messagecenter=message_center,
                    send_mails_result=send_mails_result,
                    dept_belong_id=send_user_dict.get("dept_id", ""),
                    creator=user_id,
                    modifier=user_id,
                )
        return DetailResponse(msg="发送成功", data=[])

    @action(methods=["post"], detail=False, permission_classes=[OpenApiPermission], authentication_classes=[])
    def send_client_msg(self, request, *args, **kwargs):
        """
        发送客户端通知
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        apps_id = cache.get(request.META.get("HTTP_AUTHORIZATION", None))
        apps_info = Apps.objects.filter(id=apps_id).first()
        app_user = Users.objects.filter(id=apps_info.creator).first()
        SendMessageTask.objects.create(
            apps_id=apps_id,
            send_type=1,
            dept_belong_id=app_user.dept.id if app_user.dept else "",
            creator=apps_info.creator,
            modifier=apps_info.modifier,
        )
        title = request.data.get("title", "")
        short_content = request.data.get("short_content", "")
        message_type = request.data.get("message_type", "")
        thumbnail = request.data.get("thumbnail", "")
        content = xss_cleaned.cleaned_string(request.data.get("content", ""))
        url = request.data.get("url", "")
        send_user_info = request.data.get("send_user_info", "")
        if not title or not short_content or not content or not url or not send_user_info:
            return ErrorResponse(
                msg=f"参数错误,请检查参数是否合法,title={title},short_content={short_content},message_type={message_type},content={content},url={url},send_user_info={send_user_info}"
            )
        client_obj = client.Client()
        payload = {
            "title": title,
            "short_content": short_content,
            "message_type": message_type,
            "thumbnail": thumbnail,
            "content": content,
            "url": url,
            "send_user_info": send_user_info,
        }
        send_json = client_obj.send(payload)
        print(send_json)
        return HttpResponse(json.dumps(send_json), content_type="application/json")

    @action(methods=["post"], detail=False, permission_classes=[OpenApiPermission], authentication_classes=[])
    def cleaned_xss(self, request, *args, **kwargs):
        """
        XSS 注入
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        safe_content = xss_cleaned.cleaned_string(request.data.get("content"))
        return SuccessResponse(data=safe_content)

    @action(methods=["post"], detail=False, permission_classes=[OpenApiPermission], authentication_classes=[])
    def access_log(self, request, *args, **kwargs):
        """
        操作记录
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        apps_id = cache.get(request.META.get("HTTP_AUTHORIZATION", None))
        apps_info = Apps.objects.filter(id=apps_id).first()
        username = request.data.get("um", "")
        current_user = Users.objects.filter(username=username).first()
        datainfo = {
            "appid": apps_info.id,
            "request_modular": request.data.get("request_modular", ""),
            "request_path": request.data.get("request_path", ""),
            "request_body": request.data.get("request_body", ""),
            "request_method": request.data.get("request_method", ""),
            "request_msg": request.data.get("request_msg", ""),
            "request_ip": request.data.get("request_ip", ""),
            "request_browser": request.data.get("request_browser", ""),
            "response_code": request.data.get("response_code", ""),
            "request_os": request.data.get("request_os", ""),
            "json_result": request.data.get("json_result", {}),
            "status": request.data.get("status", False),
            "description": request.data.get("description", ""),
            "dept_belong_id": current_user.dept.id if current_user and current_user.dept else "",
            "creator": current_user.creator if current_user else "",
            "modifier": current_user.modifier if current_user else "",
        }
        OperationLog.objects.create(**datainfo)
        return DetailResponse(msg="操作成功")
