# -*- coding: utf-8 -*-
"""
数据库操作（批量、RETURNING支持）
"""
import re
from typing import List, Dict, Tuple
import psycopg2.extras
from .connection import DatabaseConnection


class DatabaseOperations(DatabaseConnection):
    """扩展数据库操作（包含批量upsert和returning支持）"""
    
    def batch_execute(self, sql: str, rows: List[Dict], page_size: int = 1000):
        """批量执行SQL（不带RETURNING）"""
        if not rows:
            return
        with self.conn.cursor() as c:
            psycopg2.extras.execute_batch(c, sql, rows, page_size=page_size)
    
    def batch_upsert_with_returning(self, sql: str, rows: List[Dict], page_size: int = 1000) -> Tuple[int, int]:
        """
        批量 UPSERT 并统计插入/更新数
        
        Args:
            sql: 包含RETURNING子句的SQL
            rows: 数据行列表
            page_size: 批次大小
            
        Returns:
            (inserted_count, updated_count) 元组
        """
        if not rows:
            return (0, 0)
        
        use_returning = "RETURNING" in sql.upper()
        
        with self.conn.cursor() as c:
            if not use_returning:
                psycopg2.extras.execute_batch(c, sql, rows, page_size=page_size)
                return (0, 0)
            
            # 优先尝试向量化执行
            try:
                inserted, updated = self._execute_with_returning_vectorized(c, sql, rows, page_size)
                return (inserted, updated)
            except Exception:
                # 回退到逐行执行
                return self._execute_with_returning_row_by_row(c, sql, rows)
    
    def _execute_with_returning_vectorized(self, cursor, sql: str, rows: List[Dict], page_size: int) -> Tuple[int, int]:
        """向量化执行（使用execute_values）"""
        # 解析VALUES子句
        m = re.search(r"VALUES\s*\((.*?)\)", sql, flags=re.IGNORECASE | re.DOTALL)
        if not m:
            raise ValueError("Cannot parse VALUES clause")
        
        tpl = "(" + m.group(1) + ")"
        base_sql = sql[:m.start()] + "VALUES %s" + sql[m.end():]
        
        ret = psycopg2.extras.execute_values(
            cursor, base_sql, rows, template=tpl, page_size=page_size, fetch=True
        )
        
        if not ret:
            return (0, 0)
        
        inserted = 0
        for rec in ret:
            flag = self._extract_inserted_flag(rec)
            if flag:
                inserted += 1
        
        return (inserted, len(ret) - inserted)
    
    def _execute_with_returning_row_by_row(self, cursor, sql: str, rows: List[Dict]) -> Tuple[int, int]:
        """逐行执行（回退方案）"""
        inserted = 0
        updated = 0
        
        for r in rows:
            cursor.execute(sql, r)
            try:
                rec = cursor.fetchone()
            except Exception:
                rec = None
            
            flag = self._extract_inserted_flag(rec) if rec else None
            
            if flag:
                inserted += 1
            else:
                updated += 1
        
        return (inserted, updated)
    
    @staticmethod
    def _extract_inserted_flag(rec) -> bool:
        """从返回记录中提取inserted标志"""
        if isinstance(rec, tuple):
            return bool(rec[0])
        elif isinstance(rec, dict):
            return bool(rec.get("inserted"))
        else:
            try:
                return bool(rec["inserted"])
            except Exception:
                return False


# 为了向后兼容，提供Pg别名
Pg = DatabaseOperations
