# yonghu/fadan_fenhong_utils.py
# 罚款缴纳分红处理公共方法（支持更新罚单中的申请人分红金额）

import logging
from decimal import Decimal
from django.db import transaction

from orders.models import Penalty, PenaltyBonus, PenaltyBonusRate
from users.models import UserShangjia

logger = logging.getLogger(__name__)


# 身份映射字典
# 罚单 ApplicantIdentity（shenqingren_shenfen）→ fadan_fenhong 表 Identity + fadan_fenhong_lilv 表 shenfen
# 罚单侧：1=客服 2=售后 3=管理员 4=店铺 5=商家
# fadan_fenhong 表：1=商家 2=客服 3=平台管理者 4=店铺 5=售后
IDENTITY_MAP = {
    1: {'fenhong': 2, 'lilv': 1},   # 客服 → 分红记录身份2，利率表 shenfen=1
    2: {'fenhong': 5, 'lilv': 2},   # 售后 → 分红记录身份5，利率表 shenfen=2
    3: {'fenhong': 3, 'lilv': 3},   # 管理员
    4: {'fenhong': 4, 'lilv': 4},   # 店铺
    5: {'fenhong': 1, 'lilv': 5},   # 商家 → 分红记录身份1，利率表 shenfen=5；钱进 user_shangjia.yue
}

MERCHANT_LILV_SHENFEN = 5
MERCHANT_FENHONG_SHENFEN = 1


def _normalize_club_id(club_id):
    cid = (club_id or '').strip()
    return cid or 'xq'


def _read_global_fenhong_rate(lilv_shenfen):
    try:
        global_rate = PenaltyBonusRate.objects.get(Identity=lilv_shenfen)
        rate = global_rate.Rate
        if rate is not None and Decimal(str(rate)) > 0:
            return rate
    except PenaltyBonusRate.DoesNotExist:
        pass
    return None


def _read_club_fenhong_rate(club_id, lilv_shenfen):
    """俱乐部级罚款分红费率（club_fadan_fenhong_lilv）。"""
    from jituan.models import ClubFadanFenhongLilv

    club_id = _normalize_club_id(club_id)
    row = ClubFadanFenhongLilv.query.filter(
        club_id=club_id, shenfen=int(lilv_shenfen),
    ).first()
    if row is not None and row.lilv is not None and Decimal(str(row.lilv)) > 0:
        return row.lilv
    return None


def _get_fenhong_rate(fenhongzhe_id, fenhong_shenfen, lilv_shenfen, club_id='xq'):
    """
    获取分红利率：个人单独利率 > 0 优先；否则俱乐部配置；再回退全局 fadan_fenhong_lilv。
    """
    club_id = _normalize_club_id(club_id)
    try:
        individual = PenaltyBonus.objects.get(
            BeneficiaryID=fenhongzhe_id,
            Identity=fenhong_shenfen,
            ClubID=club_id,
            IsIndividualRate=True,
        )
        ind_rate = individual.IndividualRate
        if ind_rate is not None and Decimal(str(ind_rate)) > 0:
            return ind_rate
    except PenaltyBonus.DoesNotExist:
        pass

    club_rate = _read_club_fenhong_rate(club_id, lilv_shenfen)
    if club_rate is not None:
        return club_rate

    return _read_global_fenhong_rate(lilv_shenfen)


def _calc_bonus_amount(fine_amount, rate):
    if fine_amount is None or rate is None:
        return Decimal('0.00')
    fine = Decimal(str(fine_amount))
    r = Decimal(str(rate))
    if fine <= 0 or r <= 0:
        return Decimal('0.00')
    return (fine * r).quantize(Decimal('0.01'))


def lock_penalty_bonus(fadan):
    """
    申请/改价/再次申请时锁定应得分红利率与金额，写入罚单供前端展示；
    缴纳时按此锁定值入账，不再现场重算。
    """
    if getattr(fadan, 'BonusCredited', False):
        return fadan

    zero_rate = Decimal('0.0000')
    zero_amount = Decimal('0.00')
    applicant_id = fadan.ApplicantID
    src_shenfen = fadan.ApplicantIdentity

    if not applicant_id or src_shenfen not in IDENTITY_MAP:
        fadan.ApplicantBonusRate = zero_rate
        fadan.ApplicantBonusAmount = zero_amount
        fadan.save(update_fields=['ApplicantBonusRate', 'ApplicantBonusAmount'])
        return fadan

    mapped = IDENTITY_MAP[src_shenfen]
    club_id = _normalize_club_id(fadan.ClubID)
    rate = _get_fenhong_rate(
        applicant_id, mapped['fenhong'], mapped['lilv'], club_id=club_id,
    )
    if rate is None:
        fadan.ApplicantBonusRate = zero_rate
        fadan.ApplicantBonusAmount = zero_amount
    else:
        fadan.ApplicantBonusRate = Decimal(str(rate))
        fadan.ApplicantBonusAmount = _calc_bonus_amount(fadan.FineAmount, rate)

    fadan.save(update_fields=['ApplicantBonusRate', 'ApplicantBonusAmount'])
    return fadan


def get_merchant_fenhong_lilv(yonghuid, club_id='xq'):
    """商家申请罚单页预览利率（尚无罚单时）。"""
    club_id = _normalize_club_id(club_id)
    rate = _get_fenhong_rate(
        yonghuid,
        MERCHANT_FENHONG_SHENFEN,
        MERCHANT_LILV_SHENFEN,
        club_id=club_id,
    )
    return float(rate) if rate is not None else 0.0


