"""后台会员充值记录明细（czjilu leixing=1）+ 管事/组长分红关联查询。"""
from __future__ import annotations

from datetime import datetime
from decimal import Decimal

from django.db.models import Q, Sum, Count
from django.utils import timezone

from jituan.services.club_context import filter_queryset_by_club, resolve_club_scope, resolve_club_id_from_request
from jituan.services.club_user_access import list_response_meta
from jituan.services.member_recharge import (
    MEMBER_LEIXING,
    MEMBER_PAID_STATUS,
    MEMBER_PENDING_STATUS,
    MEMBER_FAILED_STATUS,
    MEMBER_CANCELLED_STATUS,
    resolve_formal_purchase_cishu,
)
from jituan.constants import DATA_SCOPE_ALL
from products.models import Czjilu, Gsfenhong, Huiyuan
from users.models import UserDashou, UserBoss

MEMBER_STATUS_LABELS = {
    MEMBER_PAID_STATUS: '已支付',
    MEMBER_PENDING_STATUS: '待支付',
    MEMBER_FAILED_STATUS: '履约失败',
    MEMBER_CANCELLED_STATUS: '已取消',
}


def _parse_dt(value):
    if not value:
        return None
    if isinstance(value, datetime):
        return value
    text = str(value).strip()
    if not text:
        return None
    for fmt in ('%Y-%m-%d %H:%M:%S', '%Y-%m-%dT%H:%M:%S', '%Y-%m-%d'):
        try:
            dt = datetime.strptime(text[:19] if 'T' not in text else text.replace('Z', '')[:19], fmt)
            if timezone.is_naive(dt):
                return timezone.make_aware(dt, timezone.get_current_timezone())
            return dt
        except ValueError:
            continue
    return None


def _batch_user_display_names(user_ids):
    user_ids = [x for x in {str(i).strip() for i in user_ids if i} if x]
    if not user_ids:
        return {}
    result = {uid: uid for uid in user_ids}
    dashou_map = {
        r.user.UserUID: (r.nicheng or '').strip()
        for r in UserDashou.query.filter(user__UserUID__in=user_ids).select_related('user')
        if getattr(r.user, 'UserUID', None)
    }
    boss_map = {
        r.user.UserUID: (r.nickname or '').strip()
        for r in UserBoss.query.filter(user__UserUID__in=user_ids).select_related('user')
        if getattr(r.user, 'UserUID', None)
    }
    for uid in user_ids:
        name = dashou_map.get(uid) or boss_map.get(uid)
        if name:
            result[uid] = name
    return result


def _build_base_queryset(request):
    qs = Czjilu.query.filter(leixing=MEMBER_LEIXING)
    return filter_queryset_by_club(qs, request, club_field='club_id')


