"""
星阙(xq)俱乐部 · 商家发单 · 退款审核中订单 — 批量同意退款

与客服接口 POST /yonghu/kefusjtk 同一套业务逻辑（见 orders.services.merchant_refund_approve）。

用法（先排查，再执行）：

  # 1. 仅统计，默认要求待审单数 >= 762
  python manage.py batch_approve_xq_merchant_refunds

  # 2. 指定最低单数、只看某商家
  python manage.py batch_approve_xq_merchant_refunds --min-count 762 --merchant-nicheng 星阙

  # 3. 确认无误后真正执行（建议先备份库）
  python manage.py batch_approve_xq_merchant_refunds --execute --processor batch_20260710

  # 4. 单数不足也强制跑（危险）
  python manage.py batch_approve_xq_merchant_refunds --execute --force
"""
from django.core.management.base import BaseCommand, CommandError

from jituan.constants import CLUB_ID_DEFAULT
from orders.models import Order, RefundRecord
from orders.services.merchant_refund_approve import (
    MerchantRefundApproveError,
    approve_merchant_refund_order,
    normalize_processor_id,
)
from users.models import UserShangjia


class Command(BaseCommand):
    help = '批量同意星阙(xq)商家发单退款审核（Status=4 → 5）'

    def add_arguments(self, parser):
        parser.add_argument(
            '--club-id', default=CLUB_ID_DEFAULT,
            help='俱乐部 ID，默认 xq（星阙电竞）',
        )
        parser.add_argument(
            '--min-count', type=int, default=762,
            help='待审单数低于该值则中止（除非 --force），默认 762',
        )
        parser.add_argument(
            '--merchant-id', default='',
            help='仅处理指定商家 UserUID（可选）',
        )
        parser.add_argument(
            '--merchant-nicheng', default='',
            help='仅处理商家昵称包含该关键字（可选，如 星阙）',
        )
        parser.add_argument(
            '--processor', default='138377',
            help='写入 RefundRecord.ProcessorID（chuliid，最长11位）',
        )
        parser.add_argument(
            '--tuikuan-liyou', default='批量同意退款',
            help='可选：写入订单退款理由',
        )
        parser.add_argument(
            '--execute', action='store_true',
            help='真正执行；默认仅排查统计（dry-run）',
        )
        parser.add_argument(
            '--force', action='store_true',
            help='待审单数 < min-count 时也继续（默认中止）',
        )
        parser.add_argument(
            '--limit', type=int, default=0,
            help='最多处理 N 单，0 表示不限制（排查模式忽略）',
        )

    def handle(self, *args, **options):
        club_id = (options['club_id'] or CLUB_ID_DEFAULT).strip()
        min_count = int(options['min_count'] or 0)
        merchant_id = (options['merchant_id'] or '').strip()
        merchant_nicheng = (options['merchant_nicheng'] or '').strip()
        processor = normalize_processor_id((options['processor'] or '').strip())
        tuikuan_liyou = (options['tuikuan_liyou'] or '').strip()
        do_execute = bool(options['execute'])
        force = bool(options['force'])
        limit = int(options['limit'] or 0)

        pending_refund_ids = RefundRecord.query.filter(
            ApplyStatus=0,
        ).values_list('OrderID', flat=True)

        qs = (
            Order.query.filter(
                ClubID=club_id,
                Platform=2,
                Status=4,
                OrderID__in=pending_refund_ids,
            )
            .select_related('shangjia_kuozhan')
            .order_by('OrderID')
        )

        if merchant_id:
            qs = qs.filter(shangjia_kuozhan__MerchantID=merchant_id)

        if merchant_nicheng:
            merchant_uids = list(
                UserShangjia.query.filter(
                    nicheng__icontains=merchant_nicheng,
                ).values_list('user__UserUID', flat=True)
            )
            if not merchant_uids:
                raise CommandError(f'未找到昵称包含「{merchant_nicheng}」的商家')
            qs = qs.filter(shangjia_kuozhan__MerchantID__in=merchant_uids)

        orders = list(qs)
        total = len(orders)

        self.stdout.write('')
        self.stdout.write('=== 星阙商家退款审核批量排查 ===')
        self.stdout.write(f'俱乐部         : {club_id}')
        self.stdout.write(f'筛选条件       : Platform=2(商家发单) Status=4(退款审核中) RefundRecord.ApplyStatus=0')
        self.stdout.write(f'商家 UID 过滤  : {merchant_id or "(不限)"}')
        self.stdout.write(f'商家昵称过滤   : {merchant_nicheng or "(不限)"}')
        self.stdout.write(f'待审订单数     : {total}')
        self.stdout.write(f'要求最低单数   : {min_count}（{"已满足" if total >= min_count else "未满足"}）')
        self.stdout.write(f'模式           : {"执行" if do_execute else "仅排查(dry-run)"}')
        self.stdout.write('')

        if total == 0:
            self.stdout.write(self.style.WARNING('没有符合条件的待审退款单，退出。'))
            return

        if total < min_count and not force:
            raise CommandError(
                f'待审单数 {total} < {min_count}，与预期不符，已中止。'
                f'若确认仍要处理，请加 --force'
            )

        sample = orders[:5]
        self.stdout.write('样例订单（前 5 条）：')
        for o in sample:
            mid = getattr(getattr(o, 'shangjia_kuozhan', None), 'MerchantID', '')
            self.stdout.write(
                f'  {o.OrderID}  金额={o.Amount}  商家={mid}  打手={o.PlayerID or "-"}',
            )
        if total > 5:
            self.stdout.write(f'  ... 共 {total} 条')
        self.stdout.write('')

        if not do_execute:
            self.stdout.write(self.style.WARNING(
                '当前为 dry-run，未改任何数据。确认后执行：\n'
                f'  python manage.py batch_approve_xq_merchant_refunds --execute --processor {processor}'
            ))
            return

        if limit > 0:
            orders = orders[:limit]
            self.stdout.write(self.style.WARNING(f'--limit={limit}，本次只处理前 {len(orders)} 单'))

        ok_count = 0
        fail_count = 0
        for order in orders:
            try:
                approve_merchant_refund_order(
                    order,
                    processor_id=processor,
                    tuikuan_liyou=tuikuan_liyou,
                    require_status_4=True,
                )
                ok_count += 1
                if ok_count <= 10 or ok_count % 50 == 0:
                    self.stdout.write(self.style.SUCCESS(f'  OK  {order.OrderID}'))
            except MerchantRefundApproveError as exc:
                fail_count += 1
                self.stdout.write(self.style.ERROR(f'  FAIL {order.OrderID}: {exc}'))
            except Exception as exc:
                fail_count += 1
                self.stdout.write(self.style.ERROR(f'  ERR  {order.OrderID}: {exc}'))

        self.stdout.write('')
        self.stdout.write(self.style.SUCCESS(f'完成：成功 {ok_count}，失败 {fail_count}，合计 {len(orders)}'))
        if fail_count:
            self.stdout.write(self.style.WARNING('存在失败单，请查日志后单独处理。'))
