#!/usr/bin/env python3
"""
派生 frontend stage-fields.ts —— v3 主数据 82 字段 × 节点映射 → 工作台字段配置。

数据源：v3-fields.json（解析自 Requirement_Workflow_with_Master_mapping_v3.html）
输出：frontend/src/app/(modules)/robot-manager/my-work/stage-fields.ts

何时跑：v3-fields.json 改了 / RobotLifecycleStage enum 变了 / SEQ_TO_STAGE 映射调整。

用法：
  python3 docs/modules/robot-manager/business-analysis/_build-stage-fields.py
"""
import json
import os
import sys

ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
    os.path.dirname(os.path.abspath(__file__))))))

FIELDS_JSON = os.path.join(ROOT, 'docs/modules/robot-manager/business-analysis/v3-fields.json')
OUT_TS = os.path.join(ROOT, 'frontend/src/app/(modules)/robot-manager/my-work/stage-fields.ts')

# v3 seq → frontend RobotLifecycleStage 映射
# 部分 frontend stage 合并了多个 v3 节点（业务上是细分步骤，frontend 状态机更粗）
SEQ_TO_STAGE = {
    '01':   'SUPPLY_PO_CREATED',
    '02':   'SUPPLY_IN_PRODUCTION',
    '03':   'SUPPLY_READY_TO_SHIP',
    '04':   'LOGISTICS_IN_TRANSIT',
    '05':   'LOGISTICS_BONDED',
    '06':   'LOGISTICS_CUSTOMS_CLEARED',
    '07':   'WAREHOUSE_RECEIVED',
    '08':   'WAREHOUSE_AT_W1_PDI',
    '16':   'WAREHOUSE_AT_W2_RLE',
    'FT':   'WAREHOUSE_MODIFICATION',   # W3 功能测试合并到改装段
    '09':   'WAREHOUSE_MODIFICATION',
    '10':   'WAREHOUSE_MODIFICATION',   # 改装验证合并到改装段
    '11':   'WAREHOUSE_BRANDED_READY',
    '12':   'SALES_RESERVED',
    'P6.1': 'DELIVERY_PAYMENT_COLLECTED',
    '13':   'SALES_PAYMENT_VALIDATED',
    '14':   'DELIVERY_READY',
    'DA':   'DELIVERY_APPROVAL',
    'DV':   'DELIVERY_APPROVAL',        # 交付验证合并到交付审批
    '15':   'DELIVERY_DELIVERED',
    '17':   'RENTAL_ACTIVE',
    'ST':   'AFTERSALES_TICKET',
    'RI':   'AFTERSALES_RETURN_INITIATED',
    'RR':   'AFTERSALES_RETURN_RECEIVED',
    'W6':   'AFTERSALES_AT_W6',
    '18':   'AFTERSALES_UNDER_REPAIR',
    '19':   'AFTERSALES_REPAIRED',
    'QA':   'AFTERSALES_QUOTE_APPROVAL',
    '21':   'CLOSED',
}

ALL_STAGES = [
    'SUPPLY_PO_CREATED','SUPPLY_IN_PRODUCTION','SUPPLY_READY_TO_SHIP',
    'LOGISTICS_IN_TRANSIT','LOGISTICS_BONDED','LOGISTICS_CUSTOMS_CLEARED',
    'WAREHOUSE_RECEIVED','WAREHOUSE_AT_W1_PDI','WAREHOUSE_MODIFICATION',
    'WAREHOUSE_AT_W2','WAREHOUSE_AT_W2_RLE','WAREHOUSE_BRANDED_READY',
    'SALES_RESERVED','SALES_PAYMENT_VALIDATED',
    'DELIVERY_APPROVAL','DELIVERY_PAYMENT_COLLECTED','DELIVERY_READY','DELIVERY_DELIVERED',
    'RENTAL_ACTIVE',
    'AFTERSALES_TICKET','AFTERSALES_RETURN_INITIATED','AFTERSALES_RETURN_RECEIVED',
    'AFTERSALES_AT_W6','AFTERSALES_UNDER_REPAIR','AFTERSALES_QUOTE_APPROVAL','AFTERSALES_REPAIRED',
    'CLOSED','CANCELLED','RETURNED',
]


