# houtai/utils.py
import logging
import json
from django.core.exceptions import ObjectDoesNotExist
from rest_framework.response import Response
from .models import AbnormalUserLog, UserRole, RolePermission, Permission, DashouRiTongji, ShangjiaRiTongji, \
    GuanshiXufeiRiTongji, GuanshiRiTongji, ZuzhangRiTongji, TixianRiTongji

from django.db import transaction
from django.db.models import F
from datetime import date
from decimal import Decimal

logger = logging.getLogger(__name__)


def _get_real_ip(request):
    """获取真实IP（考虑代理）"""
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0].strip()
        return ip, x_forwarded_for
    else:
        ip = request.META.get('REMOTE_ADDR')
        return ip, ''


def _record_abnormal(account_id, request, attempt_type, detail=''):
    """记录异常操作（仅用于越权等攻击行为）"""
    try:
        real_ip, xff = _get_real_ip(request)
        headers = {k: v for k, v in request.META.items() if k.startswith('HTTP_')}
        headers_json = json.dumps(headers, ensure_ascii=False)[:2000]

        request_params = json.dumps(request.query_params.dict(), ensure_ascii=False) if request.query_params else ''
        request_body = request.body.decode('utf-8', errors='ignore')[:5000]

        AbnormalUserLog.objects.create(
            account_id=account_id,
            ip_address=real_ip,
            real_ip=real_ip,
            x_forwarded_for=xff,
            user_agent=request.META.get('HTTP_USER_AGENT', ''),
            request_method=request.method,
            request_path=request.path,
            request_params=request_params,
            request_body=request_body,
            request_headers=headers_json,
            attempt_type=attempt_type,
            detail=detail,
        )
        logger.warning(f"记录异常用户: {account_id} IP:{real_ip} 类型:{attempt_type}")
    except Exception as e:
        logger.error(f"记录异常日志失败: {e}")


def verify_kefu_permission(request, username_from_frontend=None):
    """
    验证后台管理员身份，并返回该用户的所有权限列表（基于新RBAC表）
    只有前端传递的username与当前登录用户不匹配时，才记录异常并警告前端。

    参数:
        request: DRF request 对象
        username_from_frontend: 前端传递的账号（用于防越权）

    返回:
        (kefu_obj, permissions_list)   # 验证通过
        (None, Response)                # 验证失败，直接返回Response
    """
    current_user = request.user

    # ---------- 1. 必须是客服 ----------
    if current_user.user_type != 'kefu':
        return None, Response({'code': 403, 'msg': '身份错误，非客服账号'}, status=403)

    # ---------- 2. 客服扩展表存在且状态正常 ----------
    try:
        kefu = current_user.kefu_profile
        if kefu.zhuangtai != 1:
            return None, Response({'code': 403, 'msg': '客服账号已被禁用'}, status=403)
    except ObjectDoesNotExist:
        return None, Response({'code': 403, 'msg': '客服账号不存在'}, status=403)

    # ---------- 3. 越权检测（只记录前端篡改username的情况） ----------
    if username_from_frontend and current_user.phone != username_from_frontend:
        detail = f'前端username: {username_from_frontend}，实际登录账号: {current_user.phone}'
        _record_abnormal(current_user.phone, request, '越权尝试篡改username', detail=detail)
        return None, Response({
            'code': 403,
            'msg': '身份错误，无权操作其他账号，相关操作已记录'
        }, status=403)

    # ---------- 4. 获取用户的所有权限（通过角色） ----------
    # 步骤1：获取用户的所有角色ID
    role_ids = UserRole.objects.filter(account_id=current_user.phone).values_list('role_id', flat=True)
    # 步骤2：通过角色ID获取权限编码
    permissions = list(Permission.objects.filter(
        rolepermission__role_id__in=role_ids
    ).values_list('perm_code', flat=True).distinct())

    if not permissions:
        logger.warning(f"用户 {current_user.phone} 没有任何权限，请检查角色分配")

    return kefu, permissions






