"""
Add Ontology Property tool for the AGS SPARQL Agent.

This tool handles add ontology property operations.
"""

import os
import sys
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


async def add_ontology_property(
    ontology_uri: str,
    property_uri: str,
    property_type: str,
    property_label: str = None,
    property_description: str = None,
    domain_uri: str = None,
    range_uri: str = None,
    superproperty_uri: str = None,
    explanation: str = None,
    dry_run: bool = False
    ) -> str:
    """Add a new property to an ontology.
    
    This tool adds an OWL property with optional metadata and domain/range restrictions.
    
    Args:
        ontology_uri: URI of the ontology to add the property to (required)
        property_uri: URI of the new property (required)
        property_type: Type of property - "object", "datatype", or "annotation" (required)
        property_label: Human-readable label for the property
        property_description: Description of the property purpose
        domain_uri: URI of the domain class (optional)
        range_uri: URI of the range class or datatype (optional)
        superproperty_uri: URI of the superproperty (optional)
        explanation: Human-readable description of the operation
        dry_run: If true, validate inputs without executing
        
    Returns:
        JSON response with property addition results
    """
    BaseToolMixin.validate_required_param(ontology_uri, "ontology_uri")
    BaseToolMixin.validate_required_param(property_uri, "property_uri")
    BaseToolMixin.validate_required_param(property_type, "property_type")
    BaseToolMixin.validate_uri(ontology_uri, "ontology_uri")
    BaseToolMixin.validate_uri(property_uri, "property_uri")
    
    if property_type not in ["object", "datatype", "annotation"]:
        raise ToolError(f"Invalid property_type '{property_type}'. Must be 'object', 'datatype', or 'annotation'")
    
    if domain_uri:
        BaseToolMixin.validate_uri(domain_uri, "domain_uri")
    if range_uri:
        BaseToolMixin.validate_uri(range_uri, "range_uri")
    if superproperty_uri:
        BaseToolMixin.validate_uri(superproperty_uri, "superproperty_uri")
    
    agent = await get_agent()
    
    # Check if ontology exists
    exists_query = f"SELECT ?o WHERE {{ GRAPH <{ontology_uri}> {{ <{ontology_uri}> a ?o }} }}"
    exists_result = agent.anzo_client.query_journal(exists_query)
    table_results = exists_result.as_table_results().as_list()
    ontology_exists = len(table_results) > 0
    
    if not ontology_exists:
        raise ToolError(f"Ontology '{ontology_uri}' not found")
    
    # Map property type to OWL class
    property_class_map = {
        "object": "http://www.w3.org/2002/07/owl#ObjectProperty",
        "datatype": "http://www.w3.org/2002/07/owl#DatatypeProperty", 
        "annotation": "http://www.w3.org/2002/07/owl#AnnotationProperty"
    }
    property_class = property_class_map[property_type]
    
    # Check if property already exists
    property_exists_query = f"SELECT ?type WHERE {{ GRAPH <{ontology_uri}> {{ <{property_uri}> a ?type . FILTER(?type = <{property_class}>) }} }}"
    property_exists_result = agent.anzo_client.query_journal(property_exists_query)
    table_results = property_exists_result.as_table_results().as_list()
    property_already_exists = len(table_results) > 0
    
    if property_already_exists:
        return BaseToolMixin.create_success_response({
            "ontology_uri": ontology_uri,
            "property_uri": property_uri,
            "property_type": property_type,
            "already_exists": True,
            "explanation": explanation
        }, f"Property '{property_uri}' already exists in ontology '{ontology_uri}'")
    
    # Dry run mode
    if dry_run:
        return BaseToolMixin.create_success_response({
            "dry_run": True,
            "ontology_uri": ontology_uri,
            "property_uri": property_uri,
            "property_type": property_type,
            "property_label": property_label,
            "property_description": property_description,
            "domain_uri": domain_uri,
            "range_uri": range_uri,
            "superproperty_uri": superproperty_uri,
            "explanation": explanation
        }, "Property addition validated. Set dry_run=false to execute.")
    
    # Get current timestamp for metadata
    current_timestamp = datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
    
    # Build the property definition
    property_triples = [f"<{property_uri}> a <{property_class}>"]
    
    if property_label:
        property_triples.append(f'<{property_uri}> <http://www.w3.org/2000/01/rdf-schema#label> "{property_label}"')
    
    if property_description:
        property_triples.append(f'<{property_uri}> <http://purl.org/dc/elements/1.1/description> "{property_description}"')
    
    if domain_uri:
        property_triples.append(f"<{property_uri}> <http://www.w3.org/2000/01/rdf-schema#domain> <{domain_uri}>")
    
    if range_uri:
        property_triples.append(f"<{property_uri}> <http://www.w3.org/2000/01/rdf-schema#range> <{range_uri}>")
    
    if superproperty_uri:
        property_triples.append(f"<{property_uri}> <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <{superproperty_uri}>")
    
    # Add metadata
    property_triples.extend([
        f'<{property_uri}> <http://purl.org/dc/terms/created> "{current_timestamp}"',
        f'<{property_uri}> <http://purl.org/dc/terms/creator> <http://openanzo.org/system/internal/sysadmin>',
        f'<{ontology_uri}> <http://purl.org/dc/terms/modified> "{current_timestamp}"',
        f'<{ontology_uri}> <http://purl.org/dc/terms/modifier> <http://openanzo.org/system/internal/sysadmin>'
    ])
    
    # Create the INSERT statement
    add_property_sparql = f"""
    PREFIX owl: <http://www.w3.org/2002/07/owl#>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    PREFIX dc: <http://purl.org/dc/elements/1.1/>
    PREFIX dct: <http://purl.org/dc/terms/>
    
    INSERT DATA {{
        GRAPH <{ontology_uri}> {{
            {' . '.join(property_triples)} .
        }}
    }}
    """
    
    # Execute the property addition
    agent.anzo_client.update_journal(add_property_sparql)
    
    return BaseToolMixin.create_success_response({
        "ontology_uri": ontology_uri,
        "property_uri": property_uri,
        "property_type": property_type,
        "property_label": property_label,
        "property_description": property_description,
        "domain_uri": domain_uri,
        "range_uri": range_uri,
        "superproperty_uri": superproperty_uri,
        "added_timestamp": current_timestamp,
        "explanation": explanation
    }, f"Successfully added {property_type} property '{property_uri}' to ontology '{ontology_uri}'")