def main():
    fields = json.load(open(FIELDS_JSON, encoding='utf-8'))
    stage_seqs = {}
    for seq, stage in SEQ_TO_STAGE.items():
        stage_seqs.setdefault(stage, []).append(seq)

    def fields_for_stage(stage):
        seqs = stage_seqs.get(stage, [])
        primary, readonly = [], []
        for f in fields:
            if any(s in f['mainNodes'] for s in seqs):
                primary.append(f)
                continue
            if 'multi' in f['mainNodes'] and any(s in f['reads'] for s in seqs):
                primary.append(f)
                continue
            if 'GLOBAL' in f['mainNodes']:
                readonly.append(f)
                continue
            if '全节点' in f['reads'] or any(s in f['reads'] for s in seqs):
                readonly.append(f)
        return primary, readonly

    j = lambda s: json.dumps(s, ensure_ascii=False)
    lines = []
    lines.append('// AUTO-GENERATED — 不要手工编辑')
    lines.append('// 数据源：docs/modules/robot-manager/business-analysis/v3-fields.json (82 字段 × 29 节点映射)')
    lines.append('// 重新生成：python3 docs/modules/robot-manager/business-analysis/_build-stage-fields.py')
    lines.append('// 含义：每个 RobotLifecycleStage 对应"需要填写的字段"（primary）+ "只读引用的上下文字段"（readonly）')
    lines.append('')
    lines.append("import type { RobotLifecycleStage } from '../_lib/api';")
    lines.append('')
    lines.append('export interface StageFieldDef {')
    lines.append('  /** Master 字段名（英文，对照 v5 主数据 schema 列） */')
    lines.append('  masterCol: string;')
    lines.append('  /** 中文标签（业务方读法） */')
    lines.append('  cnLabel: string;')
    lines.append('  /** v3 主写节点 seq（如 "01" / "FT" / "P6.1" / "multi"） */')
    lines.append('  mainSeq: string;')
    lines.append('}')
    lines.append('')
    lines.append('export interface StageFields {')
    lines.append('  /** 主写字段：当前 stage 需要"填写"的字段（卡片徽章 / Drawer 高亮区） */')
    lines.append('  primary: StageFieldDef[];')
    lines.append('  /** 只读引用：当前 stage 会"用到"但不修改的字段（Drawer 折叠区） */')
    lines.append('  readonly: StageFieldDef[];')
    lines.append('}')
    lines.append('')
    lines.append('export const STAGE_FIELDS: Record<RobotLifecycleStage, StageFields> = {')
    for stage in ALL_STAGES:
        primary, readonly = fields_for_stage(stage)
        lines.append(f'  {stage}: {{')
        lines.append('    primary: [')
        for f in primary:
            main = ','.join(f['mainNodes']) or '—'
            lines.append(f'      {{ masterCol: {j(f["field"])}, cnLabel: {j(f["cn"])}, mainSeq: {j(main)} }},')
        lines.append('    ],')
        lines.append('    readonly: [')
        for f in readonly:
            main = ','.join(f['mainNodes']) or '—'
            lines.append(f'      {{ masterCol: {j(f["field"])}, cnLabel: {j(f["cn"])}, mainSeq: {j(main)} }},')
        lines.append('    ],')
        lines.append('  },')
    lines.append('};')
    lines.append('')
    lines.append('export function getStageFields(stage: RobotLifecycleStage): StageFields {')
    lines.append('  return STAGE_FIELDS[stage] ?? { primary: [], readonly: [] };')
    lines.append('}')
    lines.append('')

    with open(OUT_TS, 'w', encoding='utf-8') as fp:
        fp.write('\n'.join(lines))

    total_primary = sum(len(fields_for_stage(s)[0]) for s in ALL_STAGES)
    total_readonly = sum(len(fields_for_stage(s)[1]) for s in ALL_STAGES)
    print(f'✅ {OUT_TS}')
    print(f'   {len(ALL_STAGES)} stages · {total_primary} primary slots · {total_readonly} readonly slots')


if __name__ == '__main__':
    main()
