# -*- coding: utf-8 -*-
"""
Schema 表定义迁移完整性属性测试

**Validates: Requirements 7.3, 7.6**

Property 6: 对于任意现有数据库 schema（billiards_ods、billiards_dws）中的表，
新 schema（ods、dws）的 DDL 文件中应包含该表的 CREATE TABLE 定义。
"""
import os
import re

from hypothesis import given, settings
from hypothesis.strategies import sampled_from

# ── 路径常量 ──────────────────────────────────────────────
SCHEMAS_DIR = os.path.join(r"C:\NeoZQYY", "db", "etl_feiqiu", "schemas")

# 旧 schema 文件（billiards_ods / billiards_dws）
OLD_ODS_FILE = os.path.join(SCHEMAS_DIR, "schema_ODS_doc.sql")
OLD_DWS_FILE = os.path.join(SCHEMAS_DIR, "schema_dws.sql")

# 新 schema 文件（ods / dws）
NEW_ODS_FILE = os.path.join(SCHEMAS_DIR, "ods.sql")
NEW_DWS_FILE = os.path.join(SCHEMAS_DIR, "dws.sql")

# ── 解析工具 ──────────────────────────────────────────────
# 匹配 CREATE TABLE [IF NOT EXISTS] [schema.]table_name
_CREATE_TABLE_RE = re.compile(
    r"CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?"
    r"(?:[\w]+\.)?(\w+)",
    re.IGNORECASE,
)


def _extract_table_names(sql_path: str) -> set[str]:
    """从 SQL 文件中提取所有 CREATE TABLE 的表名（去掉 schema 前缀）。"""
    with open(sql_path, encoding="utf-8") as f:
        content = f.read()
    return {m.group(1).lower() for m in _CREATE_TABLE_RE.finditer(content)}


# ── 预加载表名集合（模块级，只解析一次） ────────────────────
OLD_ODS_TABLES = sorted(_extract_table_names(OLD_ODS_FILE))
OLD_DWS_TABLES = sorted(_extract_table_names(OLD_DWS_FILE))

NEW_ODS_TABLES = _extract_table_names(NEW_ODS_FILE)
NEW_DWS_TABLES = _extract_table_names(NEW_DWS_FILE)

# 合并旧表名列表，附带来源标记，方便 hypothesis 采样
_OLD_ODS_TAGGED = [(t, "ods") for t in OLD_ODS_TABLES]
_OLD_DWS_TAGGED = [(t, "dws") for t in OLD_DWS_TABLES]
_ALL_OLD_TABLES = _OLD_ODS_TAGGED + _OLD_DWS_TAGGED


# ── 属性测试 ──────────────────────────────────────────────
@settings(max_examples=100)
@given(table_info=sampled_from(_ALL_OLD_TABLES))
def test_old_table_exists_in_new_schema(table_info: tuple[str, str]) -> None:
    """
    Property 6: Schema 表定义迁移完整性

    **Validates: Requirements 7.3, 7.6**

    对于旧 schema 中的任意表，新 schema DDL 中应包含同名 CREATE TABLE 定义。
    """
    table_name, source = table_info

    if source == "ods":
        assert table_name in NEW_ODS_TABLES, (
            f"旧 billiards_ods 表 '{table_name}' 在新 ods.sql 中未找到 CREATE TABLE 定义。"
            f"\n新 ods.sql 包含的表: {sorted(NEW_ODS_TABLES)}"
        )
    else:
        assert table_name in NEW_DWS_TABLES, (
            f"旧 billiards_dws 表 '{table_name}' 在新 dws.sql 中未找到 CREATE TABLE 定义。"
            f"\n新 dws.sql 包含的表: {sorted(NEW_DWS_TABLES)}"
        )