# -*- coding: utf-8 -*-
"""运营端（operator 端口）子角色权限与账号管理测试。"""
from __future__ import annotations

from fastapi.testclient import TestClient


def login(client: TestClient, username: str, password: str = "123456") -> str:
    res = client.post("/auth/login", json={"username": username, "password": password})
    assert res.status_code == 200, res.text
    return res.json()["token"]


def auth(token: str) -> dict:
    return {"Authorization": f"Bearer {token}"}


def user_id_by_username(client: TestClient, token: str, username: str) -> str:
    users = client.get("/admin/users", headers=auth(token)).json()
    return next(u["id"] for u in users if u["username"] == username)


def select_identity(client: TestClient, token: str, port: str) -> str:
    """把中性令牌切换到指定端口身份，返回绑定身份的令牌。"""
    body = client.post("/auth/login", json={"username": "pine", "password": "123456"}).json()
    ident = next(i for i in body["identities"] if i["port"] == port)["id"]
    sel = client.post(
        "/auth/select-identity", headers=auth(token), json={"identity_id": ident}
    ).json()
    return sel["token"]


def test_operator_admin_cannot_escalate_to_super_admin(client):
    # 管理员不可创建/提升 超管/管理员（特权角色）
    admin_t = login(client, "op_admin")
    res = client.post(
        "/admin/users",
        headers=auth(admin_t),
        json={"username": "13800001111", "password": "123456",
              "role": "operator", "sub_role": "op_super_admin"},
    )
    assert res.status_code == 403
    # 管理员可创建普通运营账号（客服）
    ok = client.post(
        "/admin/users",
        headers=auth(admin_t),
        json={"username": "13800002222", "password": "123456",
              "role": "operator", "sub_role": "op_customer_service"},
    )
    assert ok.status_code == 200
    # 管理员把某账号提升为超管 → 403
    target_id = user_id_by_username(client, admin_t, "13800002222")
    up = client.post(
        f"/admin/users/{target_id}/role",
        headers=auth(admin_t),
        json={"role": "operator", "sub_role": "op_super_admin"},
    )
    assert up.status_code == 403


def test_operator_cs_cannot_change_config(client):
    # 客服可建任务/服务商，但不可改系统配置
    cs_t = login(client, "op_cs")
    assert (
        client.put("/admin/config/platform.fee.task",
                   headers=auth(cs_t), json={"value": "0.01"}).status_code == 403
    )
    assert client.post("/admin/tasks", headers=auth(cs_t),
                       json={"title": "客服建任务"}).status_code == 200


def test_operator_finance_cannot_manage_tasks(client):
    # 财务可看结算，但不可建任务
    fin_t = login(client, "op_fin")
    assert (
        client.post("/admin/tasks", headers=auth(fin_t),
                    json={"title": "财务建任务"}).status_code == 403
    )
    assert client.get("/operator/settlements", headers=auth(fin_t)).status_code == 200


def test_operator_invalid_role_combo_rejected(client):
    # 非法/跨界角色组合被白名单拒绝
    admin_t = login(client, "op_admin")
    res = client.post(
        "/admin/users",
        headers=auth(admin_t),
        json={"username": "13800003333", "password": "123456",
              "role": "operator", "sub_role": "gov_province"},
    )
    assert res.status_code == 400


def test_operator_grant_perm_only_super_admin(client):
    # 配置角色权限仅超管可用
    admin_t = login(client, "op_admin")
    assert (
        client.post("/admin/roles/operator%7Cop_admin/permissions",
                    headers=auth(admin_t), json={"permissions": []}).status_code == 403
    )
    # pine 以超管身份可配置
    neutral = login(client, "pine")
    sa_t = select_identity(client, neutral, "operator")
    ok = client.post(
        "/admin/roles/operator%7Cop_analyst/permissions",
        headers=auth(sa_t), json={"permissions": ["menu:audit", "action:data.export"]},
    )
    assert ok.status_code == 200
    assert "menu:audit" in ok.json()["permissions"]


def test_operator_role_change_takes_effect(client):
    # 改角色后：令牌失效 + 身份同步，重新登录体现新角色权限
    admin_t = login(client, "op_admin")
    created = client.post(
        "/admin/users",
        headers=auth(admin_t),
        json={"username": "13800004444", "password": "123456",
              "role": "operator", "sub_role": "op_customer_service"},
    ).json()
    # 该账号现可建任务（客服有 task.manage）
    cs_t = login(client, "13800004444")
    assert client.post("/admin/tasks", headers=auth(cs_t),
                       json={"title": "t"}).status_code == 200
    # 管理员将其改为分析师（无 task.manage）
    target_id = user_id_by_username(client, admin_t, "13800004444")
    up = client.post(
        f"/admin/users/{target_id}/role",
        headers=auth(admin_t),
        json={"role": "operator", "sub_role": "op_analyst"},
    )
    assert up.status_code == 200
    # 旧令牌已失效
    assert client.get("/admin/users", headers=auth(cs_t)).status_code == 401
    # 新登录为分析师：不可建任务
    an_t = login(client, "13800004444")
    assert client.post("/admin/tasks", headers=auth(an_t),
                       json={"title": "t2"}).status_code == 403