def update_dashou_daily_by_action(yonghuid, amount, action):
    """
    根据行为类型更新打手每日统计（接单、成交、退款）

    参数:
        yonghuid: 打手用户ID
        amount: 本单涉及的金额（Decimal）
        action: 1 = 接单, 2 = 成交（结算）, 3 = 退款
    """
    amount = Decimal(str(amount)) if amount else Decimal('0.00')
    if amount <= 0:
        return  # 金额非正不统计

    today = date.today()

    with transaction.atomic():
        stat, created = DashouRiTongji.objects.select_for_update().get_or_create(
            yonghuid=yonghuid,
            riqi=today,
            defaults={
                'yonghuid': yonghuid,
                'riqi': today,
                'jiedan_zongliang': 0,
                'jiedan_zonge': Decimal('0.00'),
                'chengjiao_zongliang': 0,
                'chengjiao_zonge': Decimal('0.00'),
                'tuikuan_liang': 0,
                'tuikuan_jine': Decimal('0.00'),
            }
        )

        update_fields = {}
        if action == 1:  # 接单
            update_fields['jiedan_zongliang'] = F('jiedan_zongliang') + 1
            update_fields['jiedan_zonge'] = F('jiedan_zonge') + amount
        elif action == 2:  # 成交
            update_fields['chengjiao_zongliang'] = F('chengjiao_zongliang') + 1
            update_fields['chengjiao_zonge'] = F('chengjiao_zonge') + amount
        elif action == 3:  # 退款
            update_fields['tuikuan_liang'] = F('tuikuan_liang') + 1
            update_fields['tuikuan_jine'] = F('tuikuan_jine') + amount
        else:
            return  # 无效行为

        if update_fields:
            DashouRiTongji.objects.filter(id=stat.id).update(**update_fields)

def update_shangjia_daily(yonghuid, amount, action):
    """
    根据操作行为更新商家每日统计（派发、结算、退款）

    参数:
        yonghuid: 商家用户ID
        amount: 当前订单涉及的金额（Decimal）
        action: 操作类型，1 = 派发，2 = 结算（成交），3 = 退款

    说明:
        - 金额必须大于0，否则不执行任何操作
        - 使用 select_for_update + F() 表达式保证原子性和并发安全
        - 每天每个商家只会有一条统计记录，不存在则自动创建
    """
    amount = Decimal(str(amount)) if amount else Decimal('0.00')
    if amount <= 0:
        return  # 金额非正，不统计

    today = date.today()

    with transaction.atomic():
        # 获取或创建当天统计记录，同时加锁防止并发
        stat, created = ShangjiaRiTongji.objects.select_for_update().get_or_create(
            yonghuid=yonghuid,
            riqi=today,
            defaults={
                'yonghuid': yonghuid,
                'riqi': today,
                'paifa_dingdan_shu': 0,
                'paifa_jine': Decimal('0.00'),
                'jiesuan_dingdan_shu': 0,
                'jiesuan_jine': Decimal('0.00'),
                'tuikuan_dingdan_shu': 0,
                'tuikuan_jine': Decimal('0.00'),
            }
        )

        # 构建本次更新的字段，使用 F 表达式进行原子累加
        update_fields = {}
        if action == 1:  # 派发
            update_fields['paifa_dingdan_shu'] = F('paifa_dingdan_shu') + 1
            update_fields['paifa_jine'] = F('paifa_jine') + amount
        elif action == 2:  # 结算（成交）
            update_fields['jiesuan_dingdan_shu'] = F('jiesuan_dingdan_shu') + 1
            update_fields['jiesuan_jine'] = F('jiesuan_jine') + amount
        elif action == 3:  # 退款
            update_fields['tuikuan_dingdan_shu'] = F('tuikuan_dingdan_shu') + 1
            update_fields['tuikuan_jine'] = F('tuikuan_jine') + amount
        else:
            # 无效的行为类型，直接返回
            return

        # 执行原子更新
        ShangjiaRiTongji.objects.filter(id=stat.id).update(**update_fields)

