#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
system 应用信号：MessageCenter 创建时生成目标用户记录；Users 创建/更新/删除时回调应用；Tags 同。
含防止 AnonymousUser 写入库的 pre_save/post_save 处理。
"""
import json
import logging

import httpx
from django.db.models import Q
from django.db.models.signals import post_delete, post_save, pre_save
from django.dispatch import receiver

from django_base_ai.system.models import Apps, MessageCenter, MessageCenterTargetUser, Tags, Users
from django_base_ai.system.views.tags import TagsSerializer
from django_base_ai.system.views.user import UserSerializer
from django_base_ai.utils.format_core_base_auth import get_auth_user_info

logger = logging.getLogger(__name__)

"""
from django.core.signals import request_finished
from django.core.signals import request_started
from django.core.signals import got_request_exception
from django.db.models.signals import class_prepared
from django.db.models.signals import pre_init, post_init
from django.db.models.signals import pre_save, post_save
from django.db.models.signals import pre_delete, post_delete
from django.db.models.signals import m2m_changed
from django.db.models.signals import pre_migrate, post_migrate
from django.test.signals import setting_changed
from django.test.signals import template_rendered
from django.db.backends.signals import connection_created
"""
"""
Model signals
    pre_init                    # django的modal执行其构造方法前，自动触发
    post_init                   # django的modal执行其构造方法后，自动触发
    pre_save                    # django的modal对象保存save()前，自动触发
    post_save                   # django的modal对象保存save()后，自动触发
    pre_delete                  # django的modal对象删除delete()前，自动触发
    post_delete                 # django的modal对象删除delete()后，自动触发
    m2m_changed  # django的modal中使用m2m字段操作第三张表（add,remove,clear）前后，自动触发
    class_prepared # 程序启动时，检测已注册的app中modal类，对于每一个类，自动触发
Management signals
    pre_migrate                 # 执行migrate命令前，自动触发
    post_migrate                # 执行migrate命令后，自动触发
Request/response signals
    request_started             # 请求到来前，自动触发
    request_finished            # 请求结束后，自动触发
    got_request_exception       # 请求异常后，自动触发
Test signals
    setting_changed             # 使用test测试修改配置文件时，自动触发
    template_rendered           # 使用test测试渲染模板时，自动触发
Database Wrappers
    connection_created          # 创建数据库连接时，自动触发
