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 (?)
    # Chỉ thay thế %s nếu nó KHÔNG nằm trong một chuỗi LIKE (ví dụ '%sơ mi%')
    # Một cách đơn giản là chỉ thay %s nếu nó đứng độc lập hoặc theo sau bởi dấu phẩy/ngoặc
    q = re.sub(r'(?<!%)\b%s\b(?!%)', '?', query)
    # Tuy nhiên %s trong psycopg thường không phải là word boundary.
    # Thử cách khác: chỉ thay %s nếu nó KHÔNG đứng cạnh ký tự chữ/số nào trừ khi là chính nó?
    # Thực tế trong project này %s thường dùng làm placeholder cho tham số.
    # Cách an toàn nhất cho Mock là replace %s nếu nó đứng sau dấu cách hoặc dấu mở ngoặc.
    q = re.sub(r'([ \(\,])%s([ \)\,])', r'\1?\2', query)
    # Xử lý trường hợp %s ở cuối câu
    q = re.sub(r'([ \(\,])%s$', r'\1?', q)
    
    # Nếu vẫn còn lỗi, ta có thể dùng một cách thủ công hơn cho dự án này: 
    # Nếu query có dùng LIKE, ta tạm thời không replace %s bừa bãi.
    if "LIKE" in query.upper() and "%s" in query:
        # Nếu có LIKE, khả năng cao %s là placeholder CỦA LIKE pattern nếu nó đứng cạnh %
        # Nhưng ở đây %s là placeholder của psycopg.
        # TRICK: TRong SQL query của stylist_engine, ta không dùng params cho LIKE pattern %s.
        # Ta dùng f-string. Vậy %s CHẮC CHẮN là pattern hoặc lỗi.
        pass 
    else:
        q = q.replace("%s", "?")
    
    # 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
    # Mẫu query thường gặp: shared_source.magento_product_dimension_with_text_embedding
    # Hoặc test_db.magento_product_...
    # Hoặc magento_product_...
    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)
    # IF(cond, true, false) -> IIF(cond, true, false) của SQLite
    # Lưu ý: Tìm chữ IF đứng đầu cẩn thận dính chuỗi
    q = re.sub(r'\bIF\s*\(', r'IIF(', 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()