def update_guanshi_daily_by_action(yonghuid, action, amount=Decimal('0.00')):
    """
    根据操作行为更新管事每日统计（邀请打手、充值会员、订单/押金分红）
    action: 1 = 邀请打手, 2 = 充值会员, 3 = 商家订单分红, 4 = 押金分红
    """
    from django.db import transaction
    from django.db.models import F
    from datetime import date

    today = date.today()

    with transaction.atomic():
        stat, created = GuanshiRiTongji.objects.select_for_update().get_or_create(
            yonghuid=yonghuid,
            riqi=today,
            defaults={
                'yonghuid': yonghuid,
                'riqi': today,
                'yaoqing_dashou_shu': 0,
                'chongzhi_dashou_shu': 0,
                'shouru_zonge': Decimal('0.00'),
            }
        )

        if action == 1:
            # 邀请打手：无论新创建还是已存在，直接 +1
            if created:
                stat.yaoqing_dashou_shu = 1
                stat.save()
            else:
                GuanshiRiTongji.objects.filter(id=stat.id).update(
                    yaoqing_dashou_shu=F('yaoqing_dashou_shu') + 1
                )

        elif action == 2:
            amount = Decimal(str(amount)) if amount else Decimal('0.00')
            if amount <= 0:
                return
            if created:
                stat.chongzhi_dashou_shu = 1
                stat.shouru_zonge = amount
                stat.save()
            else:
                GuanshiRiTongji.objects.filter(id=stat.id).update(
                    chongzhi_dashou_shu=F('chongzhi_dashou_shu') + 1,
                    shouru_zonge=F('shouru_zonge') + amount
                )

        elif action in (3, 4):
            amount = Decimal(str(amount)) if amount else Decimal('0.00')
            if amount <= 0:
                return
            if created:
                stat.shouru_zonge = amount
                stat.save()
            else:
                GuanshiRiTongji.objects.filter(id=stat.id).update(
                    shouru_zonge=F('shouru_zonge') + amount
                )

'''def update_guanshi_daily_by_action(yonghuid, action, amount=Decimal('0.00')):
    """
    根据操作行为更新管事每日统计（邀请打手、充值会员）

    参数:
        yonghuid: 管事用户ID
        action: 操作类型
                1 = 邀请打手（次数自动+1，无需传其他参数）
                2 = 充值会员（需要传 amount 参数）
        amount: 充值金额（Decimal），仅在 action=2 时有效

    说明:
        - 每次调用只代表一次操作，不会批量处理。
        - 使用 select_for_update + F() 保证原子性和并发安全。
    """
    today = date.today()

    # 邀请打手：次数+1，金额不变
    if action == 1:
        count_field = 'yaoqing_dashou_shu'
        amount = Decimal('0.00')

    # 充值会员：次数+1，金额累加
    elif action == 2:
        amount = Decimal(str(amount)) if amount else Decimal('0.00')
        if amount <= 0:
            return
        count_field = 'chongzhi_dashou_shu'

    else:
        return  # 无效行为，直接返回

    with transaction.atomic():
        stat, created = GuanshiRiTongji.objects.select_for_update().get_or_create(
            yonghuid=yonghuid,
            riqi=today,
            defaults={
                'yonghuid': yonghuid,
                'riqi': today,
                'yaoqing_dashou_shu': 0,
                'chongzhi_dashou_shu': 0,
                'shouru_zonge': Decimal('0.00'),
            }
        )

        if created:
            # 新记录直接赋初值
            if action == 1:
                stat.yaoqing_dashou_shu = 1
        else:
            # 已存在记录，使用 F 表达式原子累加次数
            update_fields = {count_field: F(count_field) + 1}

            if action == 2:
                update_fields['shouru_zonge'] = F('shouru_zonge') + amount

            GuanshiRiTongji.objects.filter(id=stat.id).update(**update_fields)'''

