"""
Test file for SlotCountService
Usage: python manage.py shell < test_slot_count_service.py
Or: python test_slot_count_service.py (if running standalone)
"""

import os
import sys
from pathlib import Path

# Add the project root to the path if running standalone
if __name__ == '__main__':
    django_project_path = Path(__file__).parent.parent
    sys.path.insert(0, str(django_project_path))
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'routineapi.settings')
    import django
    django.setup()

from routine.services.slot_count_service import SlotCountService
import json

# ============================================================================
# CONFIGURATION: Update these paths to point to your test files
# ============================================================================

TEST_FILES = {
    'image_jpg': 'G:\\routine\\test_files\\routine_sample.jpg',
    'image_png': 'G:\\routine\\test_files\\routine_sample.png',
    'pdf': 'G:\\routine\\routine_django\\1st_Batch_32.pdf',
    # Add more test files here
}

# ============================================================================
# TEST FUNCTIONS
# ============================================================================

def test_image_extraction(file_path: str):
    """Test image cell extraction"""
    print(f"\n{'='*80}")
    print(f"Testing Image Extraction: {file_path}")
    print(f"{'='*80}")
    
    if not os.path.exists(file_path):
        print(f"❌ File not found: {file_path}")
        return
    
    print(f"✓ File exists: {file_path}")
    print(f"File size: {os.path.getsize(file_path) / 1024:.2f} KB")
    
    result = SlotCountService.extract_cells_with_slot_count(file_path)
    
    print(f"\n📊 Extraction Results:")
    print(f"  - Error: {result.get('error')}")
    print(f"  - Base Width: {result.get('base_width')}")
    print(f"  - Cells Extracted: {len(result.get('cells', []))}")
    print(f"  - Structured Entries: {len(result.get('structured_data', []))}")
    
    if result.get('cells'):
        print(f"\n📦 Sample Cells (first 3):")
        for i, cell in enumerate(result['cells'][:3], 1):
            print(f"  [{i}] Position: ({cell['x']}, {cell['y']}), "
                  f"Size: {cell['width']}x{cell['height']}, "
                  f"Slots: {cell.get('slot_count', 'N/A')}, "
                  f"Ratio: {cell.get('calculated_width_ratio', 'N/A'):.2f}")
    
    if result.get('structured_data'):
        print(f"\n📋 Sample Structured Data (first 3):")
        for i, data in enumerate(result['structured_data'][:3], 1):
            print(f"  [{i}] Day: {data.get('day')}, "
                  f"Text: {data.get('text', 'N/A')[:30]}, "
                  f"Slots: {data.get('slot_count', 'N/A')}")
    
    # Save detailed results to file
    output_file = file_path.replace('.', '_output.txt')
    with open(output_file, 'w') as f:
        json.dump(result, f, indent=2, default=str)
    print(f"\n💾 Detailed results saved to: {output_file}")
    
    # return result


def test_pdf_extraction(file_path: str):
    """Test PDF cell extraction"""
    print(f"\n{'='*80}")
    print(f"Testing PDF Extraction: {file_path}")
    print(f"{'='*80}")
    
    if not os.path.exists(file_path):
        print(f"❌ File not found: {file_path}")
        print(f"\nℹ️  To enable PDF processing, install poppler-utils:")
        print(f"   Windows: choco install poppler")
        print(f"   Mac: brew install poppler")
        print(f"   Linux: sudo apt-get install poppler-utils")
        return
    
    print(f"✓ File exists: {file_path}")
    print(f"File size: {os.path.getsize(file_path) / 1024:.2f} KB")
    
    result = SlotCountService.extract_cells_with_slot_count(file_path)
    
    print(f"\n📊 Extraction Results:")
    print(f"  - Error: {result.get('error')}")
    print(f"  - Base Width: {result.get('base_width')}")
    print(f"  - Cells Extracted: {len(result.get('cells', []))}")
    print(f"  - Structured Entries: {len(result.get('structured_data', []))}")
    
    if result.get('error') and 'poppler' in result.get('error', '').lower():
        print(f"\n⚠️  Poppler Error Detected!")
        print(f"Please install poppler-utils:")
        print(f"   Windows: choco install poppler")
        print(f"   Mac: brew install poppler")
        print(f"   Linux: sudo apt-get install poppler-utils")
    
    if result.get('cells'):
        print(f"\n📦 Sample Cells (first 3):")
        for i, cell in enumerate(result['cells'][:3], 1):
            print(f"  [{i}] Position: ({cell['x']}, {cell['y']}), "
                  f"Size: {cell['width']}x{cell['height']}, "
                  f"Slots: {cell.get('slot_count', 'N/A')}, "
                  f"Ratio: {cell.get('calculated_width_ratio', 'N/A'):.2f}")
    
    if result.get('structured_data'):
        print(f"\n📋 Sample Structured Data (first 3):")
        for i, data in enumerate(result['structured_data'][:3], 1):
            print(f"  [{i}] Day: {data.get('day')}, "
                  f"Text: {data.get('text', 'N/A')[:30]}, "
                  f"Slots: {data.get('slot_count', 'N/A')}")
    
    # Save detailed results to file
    output_file = file_path.replace('.', '_output.txt')
    with open(output_file, 'w') as f:
        json.dump(result, f, indent=2, default=str)
    print(f"\n💾 Detailed results saved to: {output_file}")
    
    return result


