"""提现设置与运行时：按俱乐部读 club_lilubiao / club_tixian_quota / club_withdraw_config。"""
from datetime import date
from decimal import Decimal

from django.db import transaction
from rest_framework.response import Response

from backend.models import WithdrawalDailyStats
from config.models import TixianQuotaDefault
from jituan.constants import CLUB_ID_DEFAULT, DATA_SCOPE_ALL
from jituan.models import ClubFadanFenhongLilv, ClubLilubiao, ClubTixianQuota, ClubWithdrawConfig
from jituan.services.club_config import get_commission_rate
from jituan.services.club_context import resolve_club_id_from_request, resolve_club_scope
from orders.models import PenaltyBonusRate

# 提现手续费率 → lilubiao config_type / CommissionRate Platform
LEIXING_RATE_KEY = {
    1: '5',   # 打手佣金
    2: '6',   # 管事分红
    3: '8',   # 组长分红
    4: '9',   # 考核官
    5: '11',  # 打手押金
    6: '10',  # 商家余额
}

# 罚款分红身份（与 fadan_fenhong_lilv.shenfen 一致）
PENALTY_BONUS_SHENFEN = {
    1: '客服',
    2: '售后',
    3: '管理员',
    4: '店铺',
    5: '商家',
}

# 提现身份 leixing → 平台日总限额配置 leixing（club_tixian_quota / TixianQuotaDefault UserType）
WITHDRAW_TOTAL_QUOTA_LEIXING = {1: 4, 2: 5, 3: 6, 4: 7, 5: 8, 6: 9}


def _normalize_club_id(club_id):
    return (club_id or '').strip() or CLUB_ID_DEFAULT


def _club_id(request):
    return resolve_club_id_from_request(request)


def _get_quota(club_id, leixing, default=20.0):
    club_id = _normalize_club_id(club_id)
    row = ClubTixianQuota.query.filter(club_id=club_id, leixing=leixing).first()
    if row is not None:
        return float(row.daily_limit)
    obj = TixianQuotaDefault.query.filter(UserType=leixing).first()
    return float(obj.default_quota) if obj else default


def get_quota_decimal(club_id, leixing, default=20.0):
    return Decimal(str(_get_quota(club_id, leixing, default)))


def _set_quota(club_id, leixing, quota):
    row, created = ClubTixianQuota.query.get_or_create(
        club_id=_normalize_club_id(club_id),
        leixing=leixing,
        defaults={'daily_limit': quota},
    )
    if not created:
        row.daily_limit = quota
        row.save(update_fields=['daily_limit', 'UpdateTime'])


def _set_lilv(club_id, config_type, rate):
    ct = int(config_type)
    row, created = ClubLilubiao.query.get_or_create(
        club_id=_normalize_club_id(club_id),
        config_type=ct,
        defaults={'lilv': rate, 'remark': ''},
    )
    if not created:
        row.lilv = rate
        row.save(update_fields=['lilv', 'UpdateTime'])


def _get_penalty_bonus_rate(club_id, shenfen):
    """有效罚款分红费率：俱乐部 > 全局表。"""
    club_id = _normalize_club_id(club_id)
    shenfen = int(shenfen)
    row = ClubFadanFenhongLilv.query.filter(club_id=club_id, shenfen=shenfen).first()
    if row is not None and row.lilv is not None:
        return float(row.lilv)
    try:
        g = PenaltyBonusRate.objects.get(Identity=shenfen)
        if g.Rate is not None:
            return float(g.Rate)
    except PenaltyBonusRate.DoesNotExist:
        pass
    return 0.0


def _set_penalty_bonus_rate(club_id, shenfen, rate):
    club_id = _normalize_club_id(club_id)
    shenfen = int(shenfen)
    row, created = ClubFadanFenhongLilv.query.get_or_create(
        club_id=club_id,
        shenfen=shenfen,
        defaults={'lilv': rate},
    )
    if not created:
        row.lilv = rate
        row.save(update_fields=['lilv', 'UpdateTime'])


def get_penalty_bonus_rates_map(club_id):
    return {s: _get_penalty_bonus_rate(club_id, s) for s in PENALTY_BONUS_SHENFEN}


def get_tixian_feilv(club_id, leixing):
    """读取提现手续费率（各俱乐部可不同）。"""
    rate_key = LEIXING_RATE_KEY.get(leixing)
    if not rate_key:
        raise ValueError('无效的提现类型')
    return get_commission_rate(_normalize_club_id(club_id), rate_key)


def get_withdraw_mode(club_id):
    club_id = _normalize_club_id(club_id)
    try:
        return ClubWithdrawConfig.query.get(club_id=club_id).mode
    except ClubWithdrawConfig.DoesNotExist:
        return 2


