import re
import logging
from contextlib import contextmanager

from .sqlite_db import sqlite_db

logger = logging.getLogger(__name__)

def translate_query(query: str) -> str:
    """
    Dịch câu SQL đặc thù của Postgres/StarRocks sang dạng mà SQLite hiểu được.
    """
    # 1. Thay thế Placeholder của Postgres/StarRocks (%s) thành của SQLite (?)
    # Dùng regex bao quát hơn: %s không đứng cạnh % khác
    q = re.sub(r'(?<!%)%s(?!%)', '?', query)
    
    # 2. Thay thế Postgres Schema (dashboard_canifa)
    q = re.sub(r'"dashboard_canifa"\."([a-zA-Z0-9_]+)"', r'pg__dashboard_canifa__\1', q)
    q = re.sub(r'dashboard_canifa\.([a-zA-Z0-9_]+)', r'pg__dashboard_canifa__\1', q)
    
    # Thay thế Postgres Schema (canifa_chat)
    q = re.sub(r'"canifa_chat"\."([a-zA-Z0-9_]+)"', r'pg__canifa_chat__\1', q)
    q = re.sub(r'canifa_chat\.([a-zA-Z0-9_]+)', r'pg__canifa_chat__\1', q)
    
    # Thay thế Postgres Schema (public)
    q = re.sub(r'"public"\."([a-zA-Z0-9_]+)"', r'pg__public__\1', q)
    q = re.sub(r'public\.([a-zA-Z0-9_]+)', r'pg__public__\1', q)

    # 3. Thay thế cấu trúc của StarRocks
    q = re.sub(r'([a-zA-Z0-9_]+\.)?`?magento_product_dimension_with_text_embedding`?', r'sr__test_db__magento_product_dimension_with_text_embedding', q)
    
    # 4. Vá các ngữ pháp (Dialect) bị lệch pha
    # ANY_VALUE(col) -> MAX(col)
    q = re.sub(r'ANY_VALUE\s*\(', r'MAX(', q, flags=re.IGNORECASE)
    # MAX_BY(col, score) -> MAX(col)
    q = re.sub(r'MAX_BY\s*\(\s*([^,]+)\s*,\s*[^)]+\)', r'MAX(\1)', q, flags=re.IGNORECASE)
    # IF(cond, true, false) -> IIF(cond, true, false) của SQLite
    q = re.sub(r'\bIF\s*\(', r'IIF(', q, flags=re.IGNORECASE)

    # 5. Handle StarRocks vector similarity
    # approx_cosine_similarity(vector, [0.1, ...]) -> 0.5 (dummy)
    q = re.sub(r'approx_cosine_similarity\s*\(\s*vector\s*,\s*\[[^\]]+\]\s*\)', r'0.5', q, flags=re.IGNORECASE)

    # 6. Handle ORDER BY ... NULLS LAST
    q = re.sub(r'NULLS\s+LAST', '', q, flags=re.IGNORECASE)

    # 7. Strip PostgreSQL type casts (::jsonb, ::text, ::int, ::timestamp, etc.)
    q = re.sub(r'::[a-zA-Z_]+(?:\[\])?', '', q)

    # 8. NOW() → CURRENT_TIMESTAMP  (SQLite không có NOW())
    q = re.sub(r'\bNOW\s*\(\s*\)', 'CURRENT_TIMESTAMP', q, flags=re.IGNORECASE)

    # 9. ILIKE → LIKE  (SQLite LIKE mặc định case-insensitive cho ASCII)
    q = re.sub(r'\bILIKE\b', 'LIKE', q, flags=re.IGNORECASE)

    # 10. COALESCE với jsonb → giữ nguyên (SQLite hỗ trợ COALESCE)
    # TRUE/FALSE literals → 1/0
    q = re.sub(r'\bTRUE\b', '1', q, flags=re.IGNORECASE)
    q = re.sub(r'\bFALSE\b', '0', q, flags=re.IGNORECASE)
    
    return q

class MockCursor:
    """
    Giả mạo con trỏ (Cursor) của thư viện psycopg / pymysql.
    """
    def __init__(self):
        self._last_results = []
        self._last_result = None
        self.rowcount = 0
        
    def execute(self, query: str, params: tuple = None):
        if params is None:
            params = ()
        tq = translate_query(query)
        logger.debug(f"[SQLITE MOCK] Đã biên dịch Query: {tq[:100]}...")
        
        is_select = tq.strip().lower().startswith("select")
        
        if is_select:
            self._last_results = sqlite_db.fetch_all(tq, params)
            self.rowcount = len(self._last_results)
        else:
            self.rowcount = sqlite_db.execute(tq, params)
            self._last_results = []
            
    def fetchall(self):
        return self._last_results
        
    def fetchone(self):
        if self._last_results:
            return self._last_results[0]
        return None

    def close(self):
        pass

    # Hỗ trợ Async context manager cho một số hàm dùng `async with cursor()`
    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        self.close()

    # Context manager đồng bộ (`with cursor()`)
    def __enter__(self):
        return self
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

class MockConnection:
    """
    Giả mạo kết nối DB của psycopg pool.
    """
    def cursor(self):
        """Mô phỏng conn.cursor()"""
        return MockCursor()
        
    def transaction(self):
        """Mô phỏng transaction (Fake block)"""
        @contextmanager
        def dummy_transaction():
            yield self
        return dummy_transaction()

    def close(self):
        pass # Mock close

    def commit(self):
        pass

    def rollback(self):
        pass

@contextmanager
def get_mock_pg_conn():
    """
    Mô phỏng kết quả trả về của db_pool.get_conn()
    """
    logger.info("🛡️ [SQLITE MOCK] Đã đánh chặn PostgreSQL Connection -> Chạy truy vấn trên Local SQLite!")
    yield MockConnection()

def get_mock_pg_conn_compat():
    """
    Trực tiếp trả về MockConnection cho cơ chế không dùng context manager (compat)
    """
    logger.info("🛡️ [SQLITE MOCK COMPAT] Đã đánh chặn PostgreSQL Connection -> Chạy truy vấn trên Local SQLite!")
    return MockConnection()
