#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
VWED.data 模块 - 数据存储和缓存
"""

import json
import uuid
from typing import Dict, Any, Optional, List
from sqlalchemy import text
from utils.logger import get_logger


class VWEDDataModule:
    """VWED.data 模块 - 数据存储和缓存"""
    
    def __init__(self, script_id: str):
        self.script_id = script_id
        self._storage: Dict[str, Any] = {}
        self.logger = get_logger(f"services.online_script.data_module.{script_id}")
    
    def get(self, key: str, default=None):
        """获取数据"""
        return self._storage.get(key, default)
    
    def set(self, key: str, value: Any):
        """设置数据"""
        self._storage[key] = value
    
    def delete(self, key: str):
        """删除数据"""
        if key in self._storage:
            del self._storage[key]
    
    def clear(self):
        """清空所有数据"""
        self._storage.clear()
    
    def keys(self):
        """获取所有键"""
        return list(self._storage.keys())
    
    def has(self, key: str) -> bool:
        """检查键是否存在"""
        return key in self._storage

    async def get_cache_param(self, key: str) -> Optional[str]:
        """
        获取缓存数据
        
        Args:
            key: 缓存键
            
        Returns:
            str | None: 字符串类型，JSON格式。如果数据不存在，将返回None
            
        Raises:
            Exception: 本方法会抛出异常
        """
        from sqlalchemy import select
        from data.models.datacachesplit import VWEDDataCacheSplit
        from data.session import get_async_session
        
        async with get_async_session() as session:
            query = select(VWEDDataCacheSplit).where(
                VWEDDataCacheSplit.data_key == key,
                VWEDDataCacheSplit.is_deleted == 0
            )
            result = await session.execute(query)
            record = result.scalar_one_or_none()
            
            if not record or not record.data_value:
                return None
            
            return record.data_value

    async def put_cache_param(self, key: str, value: str) -> None:
        """
        缓存数据
        
        将参数中的key和value键值对在系统中进行缓存，缓存的数据将持久化，
        之后可通过get_cache_param方法根据key获取对应的value。
        
        Args:
            key: 缓存键
            value: 缓存值。如果要缓存一个对象，需要先序列化为JSON字符串
            
        Returns:
            None
            
        Note:
            本方法不会抛出异常
        """
        try:
            from sqlalchemy import select, insert, update
            from data.models.datacachesplit import VWEDDataCacheSplit
            from data.session import get_async_session
            
            async with get_async_session() as session:
                # 查询是否已存在相同key的记录且未被删除
                query = select(VWEDDataCacheSplit).where(
                    VWEDDataCacheSplit.data_key == key,
                    VWEDDataCacheSplit.is_deleted == 0
                )
                result = await session.execute(query)
                existing_active_record = result.scalar_one_or_none()
                
                # 如果有未删除的记录，则更新它
                if existing_active_record:
                    stmt = update(VWEDDataCacheSplit).where(
                        VWEDDataCacheSplit.id == existing_active_record.id
                    ).values(
                        data_value=json.dumps(value) if not isinstance(value, str) else value,
                    )
                    await session.execute(stmt)
                else:
                    # 如果没有未删除的记录，创建新记录
                    stmt = insert(VWEDDataCacheSplit).values(
                        id=str(uuid.uuid4()),
                        data_key=key,
                        data_value=json.dumps(value) if not isinstance(value, str) else value,
                        is_deleted=0
                    )
                    await session.execute(stmt)
                
                await session.commit()
        except Exception:
            # 本方法不会抛出异常，静默处理
            pass

    async def clear_cache_param(self, key: str) -> None:
        """
        删除缓存数据
        
        Args:
            key: 缓存键
            
        Returns:
            None
            
        Note:
            本方法不抛出异常
        """
        try:
            from sqlalchemy import update, select
            from data.models.datacachesplit import VWEDDataCacheSplit
            from data.session import get_async_session
                    
            async with get_async_session() as session:
                # 首先检查是否存在该条记录
                query = select(VWEDDataCacheSplit).where(
                    VWEDDataCacheSplit.data_key == key,
                    VWEDDataCacheSplit.is_deleted == 0
                )
                result = await session.execute(query)
                exists = result.scalar_one_or_none() is not None
                
                if exists:
                    # 软删除具有指定键的记录
                    stmt = update(VWEDDataCacheSplit).where(
                        VWEDDataCacheSplit.data_key == key,
                        VWEDDataCacheSplit.is_deleted == 0
                    ).values(
                        is_deleted=1,
                    )
                    await session.execute(stmt)
                    await session.commit()
        except Exception:
            # 本方法不抛出异常，静默处理
            pass

    async def get_all_cache_params(self) -> str:
        """
        获取所有的缓存数据
        
        获取缓存块的全部缓存数据，并以JSON格式返回。
        
        Returns:
            str: 字符串类型，JSON格式。如果数据不存在，将返回空字符串
            
        Raises:
            Exception: 本方法会抛出异常
        """
        from sqlalchemy import select
        from data.models.datacachesplit import VWEDDataCacheSplit
        from data.session import get_async_session
        
        async with get_async_session() as session:
            query = select(VWEDDataCacheSplit).where(
                VWEDDataCacheSplit.is_deleted == 0
            )
            result = await session.execute(query)
            records = result.scalars().all()
            
            if not records:
                return ""
            
            # 构建缓存数据字典
            cache_data = {}
            for record in records:
                try:
                    # 尝试将值解析为JSON，如果失败则使用原始字符串
                    cache_data[record.data_key] = json.loads(record.data_value)
                except (json.JSONDecodeError, TypeError):
                    cache_data[record.data_key] = record.data_value
            
            return json.dumps(cache_data, ensure_ascii=False)

    def get_settings_config_value(self, key: str) -> str:
        """获取 settings.py 的配置
        
        Args:
            key: 配置字段名
            
        Returns:
            str: JSON 字符串格式的配置值
        """
        try:
            from config.settings import settings
            
            # 使用 getattr 获取配置值
            config_value = getattr(settings, key, None)
            if config_value is not None:
                return json.dumps(config_value, ensure_ascii=False)
            
            self.logger.warning(f"[{self.script_id}] 未找到配置项: {key}")
            return "{}"
            
        except Exception as e:
            self.logger.error(f"[{self.script_id}] 获取设置配置失败: {e}")
            return "{}"

    async def jdbc_execute_sql(self, sql: str) -> bool:
        """执行 SQL 语句
        
        通过 SQL 命令操作 RDS 系统数据库，可用于创建自定义数据表。
        
        Args:
            sql: SQL 语句
            
        Returns:
            bool: True表示执行成功，False表示执行失败
        """
        try:
            from data.session import get_async_session
            
            async with get_async_session() as session:
                await session.execute(text(sql))
                await session.commit()
                
            self.logger.info(f"[{self.script_id}] SQL执行成功: {sql[:100]}...")
            return True
            
        except Exception as e:
            self.logger.error(f"[{self.script_id}] SQL执行失败: {e}, SQL: {sql}")
            return False

    async def jdbc_query(self, sql: str) -> str:
        """使用 SQL 查询数据
        
        Args:
            sql: SQL 查询语句
            
        Returns:
            str: JSON格式的查询结果
        """
        try:
            from data.session import get_async_session
            
            async with get_async_session() as session:
                result = await session.execute(text(sql))
                
                # 获取列名
                columns = list(result.keys()) if result.keys() else []
                
                # 获取所有行数据
                rows = result.fetchall()
                
                # 转换为字典列表
                data = []
                for row in rows:
                    row_dict = {}
                    for i, col in enumerate(columns):
                        row_dict[col] = str(row[i]) if row[i] is not None else None
                    data.append(row_dict)
                
                return json.dumps(data, ensure_ascii=False)
                
        except Exception as e:
            self.logger.error(f"[{self.script_id}] SQL查询失败: {e}, SQL: {sql}")
            return "[]"

    async def jdbc_insert_or_update(self, sql: str, *sql_params: Any) -> int:
        """更新数据
        
        更新数据记录，支持动态参数。
        
        Args:
            sql: SQL语句，支持参数占位符 ?
            sql_params: 动态参数列表
            
        Returns:
            int: 0表示更新失败，大于0表示更新的记录数目
        """
        try:
            from data.session import get_async_session
            
            # 将 ? 占位符转换为 :param_n 格式
            param_sql = sql
            params = {}
            for i, param in enumerate(sql_params):
                param_key = f"param_{i}"
                param_sql = param_sql.replace("?", f":{param_key}", 1)
                params[param_key] = param
            
            async with get_async_session() as session:
                result = await session.execute(text(param_sql), params)
                await session.commit()
                
                affected_rows = result.rowcount
                self.logger.info(f"[{self.script_id}] SQL更新成功，影响行数: {affected_rows}")
                return affected_rows
                
        except Exception as e:
            self.logger.error(f"[{self.script_id}] SQL更新失败: {e}, SQL: {sql}, 参数: {sql_params}")
            return 0

    async def jdbc_query_count(self, sql: str) -> Optional[int]:
        """查询数据数量
        
        执行自定义 SQL 语句查询满足条件数据的数量。
        注意：只能使用 select count 语句。
        
        Args:
            sql: SQL count查询语句
            
        Returns:
            Optional[int]: None表示查询失败，其他数字表示查询到的记录数目
        """
        try:
            # 简单验证SQL是否为count查询
            sql_lower = sql.lower().strip()
            if not sql_lower.startswith("select count"):
                self.logger.error(f"[{self.script_id}] 只允许使用 select count 语句: {sql}")
                return None
            
            from data.session import get_async_session
            
            async with get_async_session() as session:
                result = await session.execute(text(sql))
                count = result.scalar()
                
                return int(count) if count is not None else 0
                
        except Exception as e:
            self.logger.error(f"[{self.script_id}] Count查询失败: {e}, SQL: {sql}")
            return None