"""
网络工具箱 - 功能授权客户端模块
集成auth_system的授权验证逻辑
"""
import os
import json
import hashlib
import platform
import base64
import requests
import threading
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.exceptions import InvalidSignature

# ============ 产品配置 ============
PRODUCT_ID = 1  # 网络测试工具箱
PRODUCT_NAME = "网络测试工具箱"
SERVER_URL = "http://cas.netintmast.cn:9899"  # 授权API服务器地址

APP_DATA_DIR = os.path.join(os.getenv('APPDATA'), 'NetworkToolkit')
LICENSE_FILE = os.path.join(APP_DATA_DIR, 'license.dat')

# 嵌入的公钥（防止删除）
PUBLIC_KEY_PEM = b"""-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA15fFRK5JMl9J5PbJwCbl
XJ/CpizoDbMMSX8IHkn9Vzn3l4919jS4VzTmNauLQh4RajqKQ6aSpgwb0emoNXUq
TXuJ5YbKy0Iw0/mv0RZrZ2TYgKxaRJnNNB8tZzm+NUdwSMhU61gK5r3F3Yc7Yssn
H9miBbU3FCgv1CECCDHYVywwOO9Qt6+EL33nktZ5SsxwciON+iCYzKpATF5emDzn
rNpfIyMnsfy/W5e0Sm/aiLXduTsYm2rAZxdbtTYWm/UnVKXB8+kgkjZhbdBmFz6g
mqN2vm4YE/JVpcTxqUi0W/lXCI2Tk3YXkYELfUxX1kLX5SV+mNf0pA5L8qYNVvLK
gQIDAQAB
-----END PUBLIC KEY-----"""


def get_hwid():
    """
    生成基于CPU和磁盘序列号的唯一硬件ID
    返回SHA256哈希值
    """
    try:
        import wmi
        c = wmi.WMI()
        
        # 获取CPU ID
        cpu_info = c.Win32_Processor()[0]
        cpu_id = cpu_info.ProcessorId.strip()
        
        # 获取磁盘序列号（C:盘）
        disk_serial = "UNKNOWN_DISK"
        for disk in c.Win32_DiskDrive():
            if disk.SerialNumber:
                disk_serial = disk.SerialNumber.strip()
                break
                
        raw_id = f"{cpu_id}-{disk_serial}"
        return hashlib.sha256(raw_id.encode()).hexdigest().upper()
        
    except Exception as e:
        print(f"生成HWID错误: {e}")
        # 备用方案：使用主板和CPU信息
        try:
            import subprocess
            result = subprocess.check_output('wmic baseboard get serialnumber', shell=True).decode('gbk')
            baseboard_sn = result.split('\n')[1].strip()
            
            result = subprocess.check_output('wmic cpu get processorid', shell=True).decode('gbk')
            cpu_id = result.split('\n')[1].strip()
            
            hwid_str = f"{baseboard_sn}-{cpu_id}-{platform.node()}"
            return hashlib.sha256(hwid_str.encode()).hexdigest()[:32].upper()
        except:
            return "ERROR-GENERATING-HWID"


def verify_signature(public_key, data_dict, signature_b64):
    """验证数据的签名"""
    data_str = json.dumps(data_dict, sort_keys=True)
    signature = base64.b64decode(signature_b64)
    try:
        public_key.verify(
            signature,
            data_str.encode(),
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        )
        return True
    except InvalidSignature:
        return False


