"""
Create transformation layer tool for the AGS SPARQL Agent.

This tool creates a new transformation layer with proper ordering and
metadata for organizing data transformation steps.
"""

import os
import sys
import uuid
from datetime import datetime

# Add src directory to path for imports
src_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
if src_dir not in sys.path:
    sys.path.insert(0, src_dir)

from ..base_tool import BaseToolMixin, handle_tool_errors, ToolError
from ...utils.agent_utils import get_agent, get_graphmart_uri


@handle_tool_errors
async def create_transformation_layer(
    layer_name: str,
    layer_description: str,
    graphmart_uri: str = None,
    order_after: str = None,
    explanation: str = None,
    dry_run: bool = False
) -> str:
    """Create a new transformation layer in the specified graphmart.
    
    This tool creates a new transformation layer with proper ordering and
    metadata for organizing data transformation steps.
    
    Args:
        layer_name: Human-readable name for the layer (e.g., "ERP Linking")
        layer_description: Description of what this layer does
        graphmart_uri: URI of the graphmart (optional, auto-detects)
        order_after: Layer name to put this layer after (optional, defaults to end)
        explanation: Human-readable description of the operation (required)
        dry_run: If true, validate inputs without executing
        
    Returns:
        JSON response with layer creation results
    """
    BaseToolMixin.validate_required_param(layer_name, "layer_name")
    BaseToolMixin.validate_required_param(layer_description, "layer_description")
    BaseToolMixin.validate_required_param(explanation, "explanation")
    
    # Auto-detect graphmart URI if not provided
    graphmart_uri = get_graphmart_uri(graphmart_uri)
    
    # Generate unique URIs for the layer and ordered item
    layer_uuid = str(uuid.uuid4()).replace('-', '')
    ordered_item_uuid = str(uuid.uuid4()).replace('-', '')
    
    layer_uri = f"http://cambridgesemantics.com/Layer/{layer_uuid}"
    ordered_item_uri = f"http://cambridgesemantics.com/OrderedItem/{ordered_item_uuid}"
    
    # Dry run mode
    if dry_run:
        return BaseToolMixin.create_success_response({
            "dry_run": True,
            "layer_name": layer_name,
            "layer_uri": layer_uri,
            "ordered_item_uri": ordered_item_uri,
            "graphmart_uri": graphmart_uri,
            "explanation": explanation
        }, "Layer creation validated. Set dry_run=false to execute.")
    
    agent = await get_agent()
    
    # Get current timestamp for metadata
    current_timestamp = datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
    
    # Get current highest index to determine next index
    try:
        index_query = f"""
        PREFIX anzo: <http://openanzo.org/ontologies/2008/07/Anzo#>
        PREFIX gm: <http://cambridgesemantics.com/ontologies/Graphmarts#>
        
        SELECT ?index WHERE {{
            GRAPH <{graphmart_uri}> {{
                <{graphmart_uri}> gm:layer ?orderedItem .
                ?orderedItem anzo:index ?index .
            }}
        }}
        """
        index_result = agent.anzo_client.query_journal(index_query)
        
        # Parse all indices and find the maximum numerically
        next_index = 0
        table_results = index_result.as_table_results().as_list()
        
        if table_results:
            indices = []
            for result_row in table_results:
                if result_row and len(result_row) > 0:
                    index_value = result_row[0]
                    try:
                        indices.append(int(index_value))
                    except (ValueError, TypeError):
                        BaseToolMixin.log_warning(f"Skipping non-numeric index: {index_value}")
            
            if indices:
                next_index = max(indices) + 1
                
    except Exception as index_error:
        BaseToolMixin.log_warning(f"Index query failed: {index_error}")
        next_index = 0
    
    # Create the layer and its metadata
    layer_creation_sparql = f"""
    PREFIX gm: <http://cambridgesemantics.com/ontologies/Graphmarts#>
    PREFIX dc: <http://purl.org/dc/elements/1.1/>
    PREFIX dct: <http://purl.org/dc/terms/>
    PREFIX anzo: <http://openanzo.org/ontologies/2008/07/Anzo#>
    
    INSERT DATA {{
        GRAPH <{graphmart_uri}> {{
            <{layer_uri}> a gm:Layer ;
                         dc:title "{layer_name}" ;
                         dc:description "{layer_description}" ;
                         gm:enabled "true"^^<http://www.w3.org/2001/XMLSchema#boolean> ;
                         gm:visible "true"^^<http://www.w3.org/2001/XMLSchema#boolean> ;
                         gm:exposed "true"^^<http://www.w3.org/2001/XMLSchema#boolean> ;
                         gm:defaultSelected "true"^^<http://www.w3.org/2001/XMLSchema#boolean> ;
                         gm:canExclude "true"^^<http://www.w3.org/2001/XMLSchema#boolean> ;
                         gm:dataAclsInheritFrom <{graphmart_uri}> ;
                         dct:created "{current_timestamp}" ;
                         dct:creator <http://openanzo.org/system/internal/sysadmin> ;
                         dct:modified "{current_timestamp}" ;
                         dct:modifier <http://openanzo.org/system/internal/sysadmin> .
            
            <{ordered_item_uri}> a anzo:OrderedItem ;
                                anzo:orderedValue <{layer_uri}> ;
                                anzo:index {next_index} ;
                                dct:created "{current_timestamp}" ;
                                dct:creator <http://openanzo.org/system/internal/sysadmin> ;
                                dct:modified "{current_timestamp}" ;
                                dct:modifier <http://openanzo.org/system/internal/sysadmin> .
            
            <{graphmart_uri}> gm:layer <{ordered_item_uri}> .
        }}
    }}
    """
    
    # Execute the layer creation
    agent.anzo_client.update_journal(layer_creation_sparql)
    
    return BaseToolMixin.create_success_response({
        "layer_name": layer_name,
        "layer_uri": layer_uri,
        "ordered_item_uri": ordered_item_uri,
        "layer_index": next_index,
        "graphmart_uri": graphmart_uri,
        "explanation": explanation
    }, f"Successfully created transformation layer '{layer_name}'")