"""
MemoryX Client - 核心客户端
"""

import json
import hashlib
import platform
import socket
import uuid
from typing import Optional, List, Dict, Any
from urllib.request import Request, urlopen
from urllib.error import HTTPError


class MemoryXClient:
    """MemoryX 记忆客户端"""
    
    DEFAULT_BASE_URL = "http://t0ken.ai/api"
    
    def __init__(self, api_key: Optional[str] = None, base_url: Optional[str] = None):
        """
        初始化 MemoryX 客户端
        
        Args:
            api_key: API Key（如果已有）
            base_url: API 基础 URL
        """
        self.api_key = api_key
        self.base_url = base_url or self.DEFAULT_BASE_URL
        self.machine_fingerprint = self._generate_fingerprint()
        
    def _generate_fingerprint(self) -> str:
        """生成机器指纹"""
        # 基于硬件信息生成唯一标识
        machine_info = {
            "hostname": socket.gethostname(),
            "platform": platform.system(),
            "machine": platform.machine(),
            "processor": platform.processor() or "unknown",
            "mac": hex(uuid.getnode()),
        }
        fingerprint_str = json.dumps(machine_info, sort_keys=True)
        return hashlib.sha256(fingerprint_str.encode()).hexdigest()[:32]
    
    def _request(self, method: str, endpoint: str, data: Optional[dict] = None) -> dict:
        """发送 HTTP 请求"""
        url = f"{self.base_url}{endpoint}"
        headers = {
            "Content-Type": "application/json",
            "User-Agent": f"memoryx-python/1.0.0"
        }
        
        if self.api_key:
            headers["X-API-Key"] = self.api_key
            
        req = Request(
            url,
            data=json.dumps(data).encode() if data else None,
            headers=headers,
            method=method
        )
        
        try:
            with urlopen(req, timeout=30) as response:
                return json.loads(response.read().decode())
        except HTTPError as e:
            error_body = e.read().decode()
            try:
                error_data = json.loads(error_body)
                raise MemoryXError(error_data.get("message", f"HTTP {e.code}"))
            except json.JSONDecodeError:
                raise MemoryXError(f"HTTP {e.code}: {error_body}")
        except Exception as e:
            raise MemoryXError(f"Request failed: {str(e)}")
    
    def auto_register(self) -> dict:
        """
        自动注册机器账户
        
        Returns:
            注册结果，包含 api_key, user_id 等
        """
        data = {
            "machine_fingerprint": self.machine_fingerprint,
            "platform": platform.system().lower(),
            "hostname": socket.gethostname()
        }
        
        result = self._request("POST", "/agents/auto-register", data)
        
        if result.get("success"):
            self.api_key = result["data"]["api_key"]
            # 保存配置
            self._save_config()
            
        return result
    
    def _save_config(self):
        """保存配置到本地文件"""
        import os
        config_dir = os.path.expanduser("~/.memoryx")
        os.makedirs(config_dir, exist_ok=True)
        
        config = {
            "api_key": self.api_key,
            "machine_fingerprint": self.machine_fingerprint,
            "base_url": self.base_url
        }
        
        with open(os.path.join(config_dir, "config.json"), "w") as f:
            json.dump(config, f)
    
    def _load_config(self) -> bool:
        """从本地文件加载配置"""
        import os
        config_path = os.path.expanduser("~/.memoryx/config.json")
        
        if not os.path.exists(config_path):
            return False
            
        try:
            with open(config_path, "r") as f:
                config = json.load(f)
            
            # 验证机器指纹
            if config.get("machine_fingerprint") == self.machine_fingerprint:
                self.api_key = config.get("api_key")
                self.base_url = config.get("base_url", self.DEFAULT_BASE_URL)
                return True
        except Exception:
            pass
            
        return False
    
    def add(self, content: str, category: str = "semantic", 
            project_id: str = "default", metadata: Optional[dict] = None) -> dict:
        """
        存储记忆
        
        Args:
            content: 记忆内容
            category: 认知分类 (episodic/semantic/procedural/emotional/reflective)
            project_id: 项目 ID
            metadata: 额外元数据
            
        Returns:
            存储结果
        """
        if not self.api_key:
            raise MemoryXError("Not registered. Call auto_register() first.")
            
        data = {
            "content": content,
            "category": category,
            "project_id": project_id,
            "metadata": metadata or {}
        }
        
        return self._request("POST", "/memories", data)
    
    def list(self, project_id: Optional[str] = None, 
             limit: int = 100, offset: int = 0) -> dict:
        """
        列出记忆
        
        Args:
            project_id: 项目 ID 过滤
            limit: 返回数量限制
            offset: 分页偏移
            
        Returns:
            记忆列表
        """
        if not self.api_key:
            raise MemoryXError("Not registered. Call auto_register() first.")
            
        params = f"?limit={limit}&offset={offset}"
        if project_id:
            params += f"&project_id={project_id}"
            
        return self._request("GET", f"/memories{params}")
    
    def search(self, query: str, project_id: Optional[str] = None,
               limit: int = 10) -> dict:
        """
        搜索记忆
        
        Args:
            query: 搜索关键词
            project_id: 项目 ID 过滤
            limit: 返回数量限制
            
        Returns:
            搜索结果
        """
        if not self.api_key:
            raise MemoryXError("Not registered. Call auto_register() first.")
            
        data = {
            "query": query,
            "limit": limit
        }
        
        if project_id:
            data["project_id"] = project_id
            
        return self._request("POST", "/memories/search", data)
    
    def delete(self, memory_id: str) -> dict:
        """
        删除记忆
        
        Args:
            memory_id: 记忆 ID
            
        Returns:
            删除结果
        """
        if not self.api_key:
            raise MemoryXError("Not registered. Call auto_register() first.")
            
        return self._request("DELETE", f"/memories/{memory_id}")
    
    def get_claim_code(self) -> str:
        """
        获取认领验证码
        
        Returns:
            6 位验证码
        """
        if not self.api_key:
            raise MemoryXError("Not registered. Call auto_register() first.")
            
        # 这里需要调用 claim/init 接口
        # 由于需要邮箱，我们先返回一个提示
        result = self._request("POST", "/agents/claim/init", {
            "machine_fingerprint": self.machine_fingerprint,
            "email": "pending@example.com"  # 占位，实际需要用户提供
        })
        
        if result.get("success"):
            return result["data"]["verification_code"]
        
        raise MemoryXError("Failed to get claim code")
    
    def get_stats(self) -> dict:
        """获取机器统计信息"""
        if not self.api_key:
            raise MemoryXError("Not registered. Call auto_register() first.")
            
        return self._request("GET", f"/agents/machine-stats?machine_fingerprint={self.machine_fingerprint}")


