"""
Characterization Test: One Big Table Refactor
Self-contained tests - no external dependencies needed.
"""
import json
import sys
import os

# Add backend to path
BACKEND_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "backend")
sys.path.insert(0, BACKEND_DIR)

# ═══════════════════════════════════════════════════════════════
# Test 1: Verify SELECT_COLUMNS via file parsing (no import needed)
# ═══════════════════════════════════════════════════════════════
def test_select_columns_contain_new_fields():
    """Verify SELECT_COLUMNS includes the 3 new One Big Table columns."""
    search_engine_path = os.path.join(BACKEND_DIR, "agent", "tools", "tool_module", "search_engine.py")
    with open(search_engine_path, "r", encoding="utf-8") as f:
        content = f.read()
    
    # Extract the SELECT_COLUMNS string
    assert "tags," in content or "tags\n" in content, "Missing 'tags' in SELECT_COLUMNS"
    assert "outfit_recommendations" in content, "Missing 'outfit_recommendations' in SELECT_COLUMNS"
    assert "description_text_full" in content, "Missing 'description_text_full' in SELECT_COLUMNS"
    # Old columns still present
    assert "internal_ref_code" in content, "Missing 'internal_ref_code'"
    assert "sale_price" in content, "Missing 'sale_price'"
    assert "description_text" in content, "Missing 'description_text'"
    print("✅ test_select_columns_contain_new_fields PASSED")


# ═══════════════════════════════════════════════════════════════
# Test 2: Verify _enrich_with_outfit is REMOVED
# ═══════════════════════════════════════════════════════════════
def test_enrich_with_outfit_removed():
    """Verify the old multi-table query method is removed."""
    search_engine_path = os.path.join(BACKEND_DIR, "agent", "tools", "tool_module", "search_engine.py")
    with open(search_engine_path, "r", encoding="utf-8") as f:
        content = f.read()
    
    assert "async def _enrich_with_outfit" not in content, "_enrich_with_outfit should be REMOVED"
    assert "pg__dashboard_canifa__ai_outfit_product_matches" not in content, "Old table reference should be REMOVED"
    assert "sqlite3.connect" not in content, "sqlite3.connect should be REMOVED from search_engine"
    assert "SQLITE_DB_PATH" not in content, "SQLITE_DB_PATH import should be REMOVED"
    print("✅ test_enrich_with_outfit_removed PASSED")


# ═══════════════════════════════════════════════════════════════
# Test 3: Verify _parse_outfit_recommendations EXISTS
# ═══════════════════════════════════════════════════════════════
def test_parse_method_exists():
    """Verify the new static method replacement exists."""
    search_engine_path = os.path.join(BACKEND_DIR, "agent", "tools", "tool_module", "search_engine.py")
    with open(search_engine_path, "r", encoding="utf-8") as f:
        content = f.read()
    
    assert "def _parse_outfit_recommendations" in content, "_parse_outfit_recommendations method should exist"
    assert "json.loads(raw)" in content, "Should use json.loads to parse outfit JSON"
    assert "json.JSONDecodeError" in content, "Should handle JSONDecodeError gracefully"
    print("✅ test_parse_method_exists PASSED")


# ═══════════════════════════════════════════════════════════════
# Test 4: JSON parse logic (pure unit test, no imports)
# ═══════════════════════════════════════════════════════════════
def test_json_parse_logic():
    """Test the JSON parse logic directly."""
    # Simulate _parse_outfit_recommendations
    def parse_outfit(products):
        for p in products:
            raw = p.get("outfit_recommendations")
            if raw and isinstance(raw, str):
                try:
                    p["outfit_recommendations"] = json.loads(raw)
                except (json.JSONDecodeError, TypeError):
                    p["outfit_recommendations"] = []
            elif not raw:
                p["outfit_recommendations"] = []
        return products
    
    # Case 1: Valid JSON
    products = [{"outfit_recommendations": json.dumps([
        {"match_product_code": "A001", "role": "top", "reason": "Test"}
    ])}]
    result = parse_outfit(products)
    assert isinstance(result[0]["outfit_recommendations"], list)
    assert len(result[0]["outfit_recommendations"]) == 1
    assert result[0]["outfit_recommendations"][0]["role"] == "top"
    
    # Case 2: None
    products = [{"outfit_recommendations": None}]
    result = parse_outfit(products)
    assert result[0]["outfit_recommendations"] == []
    
    # Case 3: Missing key
    products = [{"internal_ref_code": "X"}]
    result = parse_outfit(products)
    assert result[0]["outfit_recommendations"] == []
    
    # Case 4: Invalid JSON
    products = [{"outfit_recommendations": "NOT JSON {{{"}]
    result = parse_outfit(products)
    assert result[0]["outfit_recommendations"] == []
    
    # Case 5: Already a list (should remain untouched)
    products = [{"outfit_recommendations": [{"role": "top"}]}]
    result = parse_outfit(products)
    assert result[0]["outfit_recommendations"] == [{"role": "top"}]
    
    print("✅ test_json_parse_logic PASSED (5 sub-cases)")


# ═══════════════════════════════════════════════════════════════
# Test 5: Verify search() still calls _parse_outfit_recommendations
# ═══════════════════════════════════════════════════════════════
def test_search_calls_parse():
    """Verify search() method calls _parse_outfit_recommendations instead of _enrich_with_outfit."""
    search_engine_path = os.path.join(BACKEND_DIR, "agent", "tools", "tool_module", "search_engine.py")
    with open(search_engine_path, "r", encoding="utf-8") as f:
        content = f.read()
    
    assert "_parse_outfit_recommendations(products)" in content, "search() should call _parse_outfit_recommendations"
    assert "await self._enrich_with_outfit" not in content, "search() should NOT call _enrich_with_outfit"
    print("✅ test_search_calls_parse PASSED")


# ═══════════════════════════════════════════════════════════════
# Test 6: Verify no unused imports
# ═══════════════════════════════════════════════════════════════
def test_clean_imports():
    """Verify os and sqlite3 are not imported."""
    search_engine_path = os.path.join(BACKEND_DIR, "agent", "tools", "tool_module", "search_engine.py")
    with open(search_engine_path, "r", encoding="utf-8") as f:
        content = f.read()
    
    assert "import sqlite3" not in content, "sqlite3 should not be imported"
    assert "import os" not in content, "os should not be imported"
    print("✅ test_clean_imports PASSED")


# ═══════════════════════════════════════════════════════════════
# RUNNER
# ═══════════════════════════════════════════════════════════════
if __name__ == "__main__":
    print("=" * 60)
    print("🧪 ONE BIG TABLE REFACTOR — CHARACTERIZATION TESTS")
    print("=" * 60)
    
    test_select_columns_contain_new_fields()
    test_enrich_with_outfit_removed()
    test_parse_method_exists()
    test_json_parse_logic()
    test_search_calls_parse()
    test_clean_imports()
    
    print("=" * 60)
    print("🏆 ALL 6 TESTS PASSED!")
    print("=" * 60)