def compare_image_vs_pdf(image_path: str, pdf_path: str):
    """Compare extraction results between image and PDF"""
    print(f"\n{'='*80}")
    print(f"Comparing Image vs PDF Extraction")
    print(f"{'='*80}")
    
    print(f"\n🖼️  Image: {image_path}")
    image_result = test_image_extraction(image_path)
    
    print(f"\n📄 PDF: {pdf_path}")
    pdf_result = test_pdf_extraction(pdf_path)
    
    if image_result and pdf_result:
        print(f"\n📊 Comparison:")
        print(f"  Image Cells: {len(image_result.get('cells', []))} vs PDF Cells: {len(pdf_result.get('cells', []))}")
        print(f"  Image Entries: {len(image_result.get('structured_data', []))} vs PDF Entries: {len(pdf_result.get('structured_data', []))}")
        print(f"  Image Base Width: {image_result.get('base_width'):.2f} vs PDF Base Width: {pdf_result.get('base_width'):.2f}")


def test_all_files():
    """Test all configured files"""
    print(f"\n{'='*80}")
    print(f"SlotCountService Test Suite")
    print(f"{'='*80}")
    
    for file_type, file_path in TEST_FILES.items():
        if file_type == 'pdf':
            test_pdf_extraction(file_path)
        elif 'image' in file_type or file_type in ['image_jpg', 'image_png']:
            test_image_extraction(file_path)
    
    print(f"\n{'='*80}")
    print(f"Test Suite Complete")
    print(f"{'='*80}")


# ============================================================================
# HELPER FUNCTIONS
# ============================================================================

def create_test_directory():
    """Create test directory if it doesn't exist"""
    test_dir = Path(__file__).parent.parent / 'test_files'
    test_dir.mkdir(exist_ok=True)
    print(f"ℹ️  Test directory: {test_dir}")
    print(f"ℹ️  Add your test files there: {test_dir}")


def list_test_files():
    """List all test files in the test directory"""
    test_dir = Path(__file__).parent.parent / 'test_files'
    if test_dir.exists():
        files = list(test_dir.glob('*'))
        if files:
            print(f"\n📁 Available Test Files:")
            for f in files:
                print(f"  - {f.name} ({f.stat().st_size / 1024:.2f} KB)")
        else:
            print(f"\n⚠️  No test files found in {test_dir}")
    else:
        print(f"\n⚠️  Test directory not found: {test_dir}")


# ============================================================================
# MAIN EXECUTION
# ============================================================================

if __name__ == '__main__':
    import argparse
    
    parser = argparse.ArgumentParser(description='Test SlotCountService')
    parser.add_argument('--file', type=str, help='Path to specific test file')
    parser.add_argument('--type', type=str, choices=['image', 'pdf', 'all'], 
                        default='all', help='Type of test to run')
    parser.add_argument('--list', action='store_true', help='List available test files')
    parser.add_argument('--setup', action='store_true', help='Setup test directory')
    
    args = parser.parse_args()
    
    if args.setup:
        create_test_directory()
    
    if args.list:
        list_test_files()
    
    if args.file:
        if args.file.lower().endswith(('.jpg', '.jpeg', '.png')):
            test_image_extraction(args.file)
        elif args.file.lower().endswith('.pdf'):
            test_pdf_extraction(args.file)
    elif args.type == 'image':
        for file_type, file_path in TEST_FILES.items():
            if 'image' in file_type:
                test_image_extraction(file_path)
    elif args.type == 'pdf':
        test_pdf_extraction(TEST_FILES.get('pdf', ''))
    else:  # all
        test_all_files()
    
    if not any([args.file, args.list, args.setup]):
        list_test_files()