"""


@receiver(post_save, sender=MessageCenter)
def create_message_center(sender, instance, created, **kwargs):
    # created  创建
    logger.info(f"MessageCenter 信号触发 - 实例ID: {instance.id}, 是否创建: {created}")
    if created:
        try:
            new_message_center = MessageCenter.objects.get(id=instance.id)
            send_user_info = get_auth_user_info(new_message_center.send_user_info.get("nid", None))
            logger.debug("MessageCenter 目标用户 send_user_info=%s", send_user_info)
            if not send_user_info:
                logger.warning("MessageCenter 发送失败：未找到目标用户 message_id=%s", instance.id)
                return "发送失败未找到用户数为0"
            message_center_target_user_list = []
            for uid in send_user_info:
                message_center_target_user_list.append(
                    MessageCenterTargetUser(
                        users_id=uid,
                        messagecenter=new_message_center,
                        is_send=False,
                        creator=new_message_center.creator,
                        modifier=new_message_center.modifier,
                    )
                )
            if message_center_target_user_list:
                MessageCenterTargetUser.objects.bulk_create(message_center_target_user_list)
                logger.info("成功创建 %d 个消息中心目标用户记录 message_id=%s", len(message_center_target_user_list), instance.id)
        except Exception as e:
            logger.exception("创建消息中心目标用户时发生异常 message_id=%s: %s", instance.id, e)


headers = {
    "Content-Type": "application/json; charset=utf-8",
}


@receiver([pre_save], sender=Users)
def prevent_anonymous_user(sender, instance, **kwargs):
    """阻止创建用户名为 AnonymousUser 的用户 - 静默处理，不抛出异常"""
    if instance.username == "AnonymousUser":
        logger.warning("检测到尝试创建 AnonymousUser 用户，已静默阻止保存")
        # 将 username 设置为一个临时标记值，在 post_save 中会删除该记录
        # 这样不会抛出异常，而是静默阻止
        instance.username = "_ANONYMOUS_USER_BLOCKED_"
        return


@receiver([post_save], sender=Users)
def create_update_delete_users(sender, instance, created, **kwargs):
    logger.info(f"Users 信号触发 - 用户ID: {instance.id}, 用户名: {instance.username}, 是否创建: {created}")

    # 如果用户名为标记值（在 pre_save 中被修改），或者用户名为 "AnonymousUser"，删除该用户
    if instance.username == "_ANONYMOUS_USER_BLOCKED_" or instance.username == "AnonymousUser":
        logger.warning(f"检测到不应该创建的用户（ID: {instance.id}, 用户名: {instance.username}），正在删除")
        try:
            # 使用 _raw_delete 或直接删除，但需要先保存 ID
            user_id = instance.id
            # 使用 QuerySet 的 delete()，这会触发信号，但在 delete_users 中会跳过处理
            Users.objects.filter(id=user_id).delete()
            logger.info(f"已删除不应该创建的用户（ID: {user_id}）")
        except Exception as e:
            logger.error(f"删除不应该创建的用户失败: {e}")
        return

    try:
        apps_result = Apps.objects.filter(create_or_update_callback_url="").all()
        payload = json.dumps(
            {"node_type": 4, "action_type": 0 if created else 1, "info": dict(UserSerializer(instance).data)},
            ensure_ascii=False,
        )
        logger.info(f"准备向 {len(apps_result)} 个应用发送用户变更回调")

        for item in apps_result:
            try:
                logger.debug(f"向应用 {item.title} 发送用户变更回调")
                httpx.post(item.create_or_update_callback_url, headers=headers, data=payload)
                logger.info(f"成功向应用 {item.title} 发送用户变更回调")
            except Exception as e:
                logger.warning("向应用 %s 发送用户变更回调失败: %s", item.title, e)
    except Exception as e:
        logger.exception("处理用户变更信号时发生异常: %s", e)


@receiver([post_delete], sender=Users)
def delete_users(sender, instance, **kwargs):
    logger.info(f"Users 删除信号触发 - 用户ID: {instance.id}, 用户名: {instance.username}")

    # 如果用户名为 "AnonymousUser" 或标记值，跳过回调处理
    if instance.username == "AnonymousUser" or instance.username == "_ANONYMOUS_USER_BLOCKED_":
        logger.debug("跳过不应该创建用户的删除回调处理")
        return

    try:
        apps_result = Apps.objects.filter(delete_callback_url="").all()
        payload = json.dumps(
            {"node_type": 4, "action_type": 2, "info": dict(UserSerializer(instance).data)}, ensure_ascii=False
        )
        logger.info(f"准备向 {len(apps_result)} 个应用发送用户删除回调")

        for item in apps_result:
            try:
                logger.debug(f"向应用 {item.title} 发送用户删除回调")
                httpx.post(item.delete_callback_url, headers=headers, data=payload)
                logger.info(f"成功向应用 {item.title} 发送用户删除回调")
            except Exception as e:
                logger.warning("向应用 %s 发送用户删除回调失败: %s", item.title, e)
    except Exception as e:
        logger.exception("处理用户删除信号时发生异常: %s", e)


@receiver([post_save], sender=Tags)
def create_update_tags(sender, instance, created, **kwargs):
    logger.info(f"Tags 信号触发 - 标签ID: {instance.id}, 标签名: {instance.name}, 是否创建: {created}")
    try:
        apps_result = Apps.objects.filter(~Q(create_or_update_callback_url="")).all()
        payload = json.dumps(
            {"node_type": 3, "action_type": 0 if created else 1, "info": dict(TagsSerializer(instance).data)},
            ensure_ascii=False,
        )
        logger.info(f"准备向 {len(apps_result)} 个应用发送标签变更回调")

        for item in apps_result:
            try:
                logger.debug(f"向应用 {item.title} 发送标签变更回调")
                httpx.post(item.create_or_update_callback_url, headers=headers, data=payload)
                logger.info(f"成功向应用 {item.title} 发送标签变更回调")
            except Exception as e:
                logger.warning("向应用 %s 发送标签变更回调失败: %s", item.title, e)
    except Exception as e:
        logger.exception("处理标签变更信号时发生异常: %s", e)


@receiver([post_delete], sender=Tags)
def delete_tags(sender, instance, **kwargs):
    logger.info(f"Tags 删除信号触发 - 标签ID: {instance.id}, 标签名: {instance.name}")
    try:
        apps_result = Apps.objects.filter(delete_callback_url="").all()
        payload = json.dumps(
            {"node_type": 3, "action_type": 2, "info": dict(TagsSerializer(instance).data)}, ensure_ascii=False
        )
        logger.info(f"准备向 {len(apps_result)} 个应用发送标签删除回调")

        for item in apps_result:
            try:
                logger.debug(f"向应用 {item.title} 发送标签删除回调")
                httpx.post(item.delete_callback_url, headers=headers, data=payload)
                logger.info(f"成功向应用 {item.title} 发送标签删除回调")
            except Exception as e:
                logger.warning("向应用 %s 发送标签删除回调失败: %s", item.title, e)
    except Exception as e:
        logger.exception("处理标签删除信号时发生异常: %s", e)
