# -*- coding: utf-8 -*-
"""
龙先生(lxs)审核版目录重置：对齐小程序简介的「专业电竞护航 / 技巧支持 / 策略指导」。

目标（审核口径）：
  - 强调：线上电竞技巧讲解、对局策略交流、团队协作指导、正向技能提升
  - 绝不出现：代练、代打、上分、线下陪玩、陪玩约玩等
  - 仅改 club_id=lxs + 全局审核类型(shenhezhuangtai=2) 下的专区/商品
  - 不碰正常商品(shenhezhuangtai=1)、其它俱乐部、店铺商品、订单

动作：
  1) 将 3 个审核类型名改为：电竞技巧指导 / 对局策略交流 / 线上技能提升
  2) 清空 lxs 下这些类型的审核专区+商品（只删 DB，不删 OSS）
  3) 每个类型 2 个专区；每个专区 10 个商品（共 60）
  4) 图标统一 a_long/morentouxiang.jpg
  5) 下单须知写明：仅线上指导交流，禁止代练代打与线下服务

用法:
  python manage.py reset_lxs_shenhe_esports_coach
  python manage.py reset_lxs_shenhe_esports_coach --list
  python manage.py reset_lxs_shenhe_esports_coach --apply --i-confirm=lxs-esports-coach
"""
from __future__ import annotations

from decimal import Decimal

from django.core.management.base import BaseCommand, CommandError
from django.db import transaction

ALLOWED_CLUB_ID = 'lxs'
NAME_HINT = '龙先生'
SHENHE = 2
DEFAULT_AVATAR = 'a_long/morentouxiang.jpg'
CONFIRM_TOKEN = 'lxs-esports-coach'
EXPECTED_TYPE_COUNT = 3

TYPE_NAMES = ['电竞技巧指导', '对局策略交流', '线上技能提升']

ZONE_NAMES_BY_TYPE = [
    ['技巧讲解', '操作指导'],
    ['策略复盘', '思路交流'],
    ['协作训练', '正向成长'],
]

PRODUCTS_PER_ZONE = [
    [
        ('基础操作技巧讲解', '线上讲解基础操作与键位思路，帮助建立正确习惯，重在理解与练习。', '19.90'),
        ('走位思路实时指导', '对局中讲解走位与观察习惯，提升意识，由学员本人操作完成。', '25.90'),
        ('技能连招要点拆解', '拆解技能释放节奏与连招要点，循序渐进，强调自学自练。', '22.90'),
        ('地图资源意识教学', '讲解地图信息与资源节奏，培养全局观，纯技巧交流。', '22.90'),
        ('瞄准与预判要点分享', '分享瞄准预判的练习方法，给出训练建议，学员自行练习。', '25.90'),
        ('开局节奏规划指导', '讲解开局规划与信息收集，帮助形成稳定开局习惯。', '19.90'),
        ('道具使用思路讲解', '讲解常用道具使用时机与配合思路，强调理解而非包办。', '19.90'),
        ('视野与信息读取教学', '教学如何读图、读信息，提升判断力，正向技能成长。', '22.90'),
        ('残局处理要点交流', '交流残局决策思路与优先级，鼓励独立思考与复盘。', '25.90'),
        ('个性化技巧答疑', '针对个人薄弱点线上答疑，给出可执行的练习清单。', '29.90'),
    ],
    [
        ('对局策略思路交流', '线上交流阵容与战术思路，重在理解策略，学员自主决策执行。', '25.90'),
        ('团战站位策略讲解', '讲解团战站位与目标优先级，提升团队配合意识。', '25.90'),
        ('资源分配策略讨论', '讨论资源分配与节奏取舍，培养理性决策能力。', '22.90'),
        ('对手习惯观察复盘', '复盘如何观察对手习惯，给出分析框架，鼓励自我复盘。', '22.90'),
        ('中期转线策略交流', '交流中期转线与节奏切换思路，帮助建立阶段目标。', '25.90'),
        ('防守反击策略拆解', '拆解防守反击的触发条件与执行步骤，逻辑清晰可练。', '22.90'),
        ('进攻时机判断指导', '讲解进攻时机判断要素，强调信息与纪律，杜绝侥幸。', '25.90'),
        ('阵容克制关系科普', '科普常见克制关系与应对思路，开阔视野，正向学习。', '19.90'),
        ('赛后复盘方法教学', '教学赛后复盘步骤：录像、标注、总结，养成成长闭环。', '19.90'),
        ('策略问答一对一', '一对一策略问答，解答困惑，给出清晰可落地的改进方向。', '29.90'),
    ],
    [
        ('团队沟通协作指导', '指导语音沟通话术与分工习惯，打造文明友好的协作环境。', '19.90'),
        ('良性竞争心态辅导', '交流输赢心态与压力管理，传递体育精神与正能量。', '15.90'),
        ('训练计划制定协助', '协助制定可坚持的训练计划，目标清晰、循序渐进。', '19.90'),
        ('团队默契练习指导', '指导信号、分工与节奏同步练习方法，提升协作效率。', '22.90'),
        ('文明竞技礼仪分享', '分享线上竞技礼仪与友好互动规范，拒绝不良言行。', '12.90'),
        ('专注力与节奏管理', '交流专注力与作息节奏管理小方法，支持长期进步。', '15.90'),
        ('新手友好入门指导', '面向新手的入门讲解与练习指导，学员全程自主操作。', '19.90'),
        ('进阶目标拆解辅导', '把长期目标拆成周计划，每周复盘一次，稳步提升。', '22.90'),
        ('录像点评成长课', '基于学员录像做要点点评，指出亮点与改进点，鼓励成长。', '29.90'),
        ('电竞护航技巧总复习', '汇总技巧与策略要点，形成个人笔记，巩固线上学习成果。', '25.90'),
    ],
]