def process_fadan_fenhong(fadan_id):
    """
    罚款缴纳后的分红入账：优先使用申请时已锁定的利率/金额，不现场重算。
    """
    try:
        try:
            fadan = Penalty.objects.get(id=fadan_id, Status=2)
        except Penalty.DoesNotExist:
            logger.error(f"罚单 {fadan_id} 不存在或状态不是已缴纳")
            return False, "罚单不存在或状态异常"

        if fadan.BonusCredited:
            logger.info(f"罚单 {fadan_id} 分红已入账，跳过")
            return True, "已分红"

        shenqing_chufa = fadan.ApplicantID
        src_shenfen = fadan.ApplicantIdentity

        if not shenqing_chufa:
            logger.info(f"罚单 {fadan_id} 无申请处罚者，不进行分红")
            return True, "无申请处罚者，无需分红"

        if src_shenfen not in IDENTITY_MAP:
            logger.error(f"未知的申请处罚者身份: {src_shenfen}，罚单 {fadan_id}")
            return False, f"未知身份 {src_shenfen}"

        mapped = IDENTITY_MAP[src_shenfen]
        fenhong_shenfen = mapped['fenhong']
        club_id = _normalize_club_id(fadan.ClubID)

        locked_amount = Decimal(str(fadan.ApplicantBonusAmount or 0))
        locked_rate = fadan.ApplicantBonusRate

        # 申请时已锁定：缴纳只按锁定值入账，不因全局利率后续变更而重算
        if locked_amount > 0 or (
            locked_rate is not None and Decimal(str(locked_rate)) > 0
        ):
            fenhong_jine = locked_amount
            rate = locked_rate
        else:
            # 旧数据兼容：未锁定时按当前利率现场算一次并回写
            fakuan_jine = fadan.FineAmount
            if fakuan_jine <= 0:
                fadan.ApplicantBonusAmount = Decimal('0.00')
                fadan.save(update_fields=['ApplicantBonusAmount'])
                return True, "罚款金额为0，无分红"

            rate = _get_fenhong_rate(
                shenqing_chufa, fenhong_shenfen, mapped['lilv'], club_id=club_id,
            )
            if rate is None:
                logger.warning(f"罚单 {fadan_id} 未配置分红利率")
                fadan.ApplicantBonusAmount = Decimal('0.00')
                fadan.save(update_fields=['ApplicantBonusAmount'])
                return True, "未配置分红利率，无分红"

            fenhong_jine = _calc_bonus_amount(fakuan_jine, rate)
            fadan.ApplicantBonusRate = Decimal(str(rate))
            fadan.ApplicantBonusAmount = fenhong_jine
            fadan.save(update_fields=['ApplicantBonusRate', 'ApplicantBonusAmount'])

        if fenhong_jine <= 0:
            logger.info(f"罚单 {fadan_id} 锁定分红金额为0，无需入账")
            fadan.BonusCredited = True
            fadan.save(update_fields=['BonusCredited'])
            return True, "分红金额为0"

        if src_shenfen == 5:
            with transaction.atomic():
                fadan = Penalty.objects.select_for_update().get(id=fadan_id, Status=2)
                if fadan.BonusCredited:
                    return True, "已分红"

                if not UserShangjia.objects.filter(user__UserUID=shenqing_chufa).exists():
                    logger.error(f"商家 {shenqing_chufa} 扩展表不存在，无法分红入账")
                    return False, "商家资料不存在，无法分红"

                fenhong_record, _created = PenaltyBonus.objects.get_or_create(
                    BeneficiaryID=shenqing_chufa,
                    Identity=fenhong_shenfen,
                    ClubID=club_id,
                    defaults={
                        'TotalAmount': Decimal('0.00'),
                        'WithdrawableAmount': Decimal('0.00'),
                        'BonusCount': 0,
                        'IndividualRate': rate,
                        'IsIndividualRate': False,
                    },
                )
                fenhong_record.TotalAmount += fenhong_jine
                fenhong_record.BonusCount += 1
                fenhong_record.save()

                shangjia = UserShangjia.objects.select_for_update().get(user__UserUID=shenqing_chufa)
                shangjia.yue += fenhong_jine
                shangjia.save(update_fields=['yue'])
                logger.info(f"商家 {shenqing_chufa} 余额增加 {fenhong_jine} 元（锁定值）")

                fadan.BonusCredited = True
                fadan.save(update_fields=['BonusCredited'])

        else:
            with transaction.atomic():
                fadan = Penalty.objects.select_for_update().get(id=fadan_id, Status=2)
                if fadan.BonusCredited:
                    return True, "已分红"

                fenhong_record, _created = PenaltyBonus.objects.get_or_create(
                    BeneficiaryID=shenqing_chufa,
                    Identity=fenhong_shenfen,
                    ClubID=club_id,
                    defaults={
                        'TotalAmount': Decimal('0.00'),
                        'WithdrawableAmount': Decimal('0.00'),
                        'BonusCount': 0,
                        'IndividualRate': rate,
                        'IsIndividualRate': False,
                    },
                )
                fenhong_record.TotalAmount += fenhong_jine
                fenhong_record.WithdrawableAmount += fenhong_jine
                fenhong_record.BonusCount += 1
                fenhong_record.save()

                fadan.BonusCredited = True
                fadan.save(update_fields=['BonusCredited'])

        logger.info(
            f"罚单 {fadan_id} 分红入账成功: 申请者 {shenqing_chufa}, "
            f"锁定金额 {fenhong_jine} 元, 锁定利率 {rate}"
        )
        return True, "分红处理成功"

    except Exception as e:
        logger.error(f"罚单 {fadan_id} 分红处理异常: {str(e)}", exc_info=True)
        return False, f"分红处理异常: {str(e)}"