def _apply_filters(qs, filters):
    f = filters or {}

    dingdan_id = (f.get('dingdan_id') or '').strip()
    if dingdan_id:
        qs = qs.filter(dingdan_id__icontains=dingdan_id)

    yonghuid = (f.get('yonghuid') or '').strip()
    if yonghuid:
        qs = qs.filter(yonghuid__icontains=yonghuid)

    buyer_keyword = (f.get('buyer_keyword') or f.get('dashou_keyword') or '').strip()
    if buyer_keyword:
        dashou_ids = list(
            UserDashou.query.filter(nicheng__icontains=buyer_keyword).values_list('user__UserUID', flat=True)
        )
        qs = qs.filter(
            Q(yonghuid__icontains=buyer_keyword)
            | Q(shuoming__icontains=buyer_keyword)
            | Q(yonghuid__in=dashou_ids)
        )

    huiyuan_id = f.get('huiyuan_id')
    if huiyuan_id:
        if isinstance(huiyuan_id, (list, tuple)):
            ids = [str(x).strip() for x in huiyuan_id if str(x).strip()]
            if ids:
                qs = qs.filter(huiyuan_id__in=ids)
        else:
            qs = qs.filter(huiyuan_id=str(huiyuan_id).strip())

    if f.get('is_trial') is not None and f.get('is_trial') != '':
        qs = qs.filter(is_trial=bool(f.get('is_trial')))

    zhuangtai = f.get('zhuangtai')
    if zhuangtai is not None and zhuangtai != '':
        qs = qs.filter(zhuangtai=int(zhuangtai))

    date_from = _parse_dt(f.get('date_from') or f.get('start_time'))
    date_to = _parse_dt(f.get('date_to') or f.get('end_time'))
    if date_from:
        qs = qs.filter(CreateTime__gte=date_from)
    if date_to:
        if len(str(f.get('date_to') or f.get('end_time') or '')) <= 10:
            date_to = date_to.replace(hour=23, minute=59, second=59)
        qs = qs.filter(CreateTime__lte=date_to)

    jine_min = f.get('jine_min')
    jine_max = f.get('jine_max')
    if jine_min not in (None, ''):
        qs = qs.filter(jine__gte=Decimal(str(jine_min)))
    if jine_max not in (None, ''):
        qs = qs.filter(jine__lte=Decimal(str(jine_max)))

    guanshi_id = (f.get('guanshi_id') or '').strip()
    if guanshi_id:
        order_ids = Gsfenhong.query.filter(
            guanshi__icontains=guanshi_id,
            fenhong_leixing=1,
        ).values_list('dingdan_id', flat=True)
        qs = qs.filter(dingdan_id__in=list(order_ids))

    zuzhang_id = (f.get('zuzhang_id') or '').strip()
    if zuzhang_id:
        order_ids = Gsfenhong.query.filter(
            zuzhang_id__icontains=zuzhang_id,
            fenhong_leixing=1,
        ).values_list('dingdan_id', flat=True)
        qs = qs.filter(dingdan_id__in=list(order_ids))

    keyword = (f.get('keyword') or '').strip()
    if keyword:
        qs = qs.filter(
            Q(dingdan_id__icontains=keyword)
            | Q(yonghuid__icontains=keyword)
            | Q(shuoming__icontains=keyword)
            | Q(huiyuan_id__icontains=keyword)
        )

    is_bundle = f.get('is_bundle')
    if is_bundle is not None and is_bundle != '':
        bundle_ids = list(
            Huiyuan.query.filter(is_bundle=bool(is_bundle)).values_list('huiyuan_id', flat=True)
        )
        if bool(is_bundle):
            qs = qs.filter(huiyuan_id__in=bundle_ids)
        else:
            qs = qs.exclude(huiyuan_id__in=bundle_ids)

    has_fenhong = f.get('has_fenhong')
    if has_fenhong is not None and has_fenhong != '':
        paid_ids = Gsfenhong.query.filter(fenhong_leixing=1).values_list('dingdan_id', flat=True)
        paid_set = set(paid_ids)
        if bool(has_fenhong):
            qs = qs.filter(dingdan_id__in=paid_set)
        else:
            qs = qs.exclude(dingdan_id__in=paid_set)

    club_id = (f.get('club_id') or '').strip()
    if club_id:
        qs = qs.filter(club_id=club_id)

    return qs


def _build_summary(qs):
    paid_qs = qs.filter(zhuangtai=MEMBER_PAID_STATUS)
    paid_ids = list(paid_qs.values_list('dingdan_id', flat=True))
    fh_qs = Gsfenhong.query.filter(dingdan_id__in=paid_ids, fenhong_leixing=1)
    agg = paid_qs.aggregate(
        paid_count=Count('dingdan_id'),
        paid_jine=Sum('jine'),
        trial_count=Count('dingdan_id', filter=Q(is_trial=True)),
    )
    fh_agg = fh_qs.aggregate(
        guanshi_total=Sum('fenhong'),
        zuzhang_total=Sum('zuzhang_fenhong'),
        fenhong_count=Count('dingdan_id'),
    )
    return {
        'total_count': qs.count(),
        'paid_count': int(agg.get('paid_count') or 0),
        'pending_count': qs.filter(zhuangtai=MEMBER_PENDING_STATUS).count(),
        'paid_jine': str(agg.get('paid_jine') or Decimal('0')),
        'trial_count': int(agg.get('trial_count') or 0),
        'guanshi_fenhong_total': str(fh_agg.get('guanshi_total') or Decimal('0')),
        'zuzhang_fenhong_total': str(fh_agg.get('zuzhang_total') or Decimal('0')),
        'fenhong_record_count': int(fh_agg.get('fenhong_count') or 0),
    }


def _huiyuan_options(request):
    qs = Huiyuan.query.all().order_by('-CreateTime')
    return [
        {
            'huiyuan_id': m.huiyuan_id,
            'jieshao': m.jieshao,
            'is_bundle': bool(getattr(m, 'is_bundle', False)),
        }
        for m in qs
    ]


