"""角色权限模块测试 — 模块/动作/权限配置CRUD"""
import pytest
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from tests.conftest import create_test_user, get_token_for_user, auth_header


class TestPermissionModules:
    """模块和动作定义测试"""

    BASE = "/api/cma/permissions"

    def test_list_modules(self, client: TestClient, db: Session):
        """获取模块和动作定义"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.get(f"{self.BASE}/modules", headers=auth_header(token))
        assert resp.status_code == 200
        data = resp.json()
        assert "modules" in data
        assert "actions" in data
        assert "roles" in data
        assert len(data["modules"]) > 0
        assert len(data["actions"]) > 0
        # 检查是否包含核心模块
        module_keys = [m["key"] for m in data["modules"]]
        assert "dashboard" in module_keys
        assert "kpis" in module_keys
        assert "budget" in module_keys


class TestPermissionConfig:
    """权限配置CRUD测试"""

    BASE = "/api/cma/permissions"

    def test_get_config_creates_defaults(self, client: TestClient, db: Session):
        """首次获取自动创建默认配置"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.get(f"{self.BASE}/config", headers=auth_header(token))
        assert resp.status_code == 200
        data = resp.json()
        assert "route_permissions" in data
        assert "action_permissions" in data
        assert "ceo" in data["route_permissions"]
        assert "finance" in data["route_permissions"]

    def test_update_route_permissions(self, client: TestClient, db: Session):
        """更新路由权限"""
        create_test_user(db)
        token = get_token_for_user(client)

        new_route = {
            "ceo": ["dashboard", "kpis", "maps"],
            "finance": ["dashboard", "kpis"],
        }
        resp = client.put(
            f"{self.BASE}/config",
            headers=auth_header(token),
            json={"route_permissions": new_route},
        )
        assert resp.status_code == 200
        assert resp.json()["message"] == "权限配置已更新"

        # 验证已更新
        get_resp = client.get(f"{self.BASE}/config", headers=auth_header(token))
        assert get_resp.json()["route_permissions"] == new_route

    def test_update_action_permissions(self, client: TestClient, db: Session):
        """更新动作权限"""
        create_test_user(db)
        token = get_token_for_user(client)

        new_actions = {
            "ceo": ["read", "approve", "delete"],
            "it": ["read", "write", "admin"],
        }
        resp = client.put(
            f"{self.BASE}/config",
            headers=auth_header(token),
            json={"action_permissions": new_actions},
        )
        assert resp.status_code == 200

        get_resp = client.get(f"{self.BASE}/config", headers=auth_header(token))
        assert get_resp.json()["action_permissions"] == new_actions

    def test_update_both_simultaneously(self, client: TestClient, db: Session):
        """同时更新路由和动作权限"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.put(
            f"{self.BASE}/config",
            headers=auth_header(token),
            json={
                "route_permissions": {"ceo": ["dashboard"]},
                "action_permissions": {"ceo": ["read"]},
            },
        )
        assert resp.status_code == 200

        data = client.get(f"{self.BASE}/config", headers=auth_header(token)).json()
        assert data["route_permissions"] == {"ceo": ["dashboard"]}
        assert data["action_permissions"] == {"ceo": ["read"]}