class MemoryXError(Exception):
    """MemoryX 错误"""
    pass


def connect_memory(base_url: Optional[str] = None) -> MemoryXClient:
    """
    快速连接记忆系统
    
    自动检测本地配置，如果没有则自动注册
    
    Args:
        base_url: API 基础 URL（可选）
        
    Returns:
        MemoryXClient 实例
        
    Example:
        >>> from memoryx import connect_memory
        >>> memory = connect_memory()
        >>> memory.add("用户喜欢深色模式")
        >>> results = memory.search("用户偏好")
    """
    client = MemoryXClient(base_url=base_url)
    
    # 尝试加载已有配置
    if client._load_config():
        print("✅ 已连接到 MemoryX 记忆系统")
        return client
    
    # 自动注册
    print("🔄 首次使用，自动注册中...")
    result = client.auto_register()
    
    if result.get("success"):
        data = result["data"]
        print(f"✅ 注册成功！")
        print(f"   Agent ID: {data['user_id']}")
        print(f"   API Key: {data['api_key'][:20]}...")
        print(f"\n💡 请访问 http://t0ken.ai/agent-register 认领这台机器")
        print(f"   或询问我：\"我的认领验证码是多少？\"")
    else:
        raise MemoryXError(f"Registration failed: {result.get('message')}")
    
    return client
