import os
import sqlite3
from typing import Optional, List
from dataclasses import dataclass


IMPORTANCE_LEVELS = {
    1: "很低",
    2: "低",
    3: "中等",
    4: "高",
    5: "很高"
}


@dataclass
class GlobalKnowledge:
    id: int
    category: str
    content: str
    importance: int


class GlobalKnowledgeCenter:
    _instance: Optional["GlobalKnowledgeCenter"] = None
    
    def __new__(cls) -> "GlobalKnowledgeCenter":
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._initialized = False
        return cls._instance
    
    def __init__(self):
        if self._initialized:
            return
        
        from diona.project.storage import get_storage_instance
        self._storage = get_storage_instance()
        self._db_path = self._storage.get_path("agent", "global_knowledge.db", storage_type="user")
        self._initialize_db()
        self._initialized = True
    
    def _initialize_db(self):
        os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
        conn = sqlite3.connect(self._db_path)
        cursor = conn.cursor()
        
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS global_knowledge (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            category TEXT NOT NULL,
            content TEXT NOT NULL,
            importance INTEGER NOT NULL DEFAULT 3,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
        ''')
        
        cursor.execute('''
        CREATE INDEX IF NOT EXISTS idx_category ON global_knowledge(category)
        ''')
        
        cursor.execute('''
        CREATE INDEX IF NOT EXISTS idx_importance ON global_knowledge(importance)
        ''')
        
        conn.commit()
        conn.close()
    
    def add_knowledge(
        self,
        category: str,
        content: str,
        importance: int = 3
    ) -> Optional[int]:
        if not 1 <= importance <= 5:
            importance = 3
        
        if len(content) > 100:
            first_id = self.add_knowledge(category, content[:100], importance)
            second_id = self.add_knowledge(category, content[100:], importance)
            return first_id
        
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            cursor.execute('''
            INSERT INTO global_knowledge (category, content, importance)
            VALUES (?, ?, ?)
            ''', (category, content, importance))
            
            knowledge_id = cursor.lastrowid
            conn.commit()
            conn.close()
            
            return knowledge_id
        except Exception:
            return None
    
    def delete_knowledge(self, knowledge_id: int) -> bool:
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            cursor.execute('DELETE FROM global_knowledge WHERE id = ?', (knowledge_id,))
            
            conn.commit()
            conn.close()
            return True
        except Exception:
            return False
    
    def update_knowledge(
        self,
        knowledge_id: int,
        category: Optional[str] = None,
        content: Optional[str] = None,
        importance: Optional[int] = None
    ) -> bool:
        updates = []
        params = []
        
        if category is not None:
            updates.append("category = ?")
            params.append(category)
        
        if content is not None:
            updates.append("content = ?")
            params.append(content)
        
        if importance is not None and 1 <= importance <= 5:
            updates.append("importance = ?")
            params.append(importance)
        
        if not updates:
            return False
        
        updates.append("updated_at = CURRENT_TIMESTAMP")
        params.append(knowledge_id)
        
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            cursor.execute(f'''
            UPDATE global_knowledge 
            SET {', '.join(updates)}
            WHERE id = ?
            ''', params)
            
            conn.commit()
            conn.close()
            return True
        except Exception:
            return False
    
    def get_knowledge(self, knowledge_id: int) -> Optional[GlobalKnowledge]:
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            cursor.execute('''
            SELECT id, category, content, importance 
            FROM global_knowledge 
            WHERE id = ?
            ''', (knowledge_id,))
            
            row = cursor.fetchone()
            conn.close()
            
            if row:
                return GlobalKnowledge(
                    id=row[0],
                    category=row[1],
                    content=row[2],
                    importance=row[3]
                )
            return None
        except Exception:
            return None
    
    def query_knowledge(
        self,
        category: Optional[str] = None,
        importance: Optional[int] = None,
        keyword: Optional[str] = None,
        limit: int = 10
    ) -> List[GlobalKnowledge]:
        conditions = []
        params = []
        
        if category:
            conditions.append("category = ?")
            params.append(category)
        
        if importance and 1 <= importance <= 5:
            conditions.append("importance = ?")
            params.append(importance)
        
        if keyword:
            conditions.append("content LIKE ?")
            params.append(f"%{keyword}%")
        
        where_clause = " AND ".join(conditions) if conditions else "1=1"
        
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            cursor.execute(f'''
            SELECT id, category, content, importance 
            FROM global_knowledge 
            WHERE {where_clause}
            ORDER BY importance DESC, updated_at DESC
            LIMIT ?
            ''', params + [limit])
            
            rows = cursor.fetchall()
            conn.close()
            
            return [
                GlobalKnowledge(
                    id=row[0],
                    category=row[1],
                    content=row[2],
                    importance=row[3]
                )
                for row in rows
            ]
        except Exception:
            return []
    
    def list_categories(self) -> List[str]:
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            cursor.execute('''
            SELECT DISTINCT category FROM global_knowledge ORDER BY category
            ''')
            
            rows = cursor.fetchall()
            conn.close()
            
            return [row[0] for row in rows]
        except Exception:
            return []
    
    def list_knowledge(
        self,
        category: Optional[str] = None,
        page: int = 1,
        page_size: int = 20
    ) -> List[GlobalKnowledge]:
        offset = (page - 1) * page_size
        
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            if category:
                cursor.execute('''
                SELECT id, category, content, importance 
                FROM global_knowledge 
                WHERE category = ?
                ORDER BY importance DESC, updated_at DESC
                LIMIT ? OFFSET ?
                ''', (category, page_size, offset))
            else:
                cursor.execute('''
                SELECT id, category, content, importance 
                FROM global_knowledge 
                ORDER BY importance DESC, updated_at DESC
                LIMIT ? OFFSET ?
                ''', (page_size, offset))
            
            rows = cursor.fetchall()
            conn.close()
            
            return [
                GlobalKnowledge(
                    id=row[0],
                    category=row[1],
                    content=row[2],
                    importance=row[3]
                )
                for row in rows
            ]
        except Exception:
            return []
    
    def get_count(self, category: Optional[str] = None) -> int:
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            if category:
                cursor.execute(
                    'SELECT COUNT(*) FROM global_knowledge WHERE category = ?',
                    (category,)
                )
            else:
                cursor.execute('SELECT COUNT(*) FROM global_knowledge')
            
            count = cursor.fetchone()[0]
            conn.close()
            
            return count
        except Exception:
            return 0


_center: Optional[GlobalKnowledgeCenter] = None


def get_global_knowledge_center() -> GlobalKnowledgeCenter:
    global _center
    if _center is None:
        _center = GlobalKnowledgeCenter()
    return _center