def build_member_recharge_records_payload(request, filters=None, page=1, page_size=20):
    page = max(1, int(page or 1))
    page_size = min(100, max(1, int(page_size or 20)))

    qs = _apply_filters(_build_base_queryset(request), filters)
    qs = qs.order_by('-CreateTime')
    total = qs.count()
    offset = (page - 1) * page_size
    rows = list(qs[offset:offset + page_size])

    dingdan_ids = [r.dingdan_id for r in rows]
    fenhong_map = {
        g.dingdan_id: g
        for g in Gsfenhong.query.filter(dingdan_id__in=dingdan_ids, fenhong_leixing=1)
    }

    huiyuan_ids = {r.huiyuan_id for r in rows if r.huiyuan_id}
    huiyuan_map = {m.huiyuan_id: m for m in Huiyuan.query.filter(huiyuan_id__in=huiyuan_ids)}

    user_ids = {r.yonghuid for r in rows if r.yonghuid}
    for g in fenhong_map.values():
        if g.guanshi:
            user_ids.add(g.guanshi)
        if g.zuzhang_id:
            user_ids.add(g.zuzhang_id)
        if g.dashouid:
            user_ids.add(g.dashouid)
    name_map = _batch_user_display_names(user_ids)

    items = []
    for order in rows:
        hy = huiyuan_map.get(order.huiyuan_id)
        fh = fenhong_map.get(order.dingdan_id)
        formal_cishu = None
        if order.zhuangtai == MEMBER_PAID_STATUS and not order.is_trial:
            formal_cishu = resolve_formal_purchase_cishu(
                order.yonghuid, order.huiyuan_id, order.dingdan_id, order.club_id,
            )

        fenhong_detail = None
        if fh:
            fenhong_detail = {
                'guanshi_id': fh.guanshi or '',
                'guanshi_nicheng': name_map.get(fh.guanshi, fh.guanshi or ''),
                'guanshi_fenhong': str(fh.fenhong or 0),
                'zuzhang_id': fh.zuzhang_id or '',
                'zuzhang_nicheng': name_map.get(fh.zuzhang_id, fh.zuzhang_id or ''),
                'zuzhang_fenhong': str(fh.zuzhang_fenhong or 0),
                'fenhong_leixing': fh.fenhong_leixing,
                'is_trial': bool(fh.is_trial),
                'fenhong_time': fh.CreateTime.isoformat() if fh.CreateTime else None,
                'formal_cishu': formal_cishu,
                'shuoming': fh.shuoming or '',
            }

        items.append({
            'dingdan_id': order.dingdan_id,
            'yonghuid': order.yonghuid,
            'buyer_nicheng': name_map.get(order.yonghuid, order.yonghuid),
            'huiyuan_id': order.huiyuan_id,
            'huiyuan_name': hy.jieshao if hy else (order.huiyuan_id or ''),
            'is_bundle': bool(hy and getattr(hy, 'is_bundle', False)),
            'jine': str(order.jine or 0),
            'zhuangtai': order.zhuangtai,
            'zhuangtai_label': MEMBER_STATUS_LABELS.get(order.zhuangtai, f'状态{order.zhuangtai}'),
            'is_trial': bool(order.is_trial),
            'purchase_days': order.purchase_days,
            'shuoming': order.shuoming or '',
            'club_id': order.club_id,
            'CreateTime': order.CreateTime.isoformat() if order.CreateTime else None,
            'UpdateTime': order.UpdateTime.isoformat() if order.UpdateTime else None,
            'formal_cishu': formal_cishu,
            'fenhong': fenhong_detail,
        })

    return {
        'list': items,
        'total': total,
        'page': page,
        'page_size': page_size,
        'summary': _build_summary(_apply_filters(_build_base_queryset(request), filters)),
        'filter_options': {
            'huiyuan_list': _huiyuan_options(request),
            'zhuangtai_options': [
                {'value': MEMBER_PAID_STATUS, 'label': '已支付'},
                {'value': MEMBER_PENDING_STATUS, 'label': '待支付'},
                {'value': MEMBER_FAILED_STATUS, 'label': '履约失败'},
                {'value': MEMBER_CANCELLED_STATUS, 'label': '已取消'},
            ],
        },
        'scope': resolve_club_scope(request),
        'club_id': resolve_club_id_from_request(request),
        **list_response_meta(request),
    }
