#!/usr/bin/env python3
"""Create/update the S10 supplier-management Apifox scenario."""

from __future__ import annotations

import copy
import importlib.util
from pathlib import Path


BASE_SCRIPT = Path(
    "/Users/guodongwei/Documents/zhct/zhctprompt/"
    "work_food_safety/2026-09-24-apifox-full-api-automation/"
    "apifox/scripts/sync_school_s00_s06_scenarios.py"
)
SPEC = importlib.util.spec_from_file_location("school_s00_s06_sync", BASE_SCRIPT)
if SPEC is None or SPEC.loader is None:
    raise RuntimeError(f"Cannot load shared Apifox helpers from {BASE_SCRIPT}")
shared = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(shared)


NAME = "S10-供应商管理（双库真实写入）"
PREFIX = "APIFOX_S10"
DESCRIPTION = (
    "学校端 S10 供应商管理双库真实写入场景：供应商新增、详情、编辑、证件新增/导入、"
    "启停、批量导入、汇总与 CSV 导出。名称、人员、地址和证照采用真实中文业务风格；"
    "图片字段仅保存 example.invalid 引用，不进行文件上传或第三方请求。测试数据保留用于原表取证。"
)


OPERATIONS = [
    {
        "name": "读取供应商分页基线",
        "method": "GET",
        "path": "/school/inventory/suppliers?schoolId=1&page=1&pageSize=20",
        "tests": [
            ("供应商基线：分页结构完整", "pm.expect(__json.data.items).to.be.an('array'); pm.expect(Number(__json.data.page)).to.equal(1); pm.expect(Number(__json.data.pageSize)).to.equal(20)"),
        ],
    },
    {
        "name": "新增华丰绿色食材配送有限公司",
        "method": "POST",
        "path": "/school/inventory/suppliers",
        "body": {
            "schoolId": 1,
            "name": "华丰绿色食材配送有限公司（档案{{test_batch}}）",
            "phone": "{{supplier_phone}}",
            "address": "北京市朝阳区健康路88号食品产业园2号库",
            "contact": "采购经理刘女士",
            "email": "{{supplier_email}}",
            "enabled": True,
            "rating": 5,
            "categories": ["蔬菜", "肉禽蛋", "米面粮油"],
            "certificates": [
                {
                    "type": "营业执照",
                    "number": "SC{{test_batch}}",
                    "authority": "北京市朝阳区市场监督管理局",
                    "expireAt": "2029-12-31",
                    "imageUrl": "https://example.invalid/supplier/business-license.jpg",
                }
            ],
        },
        "extract": ("supplier_id", "$.data.id"),
        "tests": [
            ("供应商新增：返回正整数 ID", "pm.expect(Number(__json.data.id)).to.be.greaterThan(0)"),
            ("供应商新增：默认启用且评分为 5", "pm.expect(__json.data.enabled).to.equal(true); pm.expect(Number(__json.data.rating)).to.equal(5)"),
        ],
    },
    {
        "name": "回查供应商详情与营业执照",
        "method": "GET",
        "path": "/school/inventory/suppliers/detail?id={{supplier_id}}&schoolId=1",
        "tests": [
            ("详情回查：真实中文主体和联系人正确", "pm.expect(__json.data.name).to.equal('华丰绿色食材配送有限公司（档案' + pm.variables.get('test_batch') + '）'); pm.expect(__json.data.contact).to.equal('采购经理刘女士'); pm.expect(__json.data.address).to.include('食品产业园2号库')"),
            ("详情回查：营业执照字段正确", "pm.expect(__json.data.businessLicense).to.exist; pm.expect(__json.data.businessLicense.number).to.equal('SC' + pm.variables.get('test_batch')); pm.expect(__json.data.businessLicense.authority).to.equal('北京市朝阳区市场监督管理局')"),
        ],
    },
    {
        "name": "编辑供应商联系信息与供货分类",
        "method": "PATCH",
        "path": "/school/inventory/suppliers?id={{supplier_id}}",
        "body": {
            "schoolId": 1,
            "address": "北京市朝阳区健康路88号食品产业园3号冷链库",
            "contact": "供应链经理刘女士",
            "email": "{{supplier_email}}",
            "rating": 4,
            "categories": ["蔬菜", "肉禽蛋", "冷链食品"],
        },
        "tests": [
            ("供应商编辑：ID 与评分返回正确", "pm.expect(Number(__json.data.id)).to.equal(Number(pm.variables.get('supplier_id'))); pm.expect(Number(__json.data.rating)).to.equal(4)"),
        ],
    },
    {
        "name": "新增动物检疫合格证",
        "method": "POST",
        "path": "/school/inventory/suppliers/{{supplier_id}}/certificates?schoolId=1",
        "body": {
            "type": "动物检疫合格证",
            "number": "DWJY{{test_batch}}",
            "authority": "北京市农业农村局动物卫生监督所",
            "expireAt": "2027-09-30",
            "imageUrl": "https://example.invalid/supplier/animal-quarantine.jpg",
        },
        "tests": [("检疫证新增：ok=true", "pm.expect(__json.data.ok).to.equal(true)")],
    },
    {
        "name": "批量导入食品经营许可证与质检报告",
        "method": "POST",
        "path": "/school/inventory/suppliers/{{supplier_id}}/certificates/import?schoolId=1",
        "body": {
            "items": [
                {
                    "type": "食品经营许可证",
                    "number": "JY{{test_batch}}",
                    "authority": "北京市朝阳区市场监督管理局食品经营科",
                    "expireAt": "2029-06-30",
                    "imageUrl": "https://example.invalid/supplier/food-license.jpg",
                },
                {
                    "type": "质检报告",
                    "number": "ZJ{{test_batch}}",
                    "authority": "北京市农产品质量安全检测中心",
                    "expireAt": "2027-12-31",
                    "imageUrl": "https://example.invalid/supplier/quality-report.jpg",
                },
            ]
        },
        "tests": [("证件批量导入：count=2", "pm.expect(Number(__json.data.count)).to.equal(2)")],
    },
    {
        "name": "导出供应商证件 CSV",
        "method": "GET",
        "path": "/school/inventory/suppliers/{{supplier_id}}/certificates/export.csv?schoolId=1",
        "tests": [
            ("证件 CSV：包含四类证件与中文发证机关", "pm.expect(__json.data.csv).to.include('营业执照'); pm.expect(__json.data.csv).to.include('动物检疫合格证'); pm.expect(__json.data.csv).to.include('食品经营许可证'); pm.expect(__json.data.csv).to.include('质检报告'); pm.expect(__json.data.csv).to.include('北京市农产品质量安全检测中心')"),
        ],
    },
    {
        "name": "批量导入晨光粮油与绿源蔬菜供应商",
        "method": "POST",
        "path": "/school/inventory/suppliers/import?schoolId=1",
        "body": {
            "items": [
                {
                    "name": "晨光粮油配送中心（档案{{test_batch}}）",
                    "phone": "{{import_phone_one}}",
                    "address": "北京市丰台区丰益路16号粮油仓储区",
                    "contact": "业务主管周先生",
                    "email": "{{import_email_one}}",
                    "enabled": True,
                    "rating": 4,
                    "categories": ["米面粮油", "调味品"],
                },
                {
                    "name": "绿源蔬菜专业合作社（档案{{test_batch}}）",
                    "phone": "{{import_phone_two}}",
                    "address": "北京市顺义区李桥镇绿色农业园6号",
                    "contact": "合作社负责人赵女士",
                    "email": "{{import_email_two}}",
                    "enabled": True,
                    "rating": 5,
                    "categories": ["蔬菜", "水果"],
                },
            ]
        },
        "tests": [("供应商批量导入：count=2", "pm.expect(Number(__json.data.count)).to.equal(2)")],
    },
    {
        "name": "按名称检索本轮主供应商",
        "method": "GET",
        "path": "/school/inventory/suppliers?schoolId=1&q=华丰绿色食材配送有限公司&page=1&pageSize=20",
        "tests": [
            ("名称检索：精确包含本轮供应商", "const id=Number(pm.variables.get('supplier_id')); const row=__json.data.items.find(function(x){return Number(x.id)===id;}); pm.expect(row).to.exist; pm.expect(row.contact).to.equal('供应链经理刘女士'); pm.expect(Number(row.rating)).to.equal(4); pm.expect(row.categories).to.include('冷链食品')"),
        ],
    },
    {
        "name": "批量停用本轮主供应商",
        "method": "POST",
        "path": "/school/inventory/suppliers/enable/batch",
        "body": {"schoolId": 1, "ids": ["{{supplier_id}}"], "enabled": False},
        "tests": [("批量停用：count=1", "pm.expect(Number(__json.data.count)).to.equal(1)")],
    },
    {
        "name": "回查供应商停用状态",
        "method": "GET",
        "path": "/school/inventory/suppliers/detail?id={{supplier_id}}&schoolId=1",
        "tests": [("停用回查：enabled 数值布尔为 0", "pm.expect(Number(__json.data.enabled)).to.equal(0)")],
    },
    {
        "name": "重新启用本轮主供应商",
        "method": "POST",
        "path": "/school/inventory/suppliers/enable/batch",
        "body": {"schoolId": 1, "ids": ["{{supplier_id}}"], "enabled": True},
        "tests": [("重新启用：count=1", "pm.expect(Number(__json.data.count)).to.equal(1)")],
    },
    {
        "name": "读取供应商关联汇总",
        "method": "GET",
        "path": "/school/inventory/suppliers/summary?id={{supplier_id}}&schoolId=1",
        "tests": [("供应商汇总：商品和入库字段均为数组", "pm.expect(__json.data.products).to.be.an('array'); pm.expect(__json.data.inbound).to.be.an('array')")],
    },
    {
        "name": "导出供应商 CSV",
        "method": "GET",
        "path": "/school/inventory/suppliers/export.csv?schoolId=1",
        "tests": [
            ("供应商 CSV：包含三家本轮真实中文主体", "pm.expect(__json.data.csv).to.include('华丰绿色食材配送有限公司（档案' + pm.variables.get('test_batch') + '）'); pm.expect(__json.data.csv).to.include('晨光粮油配送中心（档案' + pm.variables.get('test_batch') + '）'); pm.expect(__json.data.csv).to.include('绿源蔬菜专业合作社（档案' + pm.variables.get('test_batch') + '）')"),
        ],
    },
    {
        "name": "最终回查主供应商和全部证件",
        "method": "GET",
        "path": "/school/inventory/suppliers/detail?id={{supplier_id}}&schoolId=1",
        "tests": [
            ("最终详情：启用、评分和联系方式正确", "pm.expect(Number(__json.data.enabled)).to.equal(1); pm.expect(Number(__json.data.rating)).to.equal(4); pm.expect(__json.data.contact).to.equal('供应链经理刘女士'); pm.expect(__json.data.address).to.include('3号冷链库')"),
            ("最终详情：营业执照、质检与检疫摘要均存在", "pm.expect(__json.data.businessLicense).to.exist; pm.expect(__json.data.qcReport).to.exist; pm.expect(__json.data.animalCert).to.exist"),
        ],
    },
]


