"""
StarRocks Database Connection Utility
Based on chatbot-rsa pattern
"""

import logging
from typing import Any

import aiomysql
import pymysql
from pymysql.cursors import DictCursor

from config import (
    STARROCKS_DB,
    STARROCKS_HOST,
    STARROCKS_PASSWORD,
    STARROCKS_PORT,
    STARROCKS_USER,
)

logger = logging.getLogger(__name__)


class StarRocksConnection:
    # Shared connection (Singleton-like behavior) for all instances
    _shared_conn = None

    def __init__(
        self,
        host: str | None = None,
        database: str | None = None,
        user: str | None = None,
        password: str | None = None,
        port: int | None = None,
    ):
        self.host = host or STARROCKS_HOST
        self.database = database or STARROCKS_DB
        self.user = user or STARROCKS_USER
        self.password = password or STARROCKS_PASSWORD
        self.port = port or STARROCKS_PORT
        # self.conn references the shared connection
        self.conn = None

    def connect(self):
        """
        Establish or reuse persistent connection.
        """
        # 1. Try to reuse existing shared connection
        if StarRocksConnection._shared_conn and StarRocksConnection._shared_conn.open:
            try:
                # Ping to check if alive, reconnect if needed
                StarRocksConnection._shared_conn.ping(reconnect=True)
                self.conn = StarRocksConnection._shared_conn
                return self.conn
            except Exception as e:
                logger.warning(f"⚠️ Connection lost, reconnecting: {e}")
                StarRocksConnection._shared_conn = None

        # 2. Create new connection if needed
        print(f"   [DB] 🔌 Đang kết nối StarRocks (New Session): {self.host}:{self.port}...")
        logger.info(f"🔌 Connecting to StarRocks at {self.host}:{self.port} (DB: {self.database})...")
        try:
            new_conn = pymysql.connect(
                host=self.host,
                port=self.port,
                user=self.user,
                password=self.password,
                database=self.database,
                charset="utf8mb4",
                cursorclass=DictCursor,
                connect_timeout=10,
                read_timeout=30,
                write_timeout=30,
            )
            print("   [DB] ✅ Kết nối thành công.")
            logger.info("✅ Connected to StarRocks")

            # Save to class variable
            StarRocksConnection._shared_conn = new_conn
            self.conn = new_conn

        except Exception as e:
            print(f"   [DB] ❌ Lỗi kết nối: {e!s}")
            logger.error(f"❌ Failed to connect to StarRocks: {e}")
            raise

        return self.conn

    def execute_query(self, query: str, params: tuple | None = None) -> list[dict[str, Any]]:
        # print("   [DB] 🚀 Bắt đầu truy vấn dữ liệu...")
        # (Reduced noise in logs)
        logger.info("🚀 Executing StarRocks Query (Persistent Conn).")

        conn = self.connect()
        try:
            with conn.cursor() as cursor:
                cursor.execute(query, params)
                results = cursor.fetchall()
                print(f"   [DB] ✅ Truy vấn xong. Lấy được {len(results)} dòng.")
                logger.info(f"📊 Query successful, returned {len(results)} rows")
                return [dict(row) for row in results]
        except Exception as e:
            print(f"   [DB] ❌ Lỗi truy vấn: {e!s}")
            logger.error(f"❌ StarRocks query error: {e}")
            # Incase of query error due to connection, invalidate it
            StarRocksConnection._shared_conn = None
            raise
        # FINALLY BLOCK REMOVED: Do NOT close connection

    # Async pool shared
    _shared_pool = None

    async def get_pool(self):
        """
        Get or create shared async connection pool
        """
        if StarRocksConnection._shared_pool is None:
            logger.info(f"🔌 Creating Async Pool to {self.host}:{self.port}...")
            StarRocksConnection._shared_pool = await aiomysql.create_pool(
                host=self.host,
                port=self.port,
                user=self.user,
                password=self.password,
                db=self.database,
                charset="utf8mb4",
                cursorclass=aiomysql.DictCursor,
                minsize=100,
                maxsize=200,  # Max Ping: Mở 2000 slot - Đủ cân 500k users (với cơ chế pooling)
                connect_timeout=10,
            )
        return StarRocksConnection._shared_pool

    async def execute_query_async(self, query: str, params: tuple | None = None) -> list[dict[str, Any]]:
        """
        Execute query asynchronously using aiomysql pool
        """
        pool = await self.get_pool()
        logger.info("🚀 Executing Async Query.")

        async with pool.acquire() as conn, conn.cursor() as cursor:
            await cursor.execute(query, params)
            results = await cursor.fetchall()
            logger.info(f"📊 Async Query successful, returned {len(results)} rows")
            # aiomysql returns tuples or dicts depending on cursor.
            # Since we asked for DictCursor, results are dicts.
            return [dict(row) for row in results]

    def close(self):
        """Explicitly close if needed (e.g. app shutdown)"""
        if StarRocksConnection._shared_conn and StarRocksConnection._shared_conn.open:
            StarRocksConnection._shared_conn.close()
            StarRocksConnection._shared_conn = None
            self.conn = None