def update_guanshi_xufei_daily(yonghuid, xufei_jine=Decimal('0.00')):
    """
    管事续费统计（单独表）
    用法: update_guanshi_xufei_daily('300001', Decimal('30'))
    """
    today = date.today()
    with transaction.atomic():
        stat, created = GuanshiXufeiRiTongji.objects.select_for_update().get_or_create(
            yonghuid=yonghuid,
            riqi=today,
            defaults={
                'yonghuid': yonghuid,
                'riqi': today,
                'xufei_zongshu': 1,
                'xufei_shouyi': xufei_jine,
            }
        )
        if not created:
            GuanshiXufeiRiTongji.objects.filter(id=stat.id).update(
                xufei_zongshu=F('xufei_zongshu') + 1,
                xufei_shouyi=F('xufei_shouyi') + xufei_jine
            )


def update_zuzhang_daily_by_action(yonghuid, action, amount=Decimal('0.00')):
    """
    根据操作行为更新组长每日统计（邀请管事、分佣收入）

    参数:
        yonghuid: 组长用户ID
        action: 操作类型
                1 = 邀请管事（次数+1，无金额）
                2 = 分佣收入（累加金额）
        amount: 分佣金额（Decimal），仅在 action=2 时有效
    """
    today = date.today()

    with transaction.atomic():
        stat, created = ZuzhangRiTongji.objects.select_for_update().get_or_create(
            yonghuid=yonghuid,
            riqi=today,
            defaults={
                'yonghuid': yonghuid,
                'riqi': today,
                'yaoqing_guanshi_shu': 0,
                'shouru_zonge': Decimal('0.00'),
                'fenyong_jine': Decimal('0.00'),
            }
        )

        if created:
            # 新记录直接设置初始值
            if action == 1:
                stat.yaoqing_guanshi_shu = 1
            elif action == 2:
                amount = Decimal(str(amount)) if amount else Decimal('0.00')
                stat.shouru_zonge = amount
                stat.fenyong_jine = amount
            stat.save()
        else:
            # 已存在记录，使用 F 表达式原子累加
            if action == 1:
                ZuzhangRiTongji.objects.filter(id=stat.id).update(
                    yaoqing_guanshi_shu=F('yaoqing_guanshi_shu') + 1
                )
            elif action == 2:
                amount = Decimal(str(amount)) if amount else Decimal('0.00')
                if amount > 0:
                    ZuzhangRiTongji.objects.filter(id=stat.id).update(
                        shouru_zonge=F('shouru_zonge') + amount,
                        fenyong_jine=F('fenyong_jine') + amount
                    )


def update_tixian_daily_stat(leixing, amount):
    """
    更新每日提现统计（平台维度）
    leixing: 1=打手, 2=管事, 3=组长
    amount: 本次提现金额（申请金额，含手续费）
    """
    today = date.today()
    with transaction.atomic():
        stat, created = TixianRiTongji.objects.select_for_update().get_or_create(
            riqi=today,
            leixing=leixing,
            defaults={'total_amount': amount}
        )
        if not created:
            TixianRiTongji.objects.filter(id=stat.id).update(
                total_amount=F('total_amount') + amount
            )

def decrease_tixian_daily_stat(leixing, amount):
    """
    减少每日提现统计（平台维度），用于提现失败或取消时回滚
    :param leixing: 1=打手,2=管事,3=组长
    :param amount: 要减少的金额（实际到账金额）
    """
    today = date.today()
    with transaction.atomic():
        # 使用 select_for_update 防止并发回滚时数据错乱
        stat = TixianRiTongji.objects.select_for_update().get(riqi=today, leixing=leixing)
        stat.total_amount -= amount
        stat.save(update_fields=['total_amount'])


