#!/usr/bin/env python3
"""
Create Elasticsearch Index from Mapping File
==============================================
Creates an empty Elasticsearch index using a mapping from a JSON file.

Usage:
    python create_index.py --mapping mapping.json
    python create_index.py --mapping mapping.json --index new_index_name
    python create_index.py --mapping mapping.json --index new_index_name --overwrite
"""

import os
import sys
import json
import argparse
from typing import Dict, Any

try:
    from elasticsearch import Elasticsearch
except ImportError:
    print("ERROR: elasticsearch package not installed.")
    print("Run: pip install elasticsearch")
    sys.exit(1)

try:
    from dotenv import load_dotenv
except ImportError:
    load_dotenv = lambda: None


def load_config() -> Dict[str, str]:
    """Load configuration from .env file."""
    load_dotenv()
    return {
        'es_host': os.getenv('TARGET_ES_HOST', 'http://localhost:9200'),
    }


def connect_elasticsearch(host: str) -> Elasticsearch:
    """Create Elasticsearch connection."""
    es = Elasticsearch(
        hosts=[host],
        verify_certs=False,
        request_timeout=60,
    )
    
    if not es.ping():
        raise ConnectionError(f"Cannot connect to Elasticsearch at {host}")
    
    info = es.info()
    print(f"✅ Connected to Elasticsearch {info['version']['number']}")
    return es


def load_mapping_file(mapping_file: str) -> Dict[str, Any]:
    """Load mapping from JSON file."""
    with open(mapping_file, 'r', encoding='utf-8') as f:
        return json.load(f)


def create_index(
    es: Elasticsearch,
    mapping_file: str,
    index_name: str = None,
    overwrite: bool = False
) -> str:
    """
    Create an empty index with the given mapping.
    
    Returns the created index name.
    """
    # Load mapping from file
    print(f"📋 Loading mapping from: {mapping_file}")
    mapping_data = load_mapping_file(mapping_file)
    
    # Determine index name
    original_index = mapping_data.get('index', 'unnamed_index')
    target_index = index_name or original_index
    
    print(f"   Source index: {original_index}")
    print(f"   Target index: {target_index}")
    
    # Check if index exists
    if es.indices.exists(index=target_index):
        if overwrite:
            print(f"\n⚠️  Index '{target_index}' exists. Deleting...")
            es.indices.delete(index=target_index)
        else:
            raise ValueError(
                f"Index '{target_index}' already exists. "
                f"Use --overwrite to delete it, or --index to specify a different name."
            )
    
    # Build create body
    create_body = {}
    
    if 'mappings' in mapping_data:
        create_body['mappings'] = mapping_data['mappings']
    
    if 'settings' in mapping_data:
        # Clean up settings (remove read-only settings)
        settings = mapping_data['settings']
        if 'index' in settings:
            index_settings = settings['index'].copy()
            readonly_settings = [
                'creation_date', 'provided_name', 'uuid', 'version',
                'resize', 'routing', 'verified_before_close'
            ]
            for key in readonly_settings:
                index_settings.pop(key, None)
            create_body['settings'] = {'index': index_settings}
    
    # Create index
    print(f"\n🔧 Creating index '{target_index}'...")
    es.indices.create(index=target_index, body=create_body)
    
    # Verify
    if es.indices.exists(index=target_index):
        print(f"✅ Index '{target_index}' created successfully!")
        
        # Show field count
        mapping = es.indices.get_mapping(index=target_index)
        field_count = len(mapping[target_index]['mappings'].get('properties', {}))
        print(f"   Fields: {field_count}")
    
    return target_index


def main():
    parser = argparse.ArgumentParser(description='Create Elasticsearch index from mapping file')
    parser.add_argument('--mapping', '-m', required=True, help='Path to mapping JSON file')
    parser.add_argument('--index', '-i', help='Target index name (default: from mapping file)')
    parser.add_argument('--host', '-H', help='Elasticsearch host URL')
    parser.add_argument('--overwrite', action='store_true', help='Overwrite if index exists')
    
    args = parser.parse_args()
    
    config = load_config()
    es_host = args.host or config['es_host']
    
    print(f"""
╔══════════════════════════════════════════════════════════════════╗
║           CREATE ELASTICSEARCH INDEX                              ║
╚══════════════════════════════════════════════════════════════════╝
    """)
    
    print(f"🔧 Configuration:")
    print(f"   Host: {es_host.split('@')[-1] if '@' in es_host else es_host}")
    print(f"   Mapping: {args.mapping}")
    if args.index:
        print(f"   Target: {args.index}")
    
    try:
        es = connect_elasticsearch(es_host)
        create_index(es, args.mapping, args.index, args.overwrite)
        print("\n🎉 Done!")
        return 0
        
    except Exception as e:
        print(f"\n❌ Error: {e}")
        return 1


if __name__ == '__main__':
    sys.exit(main())
