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

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


@allure.feature("管理后台 - 用户个人中心模块")
class TestUserProfile:
    token_set = False
    original_password = "Zhou1599"
    test_password = "Aa123456"

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

        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))
        except Exception as e:
            logging.error("登录异常: {}".format(str(e)))

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

    @classmethod
    def teardown_class(cls):
        """测试类结束后，确保密码改回原密码"""
        logging.info("=============================================")
        logging.info("=========== 测试结束，恢复原密码 ============")
        logging.info("=============================================")
        
        try:
            # 先用测试密码登录
            url = "https://joyhub-website-manager-api-test.best-envision.com/admin-api/system/auth/login-dev"
            payload = {"username": "joytest", "password": cls.test_password}
            headers = {'Content-Type': 'application/json', 'tenant-id': '126'}
            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)
                    resp = cls.test_case.kw_joyhub_user_profile_update_password_put(
                        old_password=cls.test_password,
                        new_password=cls.original_password
                    )
                    if resp and resp.get('code') == 0:
                        logging.info("密码已恢复为原密码: {}".format(cls.original_password))
                    else:
                        logging.warning("恢复原密码失败: {}".format(resp))
        except Exception as e:
            logging.error("恢复原密码异常: {}".format(str(e)))

    @allure.story("验证获得登录用户信息")
    @allure.title("测试获得登录用户信息接口")
    def test_joyhub_user_profile_get_get(self):
        """测试获得登录用户信息接口"""
        with allure.step("1. 调用接口"):
            resp = self.test_case.kw_joyhub_user_profile_get_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 "id" in resp["data"], "响应中缺少id字段"
            assert "username" in resp["data"], "响应中缺少username字段"
            logging.info("获得登录用户信息接口验证通过")

    @allure.story("验证修改用户个人信息")
    @allure.title("测试修改用户个人信息接口")
    def test_joyhub_user_profile_update_put(self):
        """测试修改用户个人信息接口"""
        with allure.step("1. 先获取当前用户信息"):
            get_resp = self.test_case.kw_joyhub_user_profile_get_get()
            if not get_resp or get_resp.get('code') != 0:
                pytest.skip("获取用户信息失败，跳过修改测试")
            
            original_data = get_resp.get('data', {})
            allure.attach(json.dumps(original_data, ensure_ascii=False, indent=2), name="原始用户信息", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("2. 准备修改参数"):
            params = {
                "nickname": "测试用户_修改",
                "email": "test_updated@example.com",
                "mobile": "13900139000",
                "sex": 1
            }
            allure.attach(json.dumps(params, ensure_ascii=False), name="修改参数", attachment_type=allure.attachment_type.TEXT)
        
        with allure.step("3. 调用修改接口"):
            resp = self.test_case.kw_joyhub_user_profile_update_put(**params)
            allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
        
        with allure.step("4. 验证响应"):
            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("修改用户个人信息接口验证通过")
        
        with allure.step("5. 恢复原始信息"):
            # 恢复原始信息
            restore_params = {
                "nickname": original_data.get("nickname", ""),
                "email": original_data.get("email", ""),
                "mobile": original_data.get("mobile", ""),
                "sex": original_data.get("sex"),
                "avatar": original_data.get("avatar", "")
            }
            restore_resp = self.test_case.kw_joyhub_user_profile_update_put(**restore_params)
            if restore_resp and restore_resp.get('code') == 0:
                logging.info("用户信息已恢复")
            else:
                logging.warning("恢复用户信息失败: {}".format(restore_resp))

    @allure.story("验证修改用户个人密码")
    @allure.title("测试修改用户个人密码接口")
    def test_joyhub_user_profile_update_password_put(self):
        """测试修改用户个人密码接口"""
        with allure.step("1. 准备修改密码参数"):
            params = {
                "old_password": self.original_password,
                "new_password": self.test_password
            }
            allure.attach(json.dumps({"oldPassword": "******", "newPassword": "******"}, ensure_ascii=False), name="修改参数", attachment_type=allure.attachment_type.TEXT)
        
        with allure.step("2. 调用修改密码接口"):
            resp = self.test_case.kw_joyhub_user_profile_update_password_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("修改用户个人密码接口验证通过，密码已修改为: {}".format(self.test_password))
            logging.info("注意：测试类结束后将自动恢复原密码: {}".format(self.original_password))
