"""按真实操作人聚合商家订单操作流水统计。"""
from collections import defaultdict
from datetime import datetime
from decimal import Decimal

from django.conf import settings
from django.db.models import Count, Max, Sum
from django.utils import timezone

from merchant_ops.constants import (
    ACTOR_MERCHANT,
    ACTOR_STAFF,
    ORDER_ACTION_LABELS,
)
from merchant_ops.models import MerchantOrderActionLog, MerchantStaffMember
from products.models import ShangpinLeixing


def _parse_dt(value, end_of_day=False):
    """解析时间；USE_TZ=False 时必须返回 naive datetime（MySQL）。"""
    if value is None or value == '':
        return None
    dt = None
    if isinstance(value, datetime):
        dt = value
    else:
        text = str(value).strip().replace('/', '-')
        for fmt in ('%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M', '%Y-%m-%d'):
            try:
                dt = datetime.strptime(text, fmt)
                if fmt == '%Y-%m-%d' and end_of_day:
                    dt = dt.replace(hour=23, minute=59, second=59)
                break
            except ValueError:
                continue
    if dt is None:
        return None

    use_tz = bool(getattr(settings, 'USE_TZ', False))
    if use_tz:
        if timezone.is_naive(dt):
            dt = timezone.make_aware(dt, timezone.get_current_timezone())
    else:
        if timezone.is_aware(dt):
            dt = timezone.make_naive(dt, timezone.get_current_timezone())
    return dt


def _money(val):
    if val is None:
        return '0.00'
    return f'{Decimal(str(val)):.2f}'


def _dec(val):
    if val is None:
        return Decimal('0')
    try:
        return Decimal(str(val))
    except Exception:
        return Decimal('0')


def build_action_stats_queryset(
    merchant_id,
    *,
    operator_user_id=None,
    operator_type=None,
    role_code=None,
    action_code=None,
    action_codes=None,
    leixing_id=None,
    start_time=None,
    end_time=None,
):
    qs = MerchantOrderActionLog.objects.filter(merchant_id=str(merchant_id))
    if operator_user_id:
        qs = qs.filter(operator_user_id=str(operator_user_id))
    if operator_type:
        qs = qs.filter(operator_type=str(operator_type).upper())
    if role_code:
        qs = qs.filter(role_code=str(role_code))
    if action_code not in (None, ''):
        qs = qs.filter(action_code=int(action_code))
    if action_codes:
        codes = []
        for c in action_codes:
            try:
                codes.append(int(c))
            except (TypeError, ValueError):
                pass
        if codes:
            qs = qs.filter(action_code__in=codes)
    if leixing_id not in (None, ''):
        qs = qs.filter(leixing_id=int(leixing_id))
    st = _parse_dt(start_time, end_of_day=False)
    et = _parse_dt(end_time, end_of_day=True)
    if st:
        qs = qs.filter(CreateTime__gte=st)
    if et:
        qs = qs.filter(CreateTime__lte=et)
    return qs


def _aggregate_unique_orders(qs, group_fields):
    """
    同一分组下：同一订单同一行为只计 1 单、金额取该订单该行为记录的 Max(amount)。
    返回: {group_tuple: {'order_count', 'action_count', 'amount'}}
    """
    # 操作次数（含重复）
    action_cnt_map = {}
    for row in qs.values(*group_fields).annotate(cnt=Count('id')):
        key = tuple(row[f] for f in group_fields)
        action_cnt_map[key] = int(row['cnt'] or 0)

    # 订单去重：每个 (group..., order_id) 只留一笔金额
    unique_rows = qs.values(*group_fields, 'order_id').annotate(one_amt=Max('amount'))
    result = defaultdict(lambda: {
        'order_count': 0,
        'action_count': 0,
        'amount': Decimal('0'),
    })
    for row in unique_rows:
        key = tuple(row[f] for f in group_fields)
        result[key]['order_count'] += 1
        result[key]['amount'] += _dec(row['one_amt'])

    for key, meta in result.items():
        meta['action_count'] = action_cnt_map.get(key, 0)
    # 只有重复操作、但 unique 漏掉的分组也补上（理论上 unique 覆盖全部）
    for key, cnt in action_cnt_map.items():
        if key not in result:
            result[key] = {
                'order_count': 0,
                'action_count': cnt,
                'amount': Decimal('0'),
            }
    return result