BANNED_WORDS = (
    '代练', '代打', '上分', '上段', '包星', '定位赛', '代肝', '代刷',
    '代打手', '代练平台', '代练服务', '护航上分', '包赢',
    '陪玩', '线下陪玩', '上门', '约玩', '陪睡觉', '色情',
    '赌博', '出租号', '买号', '卖号',
)

ORDER_NOTICE = (
    '本服务为龙先生电竞提供的线上电竞技巧支持、对局策略指导与正向技能交流。'
    '全程由学员本人登录并亲自操作、自行决策；服务内容仅限讲解、答疑与思路交流。'
    '请文明沟通，共建专业、健康的电竞学习环境。'
)


class Command(BaseCommand):
    help = '龙先生审核版改为电竞技巧/策略指导正能量目录（默认 dry-run）'

    def add_arguments(self, parser):
        parser.add_argument('--apply', action='store_true', help='真正写库')
        parser.add_argument(
            '--i-confirm',
            type=str,
            default='',
            help=f'必须等于 {CONFIRM_TOKEN} 才允许 --apply',
        )
        parser.add_argument(
            '--list',
            action='store_true',
            help='只列出当前审核类型及 lxs 存量',
        )
        parser.add_argument(
            '--skip-rename-types',
            action='store_true',
            help='不修改全局审核类型名称，仅重建 lxs 专区/商品',
        )

    def handle(self, *args, **options):
        from jituan.models import Club
        from products.models import Shangpin, ShangpinLeixing, ShangpinZhuanqu

        apply = bool(options.get('apply'))
        confirm = (options.get('i_confirm') or '').strip()
        skip_rename = bool(options.get('skip_rename_types'))

        club = Club.query.filter(club_id=ALLOWED_CLUB_ID).first()
        if not club:
            raise CommandError(f'俱乐部 {ALLOWED_CLUB_ID} 不存在')
        if NAME_HINT not in (club.name or ''):
            raise CommandError(
                f'安全拦截：{ALLOWED_CLUB_ID} name={club.name!r} 不含「{NAME_HINT}」'
            )

        audit_types = list(
            ShangpinLeixing.query.filter(shenhezhuangtai=SHENHE).order_by('id')
        )
        if len(audit_types) != EXPECTED_TYPE_COUNT:
            raise CommandError(
                f'安全拦截：审核类型数量应为 {EXPECTED_TYPE_COUNT}，'
                f'当前为 {len(audit_types)}：'
                + ', '.join(f'id={t.id}「{t.jieshao}」' for t in audit_types)
            )

        leixing_ids = [t.id for t in audit_types]

        def counts():
            z = ShangpinZhuanqu.query.filter(
                club_id=ALLOWED_CLUB_ID,
                leixing_id__in=leixing_ids,
                shenhezhuangtai=SHENHE,
                dianpu__isnull=True,
            ).count()
            p = Shangpin.query.filter(
                club_id=ALLOWED_CLUB_ID,
                leixing_id__in=leixing_ids,
                shenhezhuangtai=SHENHE,
                dianpu__isnull=True,
            ).count()
            return z, p

        if options.get('list'):
            self.stdout.write(self.style.NOTICE('审核类型 → 计划改名；lxs 当前专区/商品：'))
            for i, t in enumerate(audit_types):
                z = ShangpinZhuanqu.query.filter(
                    club_id=ALLOWED_CLUB_ID, leixing_id=t.id,
                    shenhezhuangtai=SHENHE, dianpu__isnull=True,
                ).count()
                p = Shangpin.query.filter(
                    club_id=ALLOWED_CLUB_ID, leixing_id=t.id,
                    shenhezhuangtai=SHENHE, dianpu__isnull=True,
                ).count()
                self.stdout.write(
                    f'  id={t.id}「{t.jieshao}」→「{TYPE_NAMES[i]}」  '
                    f'lxs zones={z} products={p}'
                )
            return

        for zone_list in PRODUCTS_PER_ZONE:
            if len(zone_list) != 10:
                raise CommandError('内部错误：每个类型必须恰好 10 个商品模板')
            for title, intro, _price in zone_list:
                # 只扫标题/介绍；须知用正向表述，不出现敏感词本身
                blob = title + intro
                for w in BANNED_WORDS:
                    if w in blob:
                        raise CommandError(f'文案含禁止词「{w}」: {title}')
        for w in BANNED_WORDS:
            if w in ORDER_NOTICE:
                raise CommandError(f'下单须知含禁止词「{w}」，请改成正向表述')

        for zones in ZONE_NAMES_BY_TYPE:
            if len(zones) != 2:
                raise CommandError('内部错误：每个类型必须恰好 2 个专区')
            for zn in zones:
                for w in BANNED_WORDS:
                    if w in zn:
                        raise CommandError(f'专区名含禁止词「{w}」: {zn}')

        for tn in TYPE_NAMES:
            for w in BANNED_WORDS:
                if w in tn:
                    raise CommandError(f'类型名含禁止词「{w}」: {tn}')

        if apply and confirm != CONFIRM_TOKEN:
            raise CommandError(
                f'安全拦截：--apply 必须带 --i-confirm={CONFIRM_TOKEN}\n'
                f'  python manage.py reset_lxs_shenhe_esports_coach '
                f'--apply --i-confirm={CONFIRM_TOKEN}'
            )

        old_z, old_p = counts()
        mode = 'APPLY' if apply else 'DRY-RUN'
        self.stdout.write(self.style.NOTICE(
            f'\n===== {mode} 龙先生审核 → 电竞技巧/策略指导 =====\n'
            f'club={ALLOWED_CLUB_ID} ({club.name})\n'
            f'将清空 lxs 审核专区={old_z} 商品={old_p}，再写入 '
            f'{EXPECTED_TYPE_COUNT}类型×2专区×10商品=60\n'
            f'图标: {DEFAULT_AVATAR}\n'
            f'改名全局类型: {"否" if skip_rename else "是（影响所有俱乐部审核展示名）"}\n'
            f'定位: 线上技巧支持 / 策略指导 / 正向技能提升；无代练代打、无线下陪玩\n'
        ))

        self.stdout.write('—— 类型改名计划 ——')
        for i, t in enumerate(audit_types):
            self.stdout.write(f'  id={t.id}「{t.jieshao}」→「{TYPE_NAMES[i]}」')

        self.stdout.write('—— 专区/商品结构 ——')
        for i, tname in enumerate(TYPE_NAMES):
            for zn in ZONE_NAMES_BY_TYPE[i]:
                self.stdout.write(f'  「{tname}」/「{zn}」→ 10 个指导类商品')

        self.stdout.write('—— 商品样例 ——')
        for title, intro, price in PRODUCTS_PER_ZONE[0][:3]:
            self.stdout.write(f'  {title} ¥{price} | {intro}')

        if not apply:
            self.stdout.write(self.style.WARNING(
                '\n以上仅计划。确认后执行：\n'
                f'  python manage.py reset_lxs_shenhe_esports_coach '
                f'--apply --i-confirm={CONFIRM_TOKEN}\n'
            ))
            return

        stats = {
            'types_renamed': 0,
            'deleted_products': 0,
            'deleted_zones': 0,
            'zones_created': 0,
            'products_created': 0,
        }

        with transaction.atomic():
            if not skip_rename:
                for i, t in enumerate(audit_types):
                    new_name = TYPE_NAMES[i]
                    if (t.jieshao or '') != new_name:
                        t.jieshao = new_name
                        t.tupian_url = t.tupian_url or DEFAULT_AVATAR
                        t.save()
                        stats['types_renamed'] += 1

            n_prod, _ = Shangpin.query.filter(
                club_id=ALLOWED_CLUB_ID,
                leixing_id__in=leixing_ids,
                shenhezhuangtai=SHENHE,
                dianpu__isnull=True,
            ).delete()
            n_zone, _ = ShangpinZhuanqu.query.filter(
                club_id=ALLOWED_CLUB_ID,
                leixing_id__in=leixing_ids,
                shenhezhuangtai=SHENHE,
                dianpu__isnull=True,
            ).delete()
            stats['deleted_products'] = n_prod
            stats['deleted_zones'] = n_zone

            for i, lx in enumerate(audit_types):
                lx = ShangpinLeixing.query.filter(id=lx.id).first()
                zone_names = ZONE_NAMES_BY_TYPE[i]
                base_products = PRODUCTS_PER_ZONE[i]
                for zi, zname in enumerate(zone_names):
                    zrow = ShangpinZhuanqu.query.create(
                        mingzi=zname,
                        leixing_id=lx.id,
                        club_id=ALLOWED_CLUB_ID,
                        tupian_url=DEFAULT_AVATAR,
                        shenhezhuangtai=SHENHE,
                        paixu=20 - zi * 10,
                        shangjia_zhuangtai=True,
                        fengjin_zhuangtai=True,
                        dianpu=None,
                        dianpu_leixing=None,
                    )
                    stats['zones_created'] += 1

                    for pi, (title, intro, price) in enumerate(base_products):
                        full_title = f'{title}·{zname}'
                        for w in BANNED_WORDS:
                            if w in full_title or w in intro:
                                raise CommandError(f'禁止词命中: {full_title}')
                        Shangpin.query.create(
                            biaoqian=full_title[:45],
                            jiage=Decimal(price),
                            kucun=99999,
                            leixing_id=lx.id,
                            zhuanqu_id=zrow.id,
                            zhenshi_xiaoliang=0,
                            duiwai_xiaoliang=0,
                            jieshao=intro,
                            xiadan_xuzhi=ORDER_NOTICE,
                            guize_tupian='',
                            tupian_url=DEFAULT_AVATAR,
                            yaoqiuleixing=lx.yaoqiuleixing,
                            huiyuan_id=lx.huiyuan_id,
                            yongjin=lx.yongjin,
                            kaioi_ewai_dashou_fencheng=False,
                            ewai_dashou_fencheng=None,
                            paixu=100 - pi,
                            shenhezhuangtai=SHENHE,
                            shangjia_zhuangtai=True,
                            fengjin_zhuangtai=True,
                            shenhe_zhuangtai=True,
                            club_id=ALLOWED_CLUB_ID,
                            shi_zhuanpan=False,
                            dianpu=None,
                            dianpu_leixing=None,
                        )
                        stats['products_created'] += 1

            if stats['zones_created'] != 6 or stats['products_created'] != 60:
                raise CommandError(
                    f'数量异常: zones={stats["zones_created"]} '
                    f'products={stats["products_created"]}，期望 6/60，已回滚'
                )

        self.stdout.write(self.style.SUCCESS(
            f'\n完成: {stats}\n'
            f'均为审核专用(shenhezhuangtai=2)；文案对齐「技巧支持/策略指导」，'
            f'已避开代练代打与线下陪玩。'
        ))
