#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""权限实测（第二轮）：临时实例 + 注入会话，真 HTTP 打 /api/sandept，断言内容。"""
import importlib, threading, time, sys, json, urllib.request
SDIR = '/Users/liuxinyuan/Desktop/Hermes输出-工作类/脚本'
sys.path.insert(0, SDIR)
svc = importlib.import_module('销售工作台服务')

TOK = {'chenxizi': 'p2-cxz', 'renxin': 'p2-rx', 'wuyun': 'p2-wy', 'yexinfu': 'p2-yxf',
       'liuxin': 'p2-lx', 'liuziyan': 'p2-lzy', 'admin': 'p2-adm'}
ids = {
    'chenxizi': {'name': '陈溪子', 'role': 'sales', 'dept': '诊断原料销售拓展部', 'line': 'da'},
    'renxin':   {'name': '任鑫',   'role': 'sales', 'dept': '诊断原料销售拓展部', 'line': 'da'},
    'wuyun':    {'name': '吴云',   'role': 'manager', 'dept': '生命科学销售部', 'line': 'ls'},
    'yexinfu':  {'name': '叶信福', 'role': 'sales', 'dept': '生命科学销售部', 'line': 'ls'},
    'liuxin':   {'name': '刘欣',   'role': 'manager', 'dept': '诊断原料销售拓展部', 'line': 'da'},
    'liuziyan': {'name': '刘子研', 'role': 'sales', 'dept': '诊断原料大客户销售部', 'line': 'da'},
    'admin':    {'name': '超级管理员', 'role': 'admin', 'dept': '诊断原料销售部', 'line': 'da'},
}
for k, t in TOK.items():
    svc.AUTH_SESSIONS[t] = dict(ids[k], expire_at=time.time() + 900)

srv = svc.ThreadingHTTPServer(('127.0.0.1', 8801), svc.Handler)
threading.Thread(target=srv.serve_forever, daemon=True).start()
time.sleep(0.9)
BASE = 'http://127.0.0.1:8801'

def call(who):
    req = urllib.request.Request(BASE + '/api/sandept', headers={'Authorization': 'Bearer ' + TOK[who]})
    with urllib.request.urlopen(req, timeout=25) as r:
        return r.status, json.loads(r.read().decode('utf-8'))

def amt_of(data, name):
    return round(sum(c.get('amt') or 0 for c in (data.get('customers') or []) if c.get('cust') == name), 2)

def own_total(data):
    return round(sum(c.get('amt') or 0 for c in (data.get('customers') or [])), 2)

free = ['杭州逸检汇牧智能科技有限公司', '翊新诊断技术（苏州）有限公司', '武汉锦灵生物科技有限公司',
        '集美大学', '复旦大学', '苏州大学']          # 46 家无归属样本
ok = True
res = {}
try:
    for who in TOK:
        st, j = call(who)
        d = j['data']
        res[who] = (j.get('scope'), len(d.get('customers') or []), own_total(d),
                    {n: amt_of(d, n) for n in
                     ['浙江大学', '潮州凯普生物化学有限公司', '优联瑞康(上海)基因科技有限公司',
                      '横渠诺优生物科技（南通）有限公司上海分公司', '成都中医药大学',
                      '成都泓盛生物有限公司'] if amt_of(d, n) > 0})
        print(f"--- {who}({ids[who]['name']},{ids[who]['role']}) scope={j.get('scope')} rows={res[who][1]} own={res[who][2]} 命中={res[who][3]} ---")

    # ① 新归属人看得见 / 原归属人看不见
    st, j = call('wuyun');   d = j['data']
    assert amt_of(d, '浙江大学') == 11.04, f"吴云 应见 浙江大学 11.04，实={amt_of(d,'浙江大学')}"
    st, j = call('yexinfu'); d = j['data']
    assert amt_of(d, '浙江大学') == 0, "叶信福 不应再看到 浙江大学"
    assert amt_of(d, '浙江农林大学') == 0, "叶信福 不应再看到 浙江农林大学"
    assert amt_of(d, '杭州奕文生物科技有限公司') == 0 and amt_of(d, '浙江中医药大学') == 0
    print("  ✅ 吴云 可见 浙江大学(11.04)；叶信福 不再可见其 4 家（浙大/农林/奕文/中医药）")

    # ② 陈溪子 / 任鑫 互换
    st, j = call('chenxizi'); d = j['data']
    assert amt_of(d, '成都中医药大学') == 0.2 and amt_of(d, '成都泓盛生物有限公司') == 0, "陈溪子 归属互换失败"
    st, j = call('renxin'); d = j['data']
    assert amt_of(d, '成都泓盛生物有限公司') == 0.91, f"任鑫 应见 成都泓盛 0.91，实={amt_of(d,'成都泓盛生物有限公司')}"
    print("  ✅ 陈溪子 见 成都中医药大学(0.2)、不见 成都泓盛；任鑫 见 成都泓盛(0.91)")

    # ③ 管理者 刘欣
    st, j = call('liuxin'); d = j['data']
    assert j.get('scope') == 'own', f"刘欣(manager) scope 应为 own，实={j.get('scope')}"
    assert amt_of(d, '优联瑞康(上海)基因科技有限公司') == 1.27
    assert amt_of(d, '横渠诺优生物科技（南通）有限公司上海分公司') == 0.36
    print("  ✅ 刘欣(部门经理) 可见 优联瑞康(1.27) + 横渠诺优(0.36)")

    # ④ 无归属客户：普通 sales 一个都看不到；admin 全见
    for who in ('chenxizi', 'renxin', 'wuyun', 'yexinfu', 'liuxin', 'liuziyan'):
        st, j = call(who); d = j['data']
        hit = [n for n in free if amt_of(d, n) > 0]
        assert not hit, f"{who} 不应看到无归属客户 {hit}"
    st, j = call('admin'); d = j['data']
    l = len(d.get('customers') or [])
    assert l == 2137, f"admin 应见 2137 行，实={l}"
    for n in free:
        assert amt_of(d, n) > 0, f"admin 应见无归属 {n}"
    print(f"  ✅ 无归属 46 家：普通 sales/manager 一律不可见；admin 全见 {len(d['customers'])} 行")

    # ⑤ 刘子研线回归
    st, j = call('liuziyan'); d = j['data']
    assert own_total(d) == 642.40, f"刘子研 customers 归集 {own_total(d)} != 642.40"
    spt = {r['sp']: round(sum(x.get('amt') or 0 for x in d['salespersons'] if x['sp'] == r['sp']), 2)
           for r in d['salespersons']}
    assert spt.get('刘子研') == 644.11, f"刘子研 salespersons {spt} != 644.11"
    print(f"  ✅ 刘子研 customers={own_total(d)} / salespersons={spt.get('刘子研')}")

    print("\nPERMISSION PROBE 2: ALL PASSED")
except AssertionError as e:
    ok = False
    print("PROBE FAIL:", e)
finally:
    srv.shutdown()
    for t in TOK.values():
        svc.AUTH_SESSIONS.pop(t, None)
sys.exit(0 if ok else 1)
