#!/usr/bin/env python3
"""
Schema Validation Script for mail2couch

This script validates that the CouchDB document schemas are consistent
between the Go implementation and the documented JSON examples.
"""

import json
import sys
from pathlib import Path

def load_json_file(file_path):
    """Load and parse a JSON file."""
    try:
        with open(file_path, 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        print(f"ERROR: File not found: {file_path}")
        return None
    except json.JSONDecodeError as e:
        print(f"ERROR: Invalid JSON in {file_path}: {e}")
        return None

def validate_mail_document(doc, filename):
    """Validate a mail document structure."""
    required_fields = [
        '_id', 'sourceUid', 'mailbox', 'from', 'to', 'subject', 
        'date', 'body', 'headers', 'storedAt', 'docType', 'hasAttachments'
    ]
    
    errors = []
    
    # Check required fields
    for field in required_fields:
        if field not in doc:
            errors.append(f"Missing required field: {field}")
    
    # Check field types
    if 'docType' in doc and doc['docType'] != 'mail':
        errors.append(f"Invalid docType: expected 'mail', got '{doc['docType']}'")
    
    if 'from' in doc and not isinstance(doc['from'], list):
        errors.append("Field 'from' must be an array")
    
    if 'to' in doc and not isinstance(doc['to'], list):
        errors.append("Field 'to' must be an array")
    
    if 'headers' in doc and not isinstance(doc['headers'], dict):
        errors.append("Field 'headers' must be an object")
    
    if 'hasAttachments' in doc and not isinstance(doc['hasAttachments'], bool):
        errors.append("Field 'hasAttachments' must be a boolean")
    
    # Check _id format
    if '_id' in doc:
        doc_id = doc['_id']
        if '_' not in doc_id:
            errors.append(f"Document ID '{doc_id}' should follow format 'mailbox_uid'")
    
    # Validate attachments if present
    if '_attachments' in doc:
        if not isinstance(doc['_attachments'], dict):
            errors.append("Field '_attachments' must be an object")
        else:
            for filename, stub in doc['_attachments'].items():
                if 'content_type' not in stub:
                    errors.append(f"Attachment '{filename}' missing content_type")
    
    if errors:
        print(f"ERRORS in {filename}:")
        for error in errors:
            print(f"  - {error}")
        return False
    else:
        print(f"✓ {filename}: Valid mail document")
        return True

def validate_sync_metadata(doc, filename):
    """Validate a sync metadata document structure."""
    required_fields = [
        '_id', 'docType', 'mailbox', 'lastSyncTime', 
        'lastMessageUID', 'messageCount', 'updatedAt'
    ]
    
    errors = []
    
    # Check required fields
    for field in required_fields:
        if field not in doc:
            errors.append(f"Missing required field: {field}")
    
    # Check field types
    if 'docType' in doc and doc['docType'] != 'sync_metadata':
        errors.append(f"Invalid docType: expected 'sync_metadata', got '{doc['docType']}'")
    
    if 'lastMessageUID' in doc and not isinstance(doc['lastMessageUID'], int):
        errors.append("Field 'lastMessageUID' must be an integer")
    
    if 'messageCount' in doc and not isinstance(doc['messageCount'], int):
        errors.append("Field 'messageCount' must be an integer")
    
    # Check _id format
    if '_id' in doc:
        doc_id = doc['_id']
        if not doc_id.startswith('sync_metadata_'):
            errors.append(f"Document ID '{doc_id}' should start with 'sync_metadata_'")
    
    if errors:
        print(f"ERRORS in {filename}:")
        for error in errors:
            print(f"  - {error}")
        return False
    else:
        print(f"✓ {filename}: Valid sync metadata document")
        return True

def main():
    """Main validation function."""
    script_dir = Path(__file__).parent
    project_root = script_dir.parent
    examples_dir = project_root / "examples"
    
    print("Validating CouchDB document schemas...")
    print("=" * 50)
    
    all_valid = True
    
    # Validate mail documents
    mail_files = [
        "sample-mail-document.json",
        "simple-mail-document.json"
    ]
    
    for filename in mail_files:
        file_path = examples_dir / filename
        doc = load_json_file(file_path)
        if doc is None:
            all_valid = False
            continue
        
        if not validate_mail_document(doc, filename):
            all_valid = False
    
    # Validate sync metadata
    sync_files = [
        "sample-sync-metadata.json"
    ]
    
    for filename in sync_files:
        file_path = examples_dir / filename
        doc = load_json_file(file_path)
        if doc is None:
            all_valid = False
            continue
        
        if not validate_sync_metadata(doc, filename):
            all_valid = False
    
    print("=" * 50)
    if all_valid:
        print("✓ All schemas are valid!")
        sys.exit(0)
    else:
        print("✗ Schema validation failed!")
        sys.exit(1)

if __name__ == "__main__":
    main()