class LicenseManager:
    """授权管理器"""
    
    def __init__(self):
        self.hwid = get_hwid()
        self.is_activated = False
        self.license_info = {}
        self.public_key = serialization.load_pem_public_key(PUBLIC_KEY_PEM)
        
        # 启动时检查授权
        self.check_license()
    
    def check_license(self):
        """检查本地授权文件"""
        try:
            if os.path.exists(LICENSE_FILE):
                with open(LICENSE_FILE, 'r') as f:
                    license_obj = json.load(f)
                
                data = license_obj['data']
                signature = license_obj['signature']
                
                # 验证本地授权文件的签名
                if verify_signature(self.public_key, data, signature):
                    if data['hwid'] == self.hwid:
                        # 验证产品ID是否匹配
                        if data.get('product_id') == PRODUCT_ID:
                            self.license_info = data
                            # 与服务器验证
                            self.verify_with_server()
                        else:
                            print(f"授权产品不匹配: 期望 {PRODUCT_ID}, 实际 {data.get('product_id')}")
                    else:
                        print("授权HWID不匹配")
                else:
                    print("无效的签名")
        except Exception as e:
            print(f"授权检查失败: {e}")
    
    def verify_with_server(self):
        """与服务器验证授权是否仍然有效"""
        def _verify():
            try:
                resp = requests.post(f"{SERVER_URL}/verify_license", 
                                   json={"hwid": self.hwid, "product_id": PRODUCT_ID}, 
                                   timeout=3)
                if resp.status_code == 200:
                    self.is_activated = True
                elif resp.status_code == 403:
                    print("授权已被撤销，删除本地授权文件")
                    if os.path.exists(LICENSE_FILE):
                        os.remove(LICENSE_FILE)
                    self.is_activated = False
                else:
                    # 网络问题，使用本地授权
                    self.is_activated = True
            except requests.exceptions.RequestException:
                # 无法连接服务器，使用本地授权
                self.is_activated = True
        
        threading.Thread(target=_verify, daemon=True).start()
        # 默认信任本地授权
        self.is_activated = True
    
    def activate_online(self, callback_success=None, callback_error=None):
        """在线激活"""
        def _req():
            try:
                resp = requests.post(f"{SERVER_URL}/activate", 
                                   json={"hwid": self.hwid, "product_id": PRODUCT_ID}, 
                                   timeout=5)
                if resp.status_code == 200:
                    try:
                        data = resp.json()
                        
                        # 服务器返回的是扁平结构，需要构建为嵌套结构
                        # 必须保持字段顺序与服务器签名时一致！
                        license_data = {
                            "status": data.get('status'),
                            "hwid": data.get('hwid'),
                            "product_id": data.get('product_id'),
                            "timestamp": data.get('timestamp')
                        }
                        
                        license_file = {
                            "data": license_data,
                            "signature": data.get('signature')
                        }
                        
                        if not os.path.exists(APP_DATA_DIR):
                            os.makedirs(APP_DATA_DIR)
                        
                        with open(LICENSE_FILE, 'w') as f:
                            json.dump(license_file, f)
                        
                        self.is_activated = True
                        self.license_info = license_file['data']
                        
                        if callback_success:
                            callback_success()
                    except (ValueError, KeyError) as json_error:
                        if callback_error:
                            callback_error(f"服务器响应格式错误：{str(json_error)}\n响应内容：{resp.text[:200]}")
                else:
                    try:
                        err = resp.json().get('error', '未知错误')
                    except ValueError:
                        err = f"HTTP {resp.status_code} - {resp.text[:200]}"
                    if callback_error:
                        callback_error(f"服务器返回：{err}")
            except requests.exceptions.ConnectionError as conn_err:
                if callback_error:
                    callback_error(f"无法连接到服务器：{SERVER_URL}\n错误：{str(conn_err)}\n请检查:\n1. 服务器地址是否正确\n2. 网络连接是否正常\n3. 服务器9899端口是否开放")
            except requests.exceptions.Timeout:
                if callback_error:
                    callback_error(f"连接超时：服务器 {SERVER_URL} 无响应")
            except Exception as e:
                if callback_error:
                    callback_error(f"激活失败：{str(e)}")
        
        threading.Thread(target=_req, daemon=True).start()
    
    def import_license(self, filename, callback_success=None, callback_error=None):
        """导入离线授权文件"""
        try:
            with open(filename, 'r') as f:
                license_obj = json.load(f)
            
            data = license_obj['data']
            signature = license_obj['signature']
            
            # 验证签名
            if not verify_signature(self.public_key, data, signature):
                if callback_error:
                    callback_error("授权文件签名无效！")
                return
            
            # 验证HWID
            if data['hwid'] != self.hwid:
                if callback_error:
                    callback_error("授权文件与当前设备不匹配！")
                return
            
            # 验证产品ID
            if data.get('product_id') != PRODUCT_ID:
                if callback_error:
                    callback_error(f"授权文件产品不匹配！")
                return
            
            # 保存授权文件
            if not os.path.exists(APP_DATA_DIR):
                os.makedirs(APP_DATA_DIR)
            
            with open(LICENSE_FILE, 'w') as f:
                json.dump(license_obj, f)
            
            self.is_activated = True
            self.license_info = data
            
            if callback_success:
                callback_success()
                
        except Exception as e:
            if callback_error:
                callback_error(f"无效的授权文件：{e}")
    
    def get_status(self):
        """获取激活状态"""
        return {
            'is_activated': self.is_activated,
            'hwid': self.hwid,
            'license_info': self.license_info
        }
