"""
高级SQL查询功能完整测试用例
参考项目测试规范，全面测试所有SQL功能
"""

import pytest
import os
import sys
import pandas as pd
import tempfile
from pathlib import Path

# 添加项目路径
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

# 直接导入
sys.path.insert(0, os.path.join(project_root, "src"))
from excel_mcp_server_fastmcp.api.advanced_sql_query import AdvancedSQLQueryEngine, execute_advanced_sql_query
import sqlglot


class TestAdvancedSQLQuery:
    """高级SQL查询功能测试类"""

    @pytest.fixture
    def sample_excel_file(self):
        """创建测试用的Excel文件"""
        # 游戏反馈数据
        feedback_data = {
            'GameName': ['EndlessDefense', 'HundredHeroes', 'EndlessDefense', 'HundredHeroes',
                        'EndlessDefense', 'HundredHeroes', 'EndlessDefense', 'HundredHeroes',
                        'EndlessDefense', 'HundredHeroes'],
            'FeedbackType': ['BugReport', 'FeatureSuggestion', 'ExperienceIssue', 'BugReport',
                           'FeatureSuggestion', 'ExperienceIssue', 'BugReport', 'FeatureSuggestion',
                           'BugReport', 'ExperienceIssue'],
            'Rating': [3, 4, 2, 5, 4, 3, 1, 5, 2, 4],
            'Content': ['Game lag serious', 'Hope to add new heroes', 'Interface not friendly',
                       'Good balance', 'Suggest optimize tutorial', 'Loading time too long',
                       'Crash issue', 'Good graphics', 'Network unstable', 'Character balance issue'],
            'Platform': ['iOS', 'Android', 'iOS', 'Android', 'iOS', 'Android', 'iOS', 'Android', 'iOS', 'Android']
        }

        df = pd.DataFrame(feedback_data)

        # 创建临时文件
        with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as tmp:
            df.to_excel(tmp.name, index=False, sheet_name="GameFeedback")
            yield tmp.name

        # 清理
        try:
            os.unlink(tmp.name)
        except:
            pass

    @pytest.fixture
    def large_excel_file(self):
        """创建大型测试文件"""
        large_data = []
        for i in range(1000):
            large_data.append({
                'ID': i + 1,
                'Category': f'Category_{i % 10}',
                'Value': (i * 7) % 100,
                'Score': (i * 13) % 10 + 1,
                'Status': 'Active' if i % 3 != 0 else 'Inactive'
            })

        df = pd.DataFrame(large_data)

        with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as tmp:
            df.to_excel(tmp.name, index=False, sheet_name="LargeData")
            yield tmp.name

        try:
            os.unlink(tmp.name)
        except:
            pass

    def test_engine_initialization(self):
        """测试引擎初始化"""
        engine = AdvancedSQLQueryEngine()
        assert engine is not None

        # 测试带参数初始化
        engine_with_params = AdvancedSQLQueryEngine(disable_streaming_aggregate=True)
        assert engine_with_params is not None

    def test_basic_select_query(self, sample_excel_file):
        """测试基础SELECT查询"""
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT GameName, FeedbackType FROM GameFeedback"
        )

        assert result['success'] is True
        assert len(result['data']) > 0

        # 检查返回的列
        query_info = result['query_info']
        assert 'returned_columns' in query_info
        assert 'GameName' in query_info['returned_columns']
        assert 'FeedbackType' in query_info['returned_columns']

    def test_where_clause_conditions(self, sample_excel_file):
        """测试WHERE条件查询"""
        # 测试等于条件
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT * FROM GameFeedback WHERE GameName = 'EndlessDefense'"
        )

        assert result['success'] is True
        data_rows = result['data'][1:] if result['data'] else []
        endless_rows = [row for row in data_rows if row and len(row) > 0 and row[0] == 'EndlessDefense']
        assert len(endless_rows) > 0

        # 测试大于条件
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT * FROM GameFeedback WHERE Rating > 3"
        )

        assert result['success'] is True

        # 测试LIKE条件
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT * FROM GameFeedback WHERE Content LIKE '%Game%'"
        )

        assert result['success'] is True

        # 测试IN条件
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT * FROM GameFeedback WHERE FeedbackType IN ('BugReport', 'ExperienceIssue')"
        )

        assert result['success'] is True

    def test_group_by_aggregation(self, sample_excel_file):
        """测试GROUP BY聚合查询"""
        # 测试COUNT聚合
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT GameName, COUNT(*) as FeedbackCount FROM GameFeedback GROUP BY GameName"
        )

        assert result['success'] is True
        data = result['data']

        if len(data) > 1:
            # 检查聚合结果
            found_endless = False
            found_hundred = False
            for row in data[1:]:  # 跳过表头
                if len(row) >= 2:
                    if 'EndlessDefense' in str(row[0]):
                        found_endless = True
                    if 'HundredHeroes' in str(row[0]):
                        found_hundred = True

            assert found_endless, "应该找到EndlessDefense的聚合结果"
            assert found_hundred, "应该找到HundredHeroes的聚合结果"

        # 测试AVG聚合
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT GameName, AVG(Rating) as AvgRating FROM GameFeedback GROUP BY GameName"
        )

        assert result['success'] is True

        # 测试多列GROUP BY
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT GameName, FeedbackType, COUNT(*) as Count FROM GameFeedback GROUP BY GameName, FeedbackType"
        )

        assert result['success'] is True

    def test_order_by_and_limit(self, sample_excel_file):
        """测试ORDER BY和LIMIT"""
        # 测试ORDER BY
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT GameName, Rating FROM GameFeedback ORDER BY Rating DESC"
        )

        assert result['success'] is True

        # 测试LIMIT
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT GameName, Rating FROM GameFeedback ORDER BY Rating DESC LIMIT 3"
        )

        assert result['success'] is True
        # 限制结果应该最多3行 + 1行表头
        assert len(result['data']) <= 4

    def test_complex_queries(self, sample_excel_file):
        """测试复杂查询"""
        # 复合WHERE条件 + GROUP BY + ORDER BY
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT FeedbackType, COUNT(*) as Count FROM GameFeedback WHERE GameName = 'EndlessDefense' AND Rating <= 3 GROUP BY FeedbackType ORDER BY Count DESC"
        )

        assert result['success'] is True

        # 多条件查询
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT * FROM GameFeedback WHERE Platform = 'iOS' AND (Rating >= 4 OR FeedbackType = 'BugReport')"
        )

        assert result['success'] is True

    def test_having_clause(self, sample_excel_file):
        """测试HAVING子句"""
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT GameName, COUNT(*) as Count FROM GameFeedback GROUP BY GameName HAVING COUNT(*) > 3"
        )

        assert result['success'] is True

    def test_error_handling(self, sample_excel_file):
        """测试错误处理"""
        # 测试不支持的INSERT
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="INSERT INTO GameFeedback VALUES ('Test', 'Test', 5, 'Test', 'Test')"
        )

        assert result['success'] is False
        assert '不支持的SQL' in result['message'] or 'INSERT' in result['message']

        # 测试语法错误
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT FROM GameFeedback WHERE"  # 语法错误
        )

        assert result['success'] is False
        assert '语法错误' in result['message'] or 'error' in result['message'].lower()

        # 测试文件不存在
        result = execute_advanced_sql_query(
            file_path="nonexistent_file.xlsx",
            sql="SELECT * FROM GameFeedback"
        )

        assert result['success'] is False
        assert '不存在' in result['message'] or 'not found' in result['message'].lower()

    def test_large_file_handling(self, large_excel_file):
        """测试大文件处理"""
        result = execute_advanced_sql_query(
            file_path=large_excel_file,
            sql="SELECT Category, COUNT(*) as Count, AVG(Value) as AvgValue FROM LargeData GROUP BY Category"
        )

        assert result['success'] is True
        assert len(result['data']) > 0

        # 测试LIMIT在大文件上的表现
        result = execute_advanced_sql_query(
            file_path=large_excel_file,
            sql="SELECT * FROM LargeData WHERE Status = 'Active' LIMIT 100"
        )

        assert result['success'] is True
        # 结果应该被限制
        assert len(result['data']) <= 101  # 100行数据 + 1行表头

    def test_data_types(self, sample_excel_file):
        """测试数据类型推断"""
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT GameName, Rating, Platform FROM GameFeedback"
        )

        assert result['success'] is True

        data_types = result['query_info'].get('data_types', {})
        assert isinstance(data_types, dict)

        # 应该能推断出Rating是数值类型
        if 'Rating' in data_types:
            assert data_types['Rating'] in ['integer', 'float']

    def test_edge_cases(self, sample_excel_file):
        """测试边界情况"""
        # 测试空结果
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT * FROM GameFeedback WHERE Rating > 10"
        )

        assert result['success'] is True
        # 只有表头或空结果
        assert len(result['data']) <= 1

        # 测试SELECT *
        result = execute_advanced_sql_query(
            file_path=sample_excel_file,
            sql="SELECT * FROM GameFeedback WHERE Rating = 5"
        )

        assert result['success'] is True
        # 应该返回所有列
        query_info = result['query_info']
        returned_columns = query_info.get('returned_columns', [])
        assert len(returned_columns) >= 4  # 至少有4列

    def test_multiple_sheets(self):
        """测试多工作表支持"""
        # 创建多工作表文件
        data1 = {'A': [1, 2], 'B': [3, 4]}
        data2 = {'X': [5, 6], 'Y': [7, 8]}

        df1 = pd.DataFrame(data1)
        df2 = pd.DataFrame(data2)

        with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as tmp:
            # 使用ExcelWriter写入多个工作表
            with pd.ExcelWriter(tmp.name, engine='openpyxl') as writer:
                df1.to_excel(writer, sheet_name='Sheet1', index=False)
                df2.to_excel(writer, sheet_name='Sheet2', index=False)

            # 测试查询第一个工作表
            result = execute_advanced_sql_query(
                file_path=tmp.name,
                sql="SELECT * FROM Sheet1"
            )

            assert result['success'] is True
            assert len(result['data']) >= 3  # 表头 + 2行数据

            # 测试查询第二个工作表
            result = execute_advanced_sql_query(
                file_path=tmp.name,
                sql="SELECT * FROM Sheet2"
            )

            assert result['success'] is True
            assert len(result['data']) >= 3  # 表头 + 2行数据

        try:
            os.unlink(tmp.name)
        except:
            pass

    def test_sql_validation(self, sample_excel_file):
        """测试SQL验证功能"""
        engine = AdvancedSQLQueryEngine()

        # 测试有效的SQL
        parsed = sqlglot.parse_one("SELECT * FROM GameFeedback")
        validation = engine._validate_sql_support(parsed)
        assert validation['valid'] is True

        # 测试无效的SQL (子查询)
        try:
            parsed = sqlglot.parse_one("SELECT * FROM GameFeedback WHERE id IN (SELECT id FROM other_table)")
            validation = engine._validate_sql_support(parsed)
            assert validation['valid'] is False
        except:
            pass  # 如果解析失败也算正确行为