# Test function
def test_merge_slot_data_with_parsed_data():
    """
    Test function for merge_slot_data_with_parsed_data
    """
    print("=" * 80)
    print("Testing merge_slot_data_with_parsed_data function")
    print("=" * 80)
    
    # Test Case 1: Parsed data as dictionary with routine_data
    print("\nTest Case 1: Dict with routine_data structure")
    parsed_data_dict =  {'name': '1st Batch_32.pdf', 'routine_year': '2026', 'effective_from': '01-04-2026', 'batch': '1st Batch', 'department': 'Computer Science and Engineering', 'semester': '2nd Semester', 'year': '3rd Year', 'teachers': [{'first_name': 'Md Nazmul', 'last_name': 'Hossain', 'code': 'NH'}, {'first_name': 'Sakib', 'last_name': 'Imtiaz', 'code': 'SI'}, {'first_name': 'Md. Touhidul', 'last_name': 'Islam', 'code': 'MTI'}, {'first_name': 'Saniul Islam', 'last_name': 'Anik', 'code': 'SIA'}, {'first_name': 'Md. Arafat Ibne', 'last_name': 'Mizan', 'code': 'AIM'}], 'courses': [{'code': 'CSE 3200', 'name': 'Software Development Project II', 'credit': '0.75'}, {'code': 'CSE 3201', 'name': 'Operating Systems', 'credit': '3.00'}, {'code': 'CSE 3202', 'name': 'Operating Systems Sessional', 'credit': '0.75'}, {'code': 'CSE 3203', 'name': 'Computer Architecture and Design', 'credit': '3.00'}, {'code': 'CSE 3205', 'name': 'Computer Networks', 'credit': '3.00'}, {'code': 'CSE 3206', 'name': 'Computer Networks Sessional', 'credit': '1.50'}, {'code': 'CSE 3207', 'name': 'Peripherals and Interfacings', 'credit': '3.00'}, {'code': 'CSE 3208', 'name': 'Peripherals and Interfacings Sessional', 'credit': '0.75'}, {'code': 'CSE 3209', 'name': 'Artificial Intelligence', 'credit': '3.00'}, {'code': 'CSE 3210', 'name': 'Artificial Intelligence Sessional', 'credit': '0.75'}], 'time_slots': [{'start': '09:00', 'end': '09:50', 'type': 'class', 'title': ''}, {'start': '09:50', 'end': '10:40', 'type': 'class', 'title': ''}, {'start': '10:40', 'end': '11:30', 'type': 'class', 'title': ''}, {'start': '11:30', 'end': '11:40', 'type': 'break', 'title': 'Tea Break'}, {'start': '11:40', 'end': '12:30', 'type': 'class', 'title': ''}, {'start': '12:30', 'end': '13:20', 'type': 'class', 'title': ''}, {'start': '13:20', 'end': '13:50', 'type': 'break', 'title': 'Lunch Break'}, {'start': '13:50', 'end': '14:40', 'type': 'class', 'title': ''}, {'start': '14:40', 'end': '15:30', 'type': 'class', 'title': ''}, {'start': '15:30', 'end': '16:20', 'type': 'class', 'title': ''}, {'start': '16:20', 'end': '17:10', 'type': 'class', 'title': ''}, {'start': '17:10', 'end': '18:00', 'type': 'class', 'title': ''}], 'routine_data': {'Monday': [{'slot': 0, 'course': 'CSE 3201', 'teacher': 'SI', 'room': 'Room- 104'}, {'slot': 1, 'course': 'CSE 3203', 'teacher': 'NH', 'room': 'Room- 104'}, {'slot': 4, 'course': 'CSE 3209', 'teacher': 'MTI', 'room': 'Room- 104'}], 'Tuesday': [{'slot': 0, 'course': 'CSE 3202', 'teacher': 'SI', 'room': 'Room – 305 (Every Alternative Week)'}, {'slot': 1, 'course': 'CSE 3209', 'teacher': 'MTI', 'room': 'Room- 202'}, {'slot': 2, 'course': 'CSE 3205', 'teacher': 'SIA', 'room': 'Room- 202'}], 'Wednesday': [{'slot': 0, 'course': 'CSE 3205', 'teacher': 'SIA', 'room': 'Room- 204'}, {'slot': 1, 'course': 'CSE 3201', 'teacher': 'SI', 'room': 'Room- 204'}, {'slot': 2, 'course': 'CSE 3203', 'teacher': 'NH', 'room': 'Room- 204'}, {'slot': 4, 'course': 'CSE 3208', 'teacher': 'NH', 'room': 'Room – 302 (Every Alternative Week)'}, {'slot': 5, 'course': 'CSE 3208', 'teacher': 'NH', 'room': 'Room – 302 (Every Alternative Week)'}], 'Thursday': [{'slot': 0, 'course': 'CSE 3207', 'teacher': 'AIM', 'room': 'Room- 205'}, {'slot': 1, 'course': 'CSE 3201', 'teacher': 'SI', 'room': 'Room- 205'}, {'slot': 2, 'course': 'CSE 3205', 'teacher': 'SIA', 'room': 'Room- 205'}, {'slot': 4, 'course': 'CSE 3210', 'teacher': 'MTI', 'room': 'Room – 305 (Every Alternative Week)'}, {'slot': 5, 'course': 'CSE 3210', 'teacher': 'MTI', 'room': 'Room – 305 (Every Alternative Week)'}], 'Friday': [{'slot': 0, 'course': 'CSE 3206', 'teacher': 'SIA', 'room': 'Room – 305'}, {'slot': 1, 'course': 'CSE 3207', 'teacher': 'AIM', 'room': 'Room- 302'}]}}

    
    slot_data = {
  "cells": [
    {
      "x": 246,
      "y": 407,
      "width": 172,
      "height": 102,
      "text": "CSE 3201",
      "day": "Monday",
      "slot_count": 1,
      "calculated_width_ratio": 0.882051282051282
    },
    {
      "x": 423,
      "y": 407,
      "width": 353,
      "height": 102,
      "text": "CSE 3203",
      "day": "Monday",
      "slot_count": 2,
      "calculated_width_ratio": 1.8102564102564103
    },
    {
      "x": 246,
      "y": 514,
      "width": 530,
      "height": 138,
      "text": "CSE 3202",
      "day": "Tuesday",
      "slot_count": 3,
      "calculated_width_ratio": 2.717948717948718
    },
    {
      "x": 894,
      "y": 514,
      "width": 244,
      "height": 137,
      "text": "CSE 3209",
      "day": "Tuesday",
      "slot_count": 1,
      "calculated_width_ratio": 1.2512820512820513
    },
    {
      "x": 1144,
      "y": 514,
      "width": 194,
      "height": 137,
      "text": "CSE 3205",
      "day": "Tuesday",
      "slot_count": 1,
      "calculated_width_ratio": 0.9948717948717949
    },
    {
      "x": 1456,
      "y": 514,
      "width": 498,
      "height": 137,
      "text": "CSE 3200",
      "day": "Tuesday",
      "slot_count": 3,
      "calculated_width_ratio": 2.5538461538461537
    },
    {
      "x": 246,
      "y": 656,
      "width": 172,
      "height": 146,
      "text": "CSE 3205",
      "day": "Wednesday",
      "slot_count": 1,
      "calculated_width_ratio": 0.882051282051282
    },
    {
      "x": 423,
      "y": 656,
      "width": 174,
      "height": 146,
      "text": "CSE 3201",
      "day": "Wednesday",
      "slot_count": 1,
      "calculated_width_ratio": 0.8923076923076924
    },
    {
      "x": 602,
      "y": 656,
      "width": 174,
      "height": 146,
      "text": "CSE 3203",
      "day": "Wednesday",
      "slot_count": 1,
      "calculated_width_ratio": 0.8923076923076924
    },
    {
      "x": 894,
      "y": 656,
      "width": 444,
      "height": 146,
      "text": "CSE 3208",
      "day": "Wednesday",
      "slot_count": 2,
      "calculated_width_ratio": 2.276923076923077
    },
    {
      "x": 1456,
      "y": 656,
      "width": 182,
      "height": 146,
      "text": "CSE 3208",
      "day": "Wednesday",
      "slot_count": 1,
      "calculated_width_ratio": 0.9333333333333333
    },
    {
      "x": 246,
      "y": 807,
      "width": 172,
      "height": 147,
      "text": "CSE 3207",
      "day": "Thursday",
      "slot_count": 1,
      "calculated_width_ratio": 0.882051282051282
    },
    {
      "x": 423,
      "y": 807,
      "width": 171,
      "height": 147,
      "text": "CSE 3201",
      "day": "Thursday",
      "slot_count": 1,
      "calculated_width_ratio": 0.8769230769230769
    },
    {
      "x": 600,
      "y": 807,
      "width": 176,
      "height": 147,
      "text": "CSE 3205",
      "day": "Thursday",
      "slot_count": 1,
      "calculated_width_ratio": 0.9025641025641026
    },
    {
      "x": 894,
      "y": 807,
      "width": 444,
      "height": 147,
      "text": "CSE 3210",
      "day": "Thursday",
      "slot_count": 2,
      "calculated_width_ratio": 2.276923076923077
    },
    {
      "x": 1456,
      "y": 807,
      "width": 183,
      "height": 147,
      "text": "CSE 3210",
      "day": "Thursday",
      "slot_count": 1,
      "calculated_width_ratio": 0.9384615384615385
    },
    {
      "x": 246,
      "y": 959,
      "width": 530,
      "height": 105,
      "text": "CSE 3206",
      "day": "Friday",
      "slot_count": 3,
      "calculated_width_ratio": 2.717948717948718
    },
    {
      "x": 894,
      "y": 959,
      "width": 444,
      "height": 105,
      "text": "CSE 3207",
      "day": "Friday",
      "slot_count": 2,
      "calculated_width_ratio": 2.276923076923077
    },
    {
      "x": 1284,
      "y": 1315,
      "width": 196,
      "height": 36,
      "text": "CSE 3206",
      "day": "Friday",
      "slot_count": 1,
      "calculated_width_ratio": 1.005128205128205
    },
    {
      "x": 1484,
      "y": 1315,
      "width": 570,
      "height": 36,
      "text": "Computer Networks Sessional",
      "day": "Friday",
      "slot_count": 3,
      "calculated_width_ratio": 2.923076923076923
    }
  ],
  "structured_data": [
    {
      "x": 246,
      "y": 407,
      "width": 172,
      "height": 102,
      "text": "CSE 3201",
      "day": "Monday",
      "slot_count": 1
    },
    {
      "x": 423,
      "y": 407,
      "width": 353,
      "height": 102,
      "text": "CSE 3203",
      "day": "Monday",
      "slot_count": 2
    },
    {
      "x": 246,
      "y": 514,
      "width": 530,
      "height": 138,
      "text": "CSE 3202",
      "day": "Tuesday",
      "slot_count": 3
    },
    {
      "x": 894,
      "y": 514,
      "width": 244,
      "height": 137,
      "text": "CSE 3209",
      "day": "Tuesday",
      "slot_count": 1
    },
    {
      "x": 1144,
      "y": 514,
      "width": 194,
      "height": 137,
      "text": "CSE 3205",
      "day": "Tuesday",
      "slot_count": 1
    },
    {
      "x": 1456,
      "y": 514,
      "width": 498,
      "height": 137,
      "text": "CSE 3200",
      "day": "Tuesday",
      "slot_count": 3
    },
    {
      "x": 246,
      "y": 656,
      "width": 172,
      "height": 146,
      "text": "CSE 3205",
      "day": "Wednesday",
      "slot_count": 1
    },
    {
      "x": 423,
      "y": 656,
      "width": 174,
      "height": 146,
      "text": "CSE 3201",
      "day": "Wednesday",
      "slot_count": 1
    },
    {
      "x": 602,
      "y": 656,
      "width": 174,
      "height": 146,
      "text": "CSE 3203",
      "day": "Wednesday",
      "slot_count": 1
    },
    {
      "x": 894,
      "y": 656,
      "width": 444,
      "height": 146,
      "text": "CSE 3208",
      "day": "Wednesday",
      "slot_count": 2
    },
    {
      "x": 1456,
      "y": 656,
      "width": 182,
      "height": 146,
      "text": "CSE 3208",
      "day": "Wednesday",
      "slot_count": 1
    },
    {
      "x": 246,
      "y": 807,
      "width": 172,
      "height": 147,
      "text": "CSE 3207",
      "day": "Thursday",
      "slot_count": 1
    },
    {
      "x": 423,
      "y": 807,
      "width": 171,
      "height": 147,
      "text": "CSE 3201",
      "day": "Thursday",
      "slot_count": 1
    },
    {
      "x": 600,
      "y": 807,
      "width": 176,
      "height": 147,
      "text": "CSE 3205",
      "day": "Thursday",
      "slot_count": 1
    },
    {
      "x": 894,
      "y": 807,
      "width": 444,
      "height": 147,
      "text": "CSE 3210",
      "day": "Thursday",
      "slot_count": 2
    },
    {
      "x": 1456,
      "y": 807,
      "width": 183,
      "height": 147,
      "text": "CSE 3210",
      "day": "Thursday",
      "slot_count": 1
    },
    {
      "x": 246,
      "y": 959,
      "width": 530,
      "height": 105,
      "text": "CSE 3206",
      "day": "Friday",
      "slot_count": 3
    },
    {
      "x": 894,
      "y": 959,
      "width": 444,
      "height": 105,
      "text": "CSE 3207",
      "day": "Friday",
      "slot_count": 2
    },
    {
      "x": 1284,
      "y": 1315,
      "width": 196,
      "height": 36,
      "text": "CSE 3206",
      "day": "Friday",
      "slot_count": 1
    },
    {
      "x": 1484,
      "y": 1315,
      "width": 570,
      "height": 36,
      "text": "Computer Networks Sessional",
      "day": "Friday",
      "slot_count": 3
    }
  ],
  "base_width": 195.0,
  "error": null
}
    
    result = SlotCountService.merge_slot_data_with_parsed_data(parsed_data_dict, slot_data)
    print("Input parsed_data:")
    print(json.dumps(parsed_data_dict, indent=2, default=str))
    print("\nSlot data structured_data:")
    print(json.dumps(slot_data['structured_data'], indent=2, default=str))
    print("\nResult after merge:")
    print(json.dumps(result['routine_data'], indent=2, default=str))
    
    # Verify slot_count was added
    monday_entries = result['routine_data']['Monday']
    print(f"\n✓ Monday entry 0 slot_count: {monday_entries[0].get('slot_count')} (expected: 1)")
    print(f"✓ Monday entry 1 slot_count: {monday_entries[1].get('slot_count')} (expected: 2)")
    
    # Test Case 2: Parsed data as list
    print("\n" + "=" * 80)
    print("Test Case 2: List of entries")
    parsed_data_list = [
        {'day': 'Monday', 'slot': 0, 'course': 'CSE 3201', 'teacher': 'SI', 'room': 'Room- 104'},
        {'day': 'Monday', 'slot': 1, 'course': 'CSE 3203', 'teacher': 'NH', 'room': 'Room- 104'},
        {'day': 'Tuesday', 'slot': 0, 'course': 'CSE 3202', 'teacher': 'SI', 'room': 'Room-305'},
    ]
    
    result_list = SlotCountService.merge_slot_data_with_parsed_data(parsed_data_list, slot_data)
    print("Input parsed_data:")
    print(json.dumps(parsed_data_list, indent=2, default=str))
    print("\nResult after merge:")
    print(json.dumps(result_list, indent=2, default=str))
    
    # Verify slot_count was added
    print(f"\n✓ Entry 0 slot_count: {result_list[0].get('slot_count')} (expected: 1)")
    print(f"✓ Entry 1 slot_count: {result_list[1].get('slot_count')} (expected: 2)")
    print(f"✓ Entry 2 slot_count: {result_list[2].get('slot_count')} (expected: 1)")
    
    # Test Case 3: Error handling
    print("\n" + "=" * 80)
    print("Test Case 3: Error handling (slot_data with error)")
    slot_data_error = {
        'error': 'Failed to extract',
        'cells': [],
        'base_width': None,
        'structured_data': []
    }
    
    result_error = SlotCountService.merge_slot_data_with_parsed_data(parsed_data_list, slot_data_error)
    print("Result when slot_data has error:")
    print(json.dumps(result_error, indent=2, default=str))
    
    # Test Case 4: No structured data
    print("\n" + "=" * 80)
    print("Test Case 4: Empty structured_data")
    slot_data_empty = {
        'cells': [],
        'base_width': None,
        'structured_data': [],
        'error': None
    }
    
    result_empty = SlotCountService.merge_slot_data_with_parsed_data(parsed_data_list, slot_data_empty)
    print("Result when structured_data is empty:")
    print(json.dumps(result_empty, indent=2, default=str))
    print(f"✓ All entries have slot_count set to 1 (default)")
    
    print("\n" + "=" * 80)
    print("All tests completed!")
    print("=" * 80)