def get_personal_daily_quota(club_id, leixing, profile):
    """打手/管事/组长个人每日限额：用户额外限额优先，否则读俱乐部配置。"""
    if leixing == 1:
        if profile.kaioi_ewai_xiane and profile.ewai_xiane > 0:
            return Decimal(str(profile.ewai_xiane))
        return get_quota_decimal(club_id, 1)
    if leixing == 2:
        if profile.kaioi_ewai_xiane and profile.ewai_xiane > 0:
            return Decimal(str(profile.ewai_xiane))
        return get_quota_decimal(club_id, 2)
    if leixing == 3:
        default = get_quota_decimal(club_id, 3, default=0.0)
        if profile.kaioi_ewai_tixian and profile.ewai_tixian_xiane > 0:
            return Decimal(str(profile.ewai_tixian_xiane))
        return default
    raise ValueError('无效的个人限额身份')


def get_platform_daily_limit(club_id, leixing):
    quota_leixing = WITHDRAW_TOTAL_QUOTA_LEIXING.get(leixing)
    if not quota_leixing:
        return Decimal('0.00')
    return get_quota_decimal(club_id, quota_leixing, default=0.0)


def get_platform_daily_total(club_id, leixing, today=None):
    """平台今日已提现总额（到账金额口径，按俱乐部）。"""
    club_id = _normalize_club_id(club_id)
    today = today or date.today()
    rec = WithdrawalDailyStats.query.filter(
        club_id=club_id, Date=today, WithdrawalType=leixing,
    ).first()
    if rec:
        return Decimal(str(rec.total_amount))
    return Decimal('0.00')


def get_or_create_platform_daily_stat(club_id, leixing, today=None):
    """在 transaction.atomic 内获取并锁定平台日统计行。"""
    club_id = _normalize_club_id(club_id)
    today = today or date.today()
    stat, _ = WithdrawalDailyStats.objects.select_for_update().get_or_create(
        club_id=club_id,
        Date=today,
        WithdrawalType=leixing,
        defaults={'total_amount': Decimal('0.00')},
    )
    return stat


def build_tixian_asset_rates(club_id):
    club_id = _normalize_club_id(club_id)
    return {
        'dashou_rate': float(get_commission_rate(club_id, '5')),
        'dashou_yajin_rate': float(get_commission_rate(club_id, '11')),
        'shangjia_rate': float(get_commission_rate(club_id, '10')),
        'guanshi_rate': float(get_commission_rate(club_id, '6')),
        'zuzhang_rate': float(get_commission_rate(club_id, '8')),
        'kaoheguan_rate': float(get_commission_rate(club_id, '9')),
    }


def build_withdraw_settings_payload(request):
    club_id = _club_id(request)
    rate_map = {}
    for leixing, code in [(1, '5'), (2, '6'), (3, '8'), (4, '9'), (5, '11'), (6, '10')]:
        rate_map[leixing] = float(get_commission_rate(club_id, code))

    order_rate_map = {}
    for leixing, code in [(1, '1'), (3, '3'), (12, '12'), (13, '13')]:
        order_rate_map[leixing] = float(get_commission_rate(club_id, code))

    quota_map = {leixing: _get_quota(club_id, leixing) for leixing in [1, 2, 3]}

    total_limit_map = {}
    for withdraw_leixing, quota_leixing in [(1, 4), (2, 5), (3, 6), (4, 7), (5, 8), (6, 9)]:
        total_limit_map[withdraw_leixing] = _get_quota(club_id, quota_leixing, default=0.0)

    today = date.today()
    today_totals = {i: 0.0 for i in range(1, 7)}
    for rec in WithdrawalDailyStats.query.filter(club_id=club_id, Date=today):
        if rec.WithdrawalType in today_totals:
            today_totals[rec.WithdrawalType] = float(rec.total_amount)

    return {
        'club_id': club_id,
        'scope': resolve_club_scope(request),
        'withdraw_mode': get_withdraw_mode(club_id),
        'rates': rate_map,
        'order_rates': order_rate_map,
        'penalty_bonus_rates': get_penalty_bonus_rates_map(club_id),
        'quotas': quota_map,
        'total_limits': total_limit_map,
        'today_totals': today_totals,
    }


