"""充值订单 czjilu 履约（押金/积分），与 member_recharge 同一套幂等原则。"""
from __future__ import annotations

import logging
from decimal import Decimal

from django.db import transaction

from backend.utils import update_guanshi_daily_by_action
from jituan.constants import CLUB_ID_DEFAULT
from jituan.services.club_penalty import resolve_gsfenhong_club_id
from orders.models import CommissionRate
from products.models import Czjilu, Gsfenhong
from users.models import UserDashou, UserGuanshi

logger = logging.getLogger(__name__)

INTEGRAL_PRICE = Decimal('5.00')
MAX_INTEGRAL = 10
INTEGRAL_INCREMENT = 5


class CzjiluFulfillError(Exception):
    def __init__(self, message, code='error'):
        super().__init__(message)
        self.code = code


@transaction.atomic
def fulfill_yajin_recharge(dingdan_id, paid_amount_yuan=None):
    """押金充值幂等履约：仅 zhuangtai==9 时入账。"""
    order = Czjilu.query.filter(dingdan_id=dingdan_id).select_for_update().first()
    if not order:
        raise CzjiluFulfillError('订单不存在', 'not_found')
    if order.leixing != 2:
        raise CzjiluFulfillError('订单类型不是押金', 'type_error')
    if order.zhuangtai != 9:
        try:
            from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
            repair_wechat_income_if_missing(
                Decimal(str(order.jine)),
                getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
                biz_ref=f'cz:{dingdan_id}',
            )
        except Exception as exc:
            logger.error('押金补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
        return {'already_done': True, 'dingdan_id': dingdan_id, 'zhuangtai': order.zhuangtai}

    amount = Decimal(str(order.jine))
    if paid_amount_yuan is not None:
        paid = Decimal(str(paid_amount_yuan))
        if abs(paid - amount) > Decimal('0.01'):
            raise CzjiluFulfillError(f'支付金额{paid}与订单{amount}不一致', 'amount_mismatch')

    try:
        dashou = UserDashou.objects.select_for_update().get(user__UserUID=order.yonghuid)
    except UserDashou.DoesNotExist:
        raise CzjiluFulfillError('打手不存在，无法充值押金', 'dashou_not_found')

    dashou.yajin += amount
    dashou.save(update_fields=['yajin'])

    order.zhuangtai = 3
    order.save(update_fields=['zhuangtai'])

    club_id = getattr(order, 'club_id', None) or CLUB_ID_DEFAULT
    try:
        from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
        repair_wechat_income_if_missing(amount, club_id, biz_ref=f'cz:{dingdan_id}')
    except Exception as exc:
        logger.error('押金收支统计失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)

    try:
        _apply_yajin_fenhong(order, dashou, amount)
    except Exception as exc:
        logger.error('押金分红失败但押金已到账 dingdan=%s: %s', dingdan_id, exc, exc_info=True)

    logger.info('押金履约完成 dingdan=%s amount=%s', dingdan_id, amount)
    return {'already_done': False, 'dingdan_id': dingdan_id, 'zhuangtai': 3, 'yajin': dashou.yajin}


def _apply_yajin_fenhong(order, dashou, amount):
    if Gsfenhong.query.filter(dingdan_id=order.dingdan_id).exists():
        return
    guanshi_id = dashou.yaoqingren
    if not guanshi_id:
        return
    lilu_obj = CommissionRate.query.filter(Platform='12').first()
    rate = lilu_obj.Rate if lilu_obj and lilu_obj.Rate is not None else Decimal('0')
    if rate <= 0:
        return
    fenhong_jine = (amount * rate).quantize(Decimal('0.01'))
    if fenhong_jine <= 0:
        return
    guanshi = UserGuanshi.objects.select_for_update().get(user__UserUID=guanshi_id)
    guanshi.yue += fenhong_jine
    guanshi.chongzhifenrun += fenhong_jine
    guanshi.save(update_fields=['yue', 'chongzhifenrun'])
    user_main = dashou.user
    Gsfenhong.query.create(
        dingdan_id=order.dingdan_id,
        guanshi=guanshi_id,
        dashouid=order.yonghuid,
        shuoming='押金分红',
        fenhong=fenhong_jine,
        avatar=user_main.Avatar,
        nicheng=dashou.nicheng or '未知打手',
        fenhong_leixing=2,
        club_id=resolve_gsfenhong_club_id(
            dingdan_id=order.dingdan_id, dashouid=order.yonghuid, czjilu=order,
        ),
    )
    try:
        update_guanshi_daily_by_action(yonghuid=guanshi_id, action=4, amount=fenhong_jine)
    except Exception as exc:
        logger.error('押金分红日统计失败: %s', exc)


@transaction.atomic
def fulfill_jifen_recharge(dingdan_id, paid_amount_yuan=None):
    """积分补充幂等履约：仅 zhuangtai==9 时入账。"""
    order = Czjilu.query.filter(dingdan_id=dingdan_id).select_for_update().first()
    if not order:
        raise CzjiluFulfillError('订单不存在', 'not_found')
    if order.leixing != 3:
        raise CzjiluFulfillError('订单类型不是积分', 'type_error')
    if order.zhuangtai != 9:
        try:
            from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
            repair_wechat_income_if_missing(
                Decimal(str(order.jine)),
                getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
                biz_ref=f'cz:{dingdan_id}',
            )
        except Exception as exc:
            logger.error('积分补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
        return {'already_done': True, 'dingdan_id': dingdan_id, 'zhuangtai': order.zhuangtai}

    amount = Decimal(str(order.jine))
    if paid_amount_yuan is not None:
        paid = Decimal(str(paid_amount_yuan))
        if abs(paid - amount) > Decimal('0.01'):
            raise CzjiluFulfillError(f'支付金额{paid}与订单{amount}不一致', 'amount_mismatch')
        if abs(paid - INTEGRAL_PRICE) > Decimal('0.01'):
            raise CzjiluFulfillError('积分订单金额必须为5元', 'amount_mismatch')

    try:
        dashou = UserDashou.objects.select_for_update().get(user__UserUID=order.yonghuid)
    except UserDashou.DoesNotExist:
        raise CzjiluFulfillError('打手不存在，无法补充积分', 'dashou_not_found')

    if dashou.jifen < MAX_INTEGRAL:
        dashou.jifen = min(dashou.jifen + INTEGRAL_INCREMENT, MAX_INTEGRAL)
        dashou.save(update_fields=['jifen'])

    order.zhuangtai = 3
    order.save(update_fields=['zhuangtai'])

    club_id = getattr(order, 'club_id', None) or CLUB_ID_DEFAULT
    try:
        from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
        repair_wechat_income_if_missing(amount, club_id, biz_ref=f'cz:{dingdan_id}')
    except Exception as exc:
        logger.error('积分收支统计失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)

    logger.info('积分履约完成 dingdan=%s jifen=%s', dingdan_id, dashou.jifen)
    return {'already_done': False, 'dingdan_id': dingdan_id, 'zhuangtai': 3, 'jifen': dashou.jifen}


def confirm_czjilu_paid(dingdan_id, yonghuid, expected_leixing):
    """轮询确认：查微信 SUCCESS 后幂等履约。"""
    from jituan.services.member_recharge import query_wechat_v2_trade_state

    try:
        order = Czjilu.query.get(dingdan_id=dingdan_id, yonghuid=yonghuid)
    except Czjilu.DoesNotExist:
        raise CzjiluFulfillError('订单不存在或不属于当前用户', 'not_found')

    if order.leixing != expected_leixing:
        raise CzjiluFulfillError('订单类型不匹配', 'type_error')

    if order.zhuangtai == 3:
        try:
            from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
            repair_wechat_income_if_missing(
                Decimal(str(order.jine)),
                getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
                biz_ref=f'cz:{dingdan_id}',
            )
        except Exception as exc:
            logger.error('充值单补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
        return {'already_done': True, 'zhuangtai': 3}

    if order.zhuangtai != 9:
        raise CzjiluFulfillError(f'订单状态异常: {order.zhuangtai}', 'status_error')

    trade_state, _ = query_wechat_v2_trade_state(dingdan_id, getattr(order, 'club_id', None))
    if trade_state != 'SUCCESS':
        raise CzjiluFulfillError('微信侧尚未支付成功，请稍后再试', 'not_paid')

    paid = Decimal(str(order.jine))
    if expected_leixing == 2:
        return fulfill_yajin_recharge(dingdan_id, paid_amount_yuan=paid)
    if expected_leixing == 3:
        return fulfill_jifen_recharge(dingdan_id, paid_amount_yuan=paid)
    raise CzjiluFulfillError('不支持的充值类型', 'type_error')