def main() -> None:
    api = shared.Apifox()
    by_name = {item["name"]: item for item in api.scenarios()}
    source = by_name["S00-环境与认证（双库）"]
    source_data = api.scenario(int(source["id"]))
    loop_template = source_data["steps"][0]
    login_template = loop_template["children"][0]
    request_template = loop_template["children"][1]

    current = by_name.get(NAME)
    scenario_id = int(current["id"]) if current else api.duplicate(int(source["id"]))
    scenario = api.scenario(scenario_id)
    scenario.update({"name": NAME, "description": DESCRIPTION, "folderId": shared.FOLDER_ID, "ordering": 110})
    loop = copy.deepcopy(loop_template)
    loop["id"] = shared.new_id()
    loop["number"] = 1
    login = shared.make_login(login_template, PREFIX)
    login_pre = login["customHttpRequest"]["preProcessors"][0]["data"]
    login["customHttpRequest"]["preProcessors"][0]["data"] = (
        login_pre
        + "const __stamp = '20260926' + String(Date.now()).slice(-6);\n"
        + "const __tail = String(Date.now()).slice(-8);\n"
        + "pm.variables.set('test_batch', __stamp);\n"
        + "pm.variables.set('supplier_phone', '138' + __tail);\n"
        + "pm.variables.set('import_phone_one', '139' + __tail);\n"
        + "pm.variables.set('import_phone_two', '137' + __tail);\n"
        + "pm.variables.set('supplier_email', 'caigou' + __tail + '@huafeng-food.example');\n"
        + "pm.variables.set('import_email_one', 'yewu' + __tail + '@chenguang-food.example');\n"
        + "pm.variables.set('import_email_two', 'hezuo' + __tail + '@lvyuan-coop.example');\n"
    )
    loop["children"] = [login]
    for number, operation in enumerate(OPERATIONS, start=2):
        step = shared.make_request(request_template, **operation)
        step["number"] = number
        loop["children"].append(step)
    scenario["steps"] = [loop]
    api.save(scenario)

    saved = api.scenario(scenario_id)
    requests = shared.flatten_requests(saved["steps"])
    business = [request for request in requests if request.get("path") != "{{base_url}}/auth/login"]
    if len(business) != len(OPERATIONS):
        raise RuntimeError(f"{NAME}: expected {len(OPERATIONS)} business requests, got {len(business)}")
    if not all(shared.request_has_auditable_evidence(request) for request in requests):
        raise RuntimeError(f"{NAME}: one or more requests lack auditable evidence")

    suite = api.test_suite()
    existing = [item for item in suite.get("items", []) if item.get("name") != NAME]
    existing.append({
        "id": shared.new_id(),
        "name": NAME,
        "type": "STATIC_TEST_SCENARIO",
        "testScenarios": [{"id": scenario_id, "options": {}}],
        "options": {},
    })
    suite["items"] = existing
    suite["description"] = (
        "学校端 S00-S10 双库兼容一键串行入口。MySQL 仅允许 foodsafe_test，达梦仅允许 WWWWEB。"
        "写接口必须接口回查并与数据库原表证据合并；删除、设备回调和 SSE 默认关闭。"
    )
    suite.setdefault("options", {})["runMode"] = "serial"
    api.save_test_suite(suite)
    saved_suite = api.test_suite()
    linked = [item["testScenarios"][0]["id"] for item in saved_suite["items"]]
    if scenario_id not in linked:
        raise RuntimeError("S10 was not linked into the one-click test suite")
    print(f"{NAME}: id={scenario_id}, operations={len(business)}, totalRequests={len(requests)}")
    print(f"一键测试-安全入口: scenarios={len(linked)}, suiteId={shared.TEST_SUITE_ID}")


if __name__ == "__main__":
    main()