def apply_withdraw_settings_update(request, permissions):
    if resolve_club_scope(request) == DATA_SCOPE_ALL:
        return Response({'code': 403, 'msg': '请在子公司视图下修改提现设置'})

    club_id = _club_id(request)
    rates = request.data.get('rates', {})
    order_rates = request.data.get('order_rates', request.data.get('commission_rates', {}))
    penalty_bonus_rates = request.data.get('penalty_bonus_rates', {})
    quotas = request.data.get('quotas', {})
    total_limits = request.data.get('total_limits', {})

    role_perms = {1: '5500a', 2: '5500b', 3: '5500c'}
    rate_code_map = {1: '5', 2: '6', 3: '8', 4: '9', 5: '11', 6: '10'}
    order_rate_code_map = {1: '1', 3: '3', 12: '12', 13: '13'}
    total_code_map = {1: 4, 2: 5, 3: 6, 4: 7, 5: 8, 6: 9}

    def _rate_key_present(data, role):
        return (str(role) in data and data[str(role)] is not None) or \
               (role in data and data[role] is not None)

    with transaction.atomic():
        for role in [1, 2, 3]:
            perm_needed = role_perms[role]
            if perm_needed not in permissions:
                if _rate_key_present(rates, role) or \
                   (str(role) in quotas and quotas[str(role)] is not None) or \
                   (role in quotas and quotas.get(role) is not None) or \
                   (str(role) in total_limits and total_limits[str(role)] is not None) or \
                   (role in total_limits and total_limits.get(role) is not None):
                    return Response({'code': 403, 'msg': f'无权限修改{["","打手","管事","组长"][role]}相关设置（需要{perm_needed}）'})

        extra_role_names = {4: '考核官', 5: '打手押金', 6: '商家余额'}
        for role in [4, 5, 6]:
            if _rate_key_present(rates, role) and not any(p in permissions for p in ('5500a', '5500b', '5500c')):
                return Response({'code': 403, 'msg': f'无权限修改{extra_role_names[role]}提现手续费率'})
            if (str(role) in total_limits and total_limits[str(role)] is not None) or \
               (role in total_limits and total_limits.get(role) is not None):
                if not any(p in permissions for p in ('5500a', '5500b', '5500c')):
                    return Response({'code': 403, 'msg': f'无权限修改{extra_role_names[role]}总限额'})

        for role in [1, 3, 12, 13]:
            if _rate_key_present(order_rates, role) and not any(p in permissions for p in ('5500a', '5500b', '5500c')):
                order_names = {
                    1: '平台订单打手分红', 3: '商家订单打手分红',
                    12: '押金管事分红', 13: '管事订单分红',
                }
                return Response({'code': 403, 'msg': f'无权限修改{order_names[role]}费率'})

        for shenfen in PENALTY_BONUS_SHENFEN:
            if _rate_key_present(penalty_bonus_rates, shenfen) and not any(
                p in permissions for p in ('5500a', '5500b', '5500c')
            ):
                return Response({
                    'code': 403,
                    'msg': f'无权限修改{PENALTY_BONUS_SHENFEN[shenfen]}罚款分红费率',
                })

        for role in [1, 2, 3, 4, 5, 6]:
            val = rates.get(str(role), rates.get(role))
            if val is not None:
                _set_lilv(club_id, rate_code_map[role], Decimal(str(val)))

        for role in [1, 3, 12, 13]:
            val = order_rates.get(str(role), order_rates.get(role))
            if val is not None:
                _set_lilv(club_id, order_rate_code_map[role], Decimal(str(val)))

        for shenfen in PENALTY_BONUS_SHENFEN:
            val = penalty_bonus_rates.get(str(shenfen), penalty_bonus_rates.get(shenfen))
            if val is not None:
                rate = Decimal(str(val))
                if rate < 0 or rate > 1:
                    return Response({
                        'code': 400,
                        'msg': f'{PENALTY_BONUS_SHENFEN[shenfen]}罚款分红费率须在 0~1 之间（如 0.6 表示 60%）',
                    })
                _set_penalty_bonus_rate(club_id, shenfen, rate)

        for role in [1, 2, 3]:
            if str(role) in quotas:
                val = quotas[str(role)]
                if val is not None:
                    _set_quota(club_id, role, Decimal(str(val)))
            elif role in quotas and quotas.get(role) is not None:
                _set_quota(club_id, role, Decimal(str(quotas[role])))

        for role in [1, 2, 3, 4, 5, 6]:
            val = total_limits.get(str(role), total_limits.get(role))
            if val is not None:
                _set_quota(club_id, total_code_map[role], Decimal(str(val)))

        withdraw_mode = request.data.get('withdraw_mode')
        if withdraw_mode is not None:
            if not any(p in permissions for p in ('5500a', '5500b', '5500c')):
                return Response({'code': 403, 'msg': '无权限修改提现模式'})
            row, created = ClubWithdrawConfig.query.get_or_create(
                club_id=club_id,
                defaults={'mode': int(withdraw_mode)},
            )
            if not created:
                row.mode = int(withdraw_mode)
                row.save(update_fields=['mode', 'UpdateTime'])

    return Response({'code': 0, 'msg': '设置修改成功'})
