import os
import sqlite3
from typing import Optional, Dict, List, Tuple
from diona.project.storage import get_storage_instance


class GlobalMemory:
    _instance: Optional["GlobalMemory"] = None

    def __new__(cls) -> "GlobalMemory":
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._initialized = False
        return cls._instance

    def __init__(self):
        if self._initialized:
            return
        
        self._storage = get_storage_instance()
        self._db_path = self._storage.get_path("agent", "global.db", storage_type="user")
        self._cache: Dict[str, str] = {}
        self._initialize_db()
        self._load_from_db()
        self._initialized = True

    def _initialize_db(self):
        conn = sqlite3.connect(self._db_path)
        cursor = conn.cursor()
        
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS global_memory (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            key TEXT UNIQUE NOT NULL,
            value TEXT NOT NULL
        )
        ''')
        
        conn.commit()
        conn.close()

    def _load_from_db(self):
        conn = sqlite3.connect(self._db_path)
        cursor = conn.cursor()
        
        cursor.execute('SELECT key, value FROM global_memory')
        rows = cursor.fetchall()
        
        for key, value in rows:
            self._cache[key] = value
        
        conn.close()

    def add_memory(self, key: str, value: str) -> bool:
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            cursor.execute('''
            INSERT OR REPLACE INTO global_memory (key, value) 
            VALUES (?, ?)
            ''', (key, value))
            
            conn.commit()
            conn.close()
            
            self._cache[key] = value
            return True
        except Exception:
            return False

    def delete_memory(self, key: str) -> bool:
        try:
            conn = sqlite3.connect(self._db_path)
            cursor = conn.cursor()
            
            cursor.execute('DELETE FROM global_memory WHERE key = ?', (key,))
            conn.commit()
            conn.close()
            
            if key in self._cache:
                del self._cache[key]
            return True
        except Exception:
            return False

    def get_memory(self, key: str) -> Optional[str]:
        return self._cache.get(key)

    def list_memories(self, page: int = 1, page_size: int = 10) -> List[Tuple[str, str]]:
        offset = (page - 1) * page_size
        
        conn = sqlite3.connect(self._db_path)
        cursor = conn.cursor()
        
        cursor.execute('''
        SELECT key, value FROM global_memory 
        ORDER BY id DESC 
        LIMIT ? OFFSET ?
        ''', (page_size, offset))
        
        rows = cursor.fetchall()
        conn.close()
        
        return rows

    def get_memory_count(self) -> int:
        return len(self._cache)

    def get_memory_char_count(self) -> int:
        return sum(len(key) + len(value) for key, value in self._cache.items())


def get_global_memory() -> GlobalMemory:
    return GlobalMemory()
