import pytest
import allure
import logging
import requests
import json
import time
from dulizhan.library.BusinessKw.JoyHub.DeptManage import DeptManage

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


@allure.feature("管理后台 - 部门管理模块")
class TestDeptManage:
    token_set = False
    dept_id = None

    @classmethod
    def setup_class(cls):
        """在整个测试类开始时登录一次，所有测试用例共享token"""
        logging.info("=============================================")
        logging.info("=========== 开始登录，获取Token ============")
        logging.info("=============================================")
        
        cls.test_case = DeptManage()
        username = "joytest"
        password = "Zhou1599"

        cls.test_case._clear_user_fingerprint(username)

        url = "https://joyhub-website-manager-api-test.best-envision.com/admin-api/system/auth/login-dev"
        payload = {"username": username, "password": password}
        headers = {'Content-Type': 'application/json', 'tenant-id': '126'}

        try:
            response = requests.post(url, json=payload, headers=headers, verify=False, timeout=10)
            login_response = response.json()

            if login_response and login_response.get('code') == 0:
                token = login_response.get('data', {}).get('accessToken', '')
                if token:
                    cls.test_case.set_joyhub_token(token)
                    cls.token_set = True
                    logging.info("登录成功，获取到Token: {}...".format(token[:20]))
                else:
                    logging.warning("登录成功但未获取到Token")
            else:
                logging.error("登录失败: {}".format(login_response))
                logging.warning("如果是指纹锁问题，请联系管理员解除设备限制")
        except Exception as e:
            logging.error("登录异常: {}".format(str(e)))

    def setup_method(self):
        """每个测试方法执行前检查token"""
        if not self.token_set:
            pytest.skip("Token未设置，跳过测试")

    @allure.story("验证登录接口")
    @allure.title("测试登录接口")
    def test_joyhub_login_post(self):
        """测试登录接口"""
        assert self.token_set, "登录失败"
        logging.info("登录接口验证通过")

    @allure.story("验证获取部门列表")
    @allure.title("测试获取部门列表接口")
    def test_joyhub_dept_list_get(self):
        """测试获取部门列表接口"""
        with allure.step("1. 调用接口"):
            resp = self.test_case.kw_joyhub_dept_list_get()
            allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("2. 验证响应"):
            assert resp is not None, "响应为空"
            assert "code" in resp, "响应中缺少code字段"
            assert resp["code"] == 0, f"请求失败，code={resp.get('code')}"
            assert "data" in resp, "响应中缺少data字段"
            assert isinstance(resp["data"], list), "data字段应为列表类型"
            logging.info("获取部门列表接口验证通过")

    @allure.story("验证创建部门")
    @allure.title("测试创建部门接口")
    def test_joyhub_dept_create_post(self):
        """测试创建部门接口"""
        with allure.step("1. 准备请求参数"):
            timestamp = int(time.time())
            params = {
                "name": f"测试部门_{timestamp}",
                "code": f"test_dept_{timestamp}",
                "sort": timestamp,
                "status": 1,
                "phone": "13900139000",
                "email": f"test_dept_{timestamp}@example.com"
            }
            allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT)
        
        with allure.step("2. 调用接口"):
            resp = self.test_case.kw_joyhub_dept_create_post(**params)
            allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("3. 验证响应"):
            assert resp is not None, "响应为空"
            assert "code" in resp, "响应中缺少code字段"
            assert resp["code"] == 0, f"请求失败，code={resp.get('code')}"
            assert "data" in resp, "响应中缺少data字段"
            assert isinstance(resp["data"], int), "data字段应为整数类型（部门ID）"
            TestDeptManage.dept_id = resp["data"]
            logging.info(f"创建部门接口验证通过，部门ID: {TestDeptManage.dept_id}")

    @allure.story("验证获得部门信息")
    @allure.title("测试获得部门信息接口")
    def test_joyhub_dept_get_get(self):
        """测试获得部门信息接口"""
        if not TestDeptManage.dept_id:
            pytest.skip("没有可用的部门ID，跳过测试")
        
        with allure.step("1. 调用接口"):
            resp = self.test_case.kw_joyhub_dept_get_get(dept_id=TestDeptManage.dept_id)
            allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("2. 验证响应"):
            assert resp is not None, "响应为空"
            assert "code" in resp, "响应中缺少code字段"
            assert resp["code"] == 0, f"请求失败，code={resp.get('code')}"
            assert "data" in resp, "响应中缺少data字段"
            assert "id" in resp["data"], "响应中缺少id字段"
            assert resp["data"]["id"] == TestDeptManage.dept_id, "返回的部门ID与请求不一致"
            logging.info("获得部门信息接口验证通过")

    @allure.story("验证更新部门")
    @allure.title("测试更新部门接口")
    def test_joyhub_dept_update_put(self):
        """测试更新部门接口"""
        if not TestDeptManage.dept_id:
            pytest.skip("没有可用的部门ID，跳过测试")
        
        with allure.step("1. 准备更新参数"):
            timestamp = int(time.time())
            params = {
                "dept_id": TestDeptManage.dept_id,
                "name": f"测试部门_修改_{timestamp}",
                "sort": timestamp,
                "status": 1,
                "phone": "13900139999",
                "email": f"test_dept_updated_{timestamp}@example.com"
            }
            allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT)
        
        with allure.step("2. 调用接口"):
            resp = self.test_case.kw_joyhub_dept_update_put(**params)
            allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("3. 验证响应"):
            assert resp is not None, "响应为空"
            assert "code" in resp, "响应中缺少code字段"
            assert resp["code"] == 0, f"请求失败，code={resp.get('code')}"
            assert "data" in resp, "响应中缺少data字段"
            assert resp["data"] is True, "更新部门失败"
            logging.info("更新部门接口验证通过")

    @allure.story("验证删除部门")
    @allure.title("测试删除部门接口")
    def test_joyhub_dept_delete_post(self):
        """测试删除部门接口"""
        with allure.step("1. 先创建一个测试部门"):
            timestamp = int(time.time())
            create_resp = self.test_case.kw_joyhub_dept_create_post(
                name=f"删除测试部门_{timestamp}",
                sort=999,
                status=1
            )
            dept_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None
            
            if not dept_id:
                pytest.skip("创建测试部门失败，跳过删除测试")
            
            allure.attach(json.dumps({"id": dept_id}, ensure_ascii=False), name="待删除部门ID", attachment_type=allure.attachment_type.TEXT)
        
        with allure.step("2. 调用删除接口"):
            resp = self.test_case.kw_joyhub_dept_delete_post(dept_id=dept_id)
            allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("3. 验证响应"):
            assert resp is not None, "响应为空"
            assert "code" in resp, "响应中缺少code字段"
            if resp["code"] == 1002005004:
                logging.warning(f"部门已被引用无法删除，code={resp.get('code')}，msg={resp.get('msg')}")
                pytest.skip("部门已被其他数据引用，跳过删除测试")
            assert resp["code"] == 0, f"请求失败，code={resp.get('code')}"
            assert "data" in resp, "响应中缺少data字段"
            assert resp["data"] is True, "删除部门失败"
            logging.info("删除部门接口验证通过")

    @allure.story("验证批量删除部门")
    @allure.title("测试批量删除部门接口")
    def test_joyhub_dept_delete_list_post(self):
        """测试批量删除部门接口"""
        with allure.step("1. 先创建两个测试部门"):
            timestamp = int(time.time())
            dept_ids = []
            
            for i in range(2):
                create_resp = self.test_case.kw_joyhub_dept_create_post(
                    name=f"批量删除测试部门_{timestamp}_{i}",
                    sort=888 + i,
                    status=1
                )
                if create_resp and create_resp.get("code") == 0:
                    dept_ids.append(create_resp.get("data"))
            
            if len(dept_ids) < 2:
                pytest.skip("创建测试部门失败，跳过批量删除测试")
            
            allure.attach(json.dumps({"ids": dept_ids}, ensure_ascii=False), name="待删除部门ID列表", attachment_type=allure.attachment_type.TEXT)
        
        with allure.step("2. 调用批量删除接口"):
            resp = self.test_case.kw_joyhub_dept_delete_list_post(ids=dept_ids)
            allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("3. 验证响应"):
            assert resp is not None, "响应为空"
            assert "code" in resp, "响应中缺少code字段"
            if resp["code"] == 1002005004:
                logging.warning(f"部门已被引用无法删除，code={resp.get('code')}，msg={resp.get('msg')}")
                pytest.skip("部门已被其他数据引用，跳过批量删除测试")
            assert resp["code"] == 0, f"请求失败，code={resp.get('code')}"
            assert "data" in resp, "响应中缺少data字段"
            assert resp["data"] is True, "批量删除部门失败"
            logging.info("批量删除部门接口验证通过")

    @allure.story("验证获取部门精简信息列表")
    @allure.title("测试获取部门精简信息列表接口")
    def test_joyhub_dept_list_all_simple_get(self):
        """测试获取部门精简信息列表接口"""
        with allure.step("1. 调用接口"):
            resp = self.test_case.kw_joyhub_dept_list_all_simple_get()
            allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("2. 验证响应"):
            assert resp is not None, "响应为空"
            assert "code" in resp, "响应中缺少code字段"
            assert resp["code"] == 0, f"请求失败，code={resp.get('code')}"
            assert "data" in resp, "响应中缺少data字段"
            assert isinstance(resp["data"], list), "data字段应为列表类型"
            logging.info("获取部门精简信息列表接口验证通过")

    @allure.story("验证获取部门精简信息列表(simple-list)")
    @allure.title("测试获取部门精简信息列表接口(simple-list)")
    def test_joyhub_dept_simple_list_get(self):
        """测试获取部门精简信息列表接口(simple-list)"""
        with allure.step("1. 调用接口"):
            resp = self.test_case.kw_joyhub_dept_simple_list_get()
            allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("2. 验证响应"):
            assert resp is not None, "响应为空"
            assert "code" in resp, "响应中缺少code字段"
            assert resp["code"] == 0, f"请求失败，code={resp.get('code')}"
            assert "data" in resp, "响应中缺少data字段"
            assert isinstance(resp["data"], list), "data字段应为列表类型"
            logging.info("获取部门精简信息列表(simple-list)接口验证通过")