def summarize_action_logs(qs):
    action_total = qs.aggregate(cnt=Count('id'))
    order_total = qs.values('order_id').distinct().count()

    # 总额：先按 (action_code, order_id) 去重取 Max(amount)，再按订单取各行为中金额的？
    # 用户关心订单量去重；总额对「全部」按 (action, order) 去重后的金额求和（不同行为各自算一笔金额）
    unique_amt_rows = qs.values('action_code', 'order_id').annotate(one_amt=Max('amount'))
    total_amount = sum((_dec(r['one_amt']) for r in unique_amt_rows), Decimal('0'))

    by_action_map = _aggregate_unique_orders(qs, ['action_code'])
    by_action = []
    for key in sorted(by_action_map.keys(), key=lambda k: k[0] if k[0] is not None else 0):
        code = int(key[0])
        meta = by_action_map[key]
        by_action.append({
            'action_code': code,
            'action_label': ORDER_ACTION_LABELS.get(code, f'未知({code})'),
            'order_count': meta['order_count'],
            'count': meta['order_count'],  # 兼容旧字段：对外主展示订单量
            'action_count': meta['action_count'],
            'amount': _money(meta['amount']),
        })

    by_leixing_map = _aggregate_unique_orders(
        qs.exclude(leixing_id__isnull=True),
        ['leixing_id'],
    )
    leixing_ids = [k[0] for k in by_leixing_map.keys() if k[0] is not None]
    name_map = {}
    if leixing_ids:
        for lx in ShangpinLeixing.query.filter(id__in=leixing_ids).only('id', 'jieshao'):
            name_map[lx.id] = getattr(lx, 'jieshao', '') or str(lx.id)

    by_leixing = []
    for key, meta in sorted(by_leixing_map.items(), key=lambda x: -x[1]['order_count']):
        lid = key[0]
        by_leixing.append({
            'leixing_id': lid,
            'leixing_name': name_map.get(lid, str(lid)),
            'order_count': meta['order_count'],
            'count': meta['order_count'],
            'action_count': meta['action_count'],
            'amount': _money(meta['amount']),
        })

    return {
        'total_order_count': int(order_total or 0),
        'total_count': int(order_total or 0),  # 主数字=去重订单量
        'total_action_count': int(action_total['cnt'] or 0),
        'total_amount': _money(total_amount),
        'by_action': by_action,
        'by_leixing': by_leixing,
    }


def build_operator_action_stats(merchant_id, filters):
    qs = build_action_stats_queryset(merchant_id, **filters)
    summary = summarize_action_logs(qs)

    people_map = _aggregate_unique_orders(
        qs,
        ['operator_user_id', 'operator_type', 'role_code', 'role_name'],
    )

    # 补职位备注
    staff_uids = [
        k[0] for k in people_map.keys()
        if k[1] == ACTOR_STAFF
    ]
    remark_map = {}
    name_map = {}
    if staff_uids:
        for m in MerchantStaffMember.objects.filter(
            merchant_id=str(merchant_id),
            staff_user_id__in=staff_uids,
            status=1,
        ).select_related('role'):
            remark_map[m.staff_user_id] = m.merchant_remark or ''
            name_map[m.staff_user_id] = m.display_name or ''

    people = []
    for key, meta in sorted(people_map.items(), key=lambda x: -x[1]['order_count']):
        uid, op_type, role_code, role_name = key
        role_name = role_name or ('商家本人' if op_type == ACTOR_MERCHANT else '')
        remark = remark_map.get(uid, '') if op_type == ACTOR_STAFF else ''
        display = name_map.get(uid, '') if op_type == ACTOR_STAFF else '商家本人'
        people.append({
            'operator_user_id': uid,
            'operator_type': op_type,
            'role_code': role_code or '',
            'role_name': role_name,
            'merchant_remark': remark,
            'display_name': display,
            'order_count': meta['order_count'],
            'count': meta['order_count'],
            'action_count': meta['action_count'],
            'amount': _money(meta['amount']),
        })

    return {
        **summary,
        'people': people,
        'action_defs': [
            {'action_code': k, 'action_label': v}
            for k, v in sorted(ORDER_ACTION_LABELS.items())
        ],
    }


def list_operator_candidates(merchant_id):
    """经营数据页可选身份：商家本人 + 子客服（展示职位+备注）。"""
    items = [{
        'operator_user_id': str(merchant_id),
        'operator_type': ACTOR_MERCHANT,
        'role_code': 'OWNER',
        'role_name': '商家本人',
        'merchant_remark': '',
        'display_name': '商家本人',
        'staff_member_id': None,
    }]
    members = (
        MerchantStaffMember.objects
        .filter(merchant_id=str(merchant_id), status=1)
        .select_related('role')
        .order_by('id')
    )
    for m in members:
        role_name = m.role.role_name if m.role else '子客服'
        remark = (m.merchant_remark or '').strip()
        nick = (m.display_name or '').strip()
        parts = [role_name]
        if remark:
            parts.append(f'备注:{remark}')
        elif nick:
            parts.append(nick)
        parts.append(m.staff_user_id)
        items.append({
            'operator_user_id': m.staff_user_id,
            'operator_type': ACTOR_STAFF,
            'role_code': m.role.role_code if m.role else '',
            'role_name': role_name,
            'merchant_remark': remark,
            'display_name': ' · '.join(parts),
            'staff_member_id': m.id,
        })
    return items