def test_parameter_validation(sample_excel_file):
    """测试参数验证"""
    from excel_mcp_server_fastmcp.api.advanced_sql_query import execute_advanced_sql_query

    # 测试空SQL语句
    result = execute_advanced_sql_query(
        file_path=sample_excel_file,
        sql=""
    )
    assert result['success'] is False
    assert 'No expression was parsed' in result['message']

    # 测试None SQL语句
    result = execute_advanced_sql_query(
        file_path=sample_excel_file,
        sql=None
    )
    assert result['success'] is False


def test_integration_with_original_interface(sample_excel_file):
    """测试与原始接口的集成"""
    # 直接测试高级SQL查询引擎，绕过相对导入问题
    from excel_mcp_server_fastmcp.api.advanced_sql_query import execute_advanced_sql_query

    # 首先检查文件的实际工作表
    import pandas as pd
    df_file_info = pd.ExcelFile(sample_excel_file)
    actual_sheet_names = df_file_info.sheet_names
    print(f"实际工作表名称: {actual_sheet_names}")

    # 使用实际存在的工作表名称，通常测试文件使用第一个工作表
    sheet_name = actual_sheet_names[0]
    print(f"使用工作表: {sheet_name}")

    # 检查工作表的列名（使用SQL引擎相同的方式，支持双行表头）
    # 先尝试 openpyxl 读取前两行检测双行表头
    import openpyxl, re
    wb = openpyxl.load_workbook(sample_excel_file, read_only=True, data_only=True)
    ws = wb[sheet_name]
    rows_iter = ws.iter_rows(max_row=2, values_only=False)
    first_row_cells = next(rows_iter, None)
    second_row_cells = next(rows_iter, None)
    wb.close()

    is_dual_header = False
    if first_row_cells and second_row_cells:
        second_vals = [str(c.value).strip() if c.value else '' for c in second_row_cells]
        first_vals = [str(c.value).strip() if c.value else '' for c in first_row_cells]
        non_empty_second = [v for v in second_vals if v]
        non_empty_first = [v for v in first_vals if v]
        if len(non_empty_second) >= 3:
            second_all_field = all(re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', v) for v in non_empty_second)
            first_all_field = all(re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', v) for v in non_empty_first) if non_empty_first else False
            if second_all_field and not first_all_field:
                is_dual_header = True

    if is_dual_header:
        df_sample = pd.read_excel(sample_excel_file, sheet_name=sheet_name, header=1, keep_default_na=False)
    else:
        df_sample = pd.read_excel(sample_excel_file, sheet_name=sheet_name, keep_default_na=False)
    df_sample = df_sample.dropna(how='all').dropna(axis=1, how='all').reset_index(drop=True)

    actual_columns = df_sample.columns.tolist()
    print(f"实际列名: {actual_columns}, 双行表头: {is_dual_header}")

    # 根据实际列名调整SQL查询
    string_cols = [col for col in actual_columns if df_sample[col].dtype == 'object']
    if string_cols:
        group_col = string_cols[0]
        sql_query = f"SELECT {group_col}, COUNT(*) as Count FROM {sheet_name} GROUP BY {group_col}"
    else:
        # 没有字符串列时用数值列做COUNT
        numeric_cols = [col for col in actual_columns if df_sample[col].dtype in ['int64', 'float64']]
        if numeric_cols:
            sql_query = f"SELECT {numeric_cols[0]}, COUNT(*) as Count FROM {sheet_name} GROUP BY {numeric_cols[0]}"
        else:
            sql_query = f"SELECT COUNT(*) as total_count FROM {sheet_name}"

    print(f"执行SQL: {sql_query}")

    # 测试新的SQL功能
    result = execute_advanced_sql_query(
        file_path=sample_excel_file,
        sql=sql_query,
        include_headers=True
    )

    if not result['success']:
        print(f"集成测试错误: {result['message']}")
        if 'query_info' in result:
            print(f"错误详情: {result['query_info']}")

    assert result['success'] is True
    assert len(result['data']) > 0

    # 验证返回的数据结构符合原始接口格式
    assert 'data' in result
    assert 'query_info' in result
    assert isinstance(result['data'], list)

    # 验证表头和数据行
    if len(result['data']) > 1:
        headers = result['data'][0]
        data_rows = result['data'][1:]
        assert len(headers) >= 1  # 至少有一列
        assert len(data_rows) > 0   # 有数据行

        print(f"测试成功！返回列: {headers}, 数据行数: {len(data_rows)}")


if __name__ == "__main__":
    # 简单的测试运行器
    print("开始运行高级SQL查询功能测试...")

    test_instance = TestAdvancedSQLQuery()

    # 创建测试文件
    print("创建测试文件...")
    with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as tmp:
        test_data = {
            'GameName': ['EndlessDefense', 'HundredHeroes', 'EndlessDefense'],
            'FeedbackType': ['BugReport', 'FeatureSuggestion', 'ExperienceIssue'],
            'Rating': [3, 4, 2],
            'Content': ['Game lag', 'Add heroes', 'Bad interface']
        }
        df = pd.DataFrame(test_data)
        df.to_excel(tmp.name, index=False, sheet_name="GameFeedback")

        try:
            # 运行一些基本测试
            print("测试基础SELECT...")
            result = execute_advanced_sql_query(
                file_path=tmp.name,
                sql="SELECT GameName, Rating FROM GameFeedback"
            )
            print(f"基础查询结果: {result['success']}")

            print("测试GROUP BY聚合...")
            result = execute_advanced_sql_query(
                file_path=tmp.name,
                sql="SELECT GameName, COUNT(*) as Count FROM GameFeedback GROUP BY GameName"
            )
            print(f"聚合查询结果: {result['success']}")
            if result['success']:
                print(f"返回数据: {result['data']}")

            print("测试WHERE条件...")
            result = execute_advanced_sql_query(
                file_path=tmp.name,
                sql="SELECT * FROM GameFeedback WHERE Rating > 2"
            )
            print(f"WHERE查询结果: {result['success']}")

            print("测试ORDER BY和LIMIT...")
            result = execute_advanced_sql_query(
                file_path=tmp.name,
                sql="SELECT GameName, Rating FROM GameFeedback ORDER BY Rating DESC LIMIT 2"
            )
            print(f"ORDER BY + LIMIT结果: {result['success']}")

            print("测试错误处理...")
            result = execute_advanced_sql_query(
                file_path=tmp.name,
                sql="INSERT INTO GameFeedback VALUES ('test', 'test', 5, 'test')"
            )
            print(f"错误处理结果: {not result['success']} - {result['message']}")

            print("所有基础测试完成!")

        finally:
            try:
                os.unlink(tmp.name)
            except:
                pass