"""
Add SELECT-based transformation step tool for the AGS SPARQL Agent.

This tool takes a SELECT query and automatically wraps it in the required
INSERT { GRAPH ${targetGraph} { ... } } pattern for AGS transformation steps.
"""

import os
import sys
import re

from ..base_tool import BaseToolMixin, handle_tool_errors, ToolError
from .add_transformation_step import add_transformation_step


@handle_tool_errors
async def add_select_step(
    layer_name_or_uri: str,
    step_name: str,
    select_query: str,
    explanation: str,
    graphmart_uri: str = None,
    dry_run: bool = False
) -> str:
    """Create a transformation step from a SELECT query by auto-converting it to INSERT format.
    
    This is a convenience tool for users who have a SELECT query and want to 
    materialize its results into the graphmart. It automatically wraps the query
    in the AGS-required INSERT { GRAPH ${targetGraph} { ... } } pattern.
    
    The SELECT clause variables become the triple pattern in the INSERT.
    For example:
        SELECT ?s ?p ?o WHERE { ?s ?p ?o }
    Becomes:
        INSERT { GRAPH ${targetGraph} { ?s ?p ?o . } }
        ${usingSources}
        WHERE { ?s ?p ?o }
    
    Args:
        layer_name_or_uri: Layer name or full URI to add step to
        step_name: Human-readable name for the step
        select_query: A SPARQL SELECT query to convert
        explanation: Human-readable description of the operation
        graphmart_uri: URI of the graphmart (optional, auto-detects)
        dry_run: If true, show converted query without executing
        
    Returns:
        JSON response with query step creation results
    """
    BaseToolMixin.validate_required_param(layer_name_or_uri, "layer_name_or_uri")
    BaseToolMixin.validate_required_param(step_name, "step_name")
    BaseToolMixin.validate_required_param(select_query, "select_query")
    BaseToolMixin.validate_required_param(explanation, "explanation")
    
    # Extract PREFIX declarations
    prefix_pattern = re.compile(r'(PREFIX\s+\S+\s+<[^>]+>)', re.IGNORECASE)
    prefixes = prefix_pattern.findall(select_query)
    prefix_block = '\n'.join(prefixes)
    
    # Remove prefixes from query for processing
    query_body = prefix_pattern.sub('', select_query).strip()
    
    # Extract SELECT variables  
    select_match = re.match(
        r'SELECT\s+(DISTINCT\s+)?(.*?)\s+WHERE\s*\{',
        query_body,
        re.IGNORECASE | re.DOTALL
    )
    
    if not select_match:
        raise ToolError(
            "Could not parse SELECT query. Expected format: "
            "SELECT ?var1 ?var2 ... WHERE { ... }"
        )
    
    select_vars = select_match.group(2).strip()
    
    # Extract WHERE clause content
    where_match = re.search(
        r'WHERE\s*\{(.+)\}\s*$',
        query_body,
        re.IGNORECASE | re.DOTALL
    )
    
    if not where_match:
        raise ToolError("Could not parse WHERE clause from SELECT query.")
    
    where_body = where_match.group(1).strip()
    
    # Build triple pattern for INSERT from SELECT variables
    vars_list = select_vars.split()
    if len(vars_list) == 3:
        # Standard ?s ?p ?o pattern
        triple_pattern = f"{vars_list[0]} {vars_list[1]} {vars_list[2]} ."
    elif select_vars.strip() == '*':
        # SELECT * - use ?s ?p ?o and assume that's in the WHERE
        triple_pattern = "?s ?p ?o ."
    else:
        # Custom variables - create triples binding them
        triple_pattern = f"{' '.join(vars_list)} ."

    # Build the INSERT query
    insert_query = f"""{prefix_block}
INSERT {{
    GRAPH ${{targetGraph}} {{
        {triple_pattern}
    }}
}}
${{usingSources}}
WHERE {{
    {where_body}
}}""".strip()
    
    if dry_run:
        return BaseToolMixin.create_success_response({
            "original_select": select_query,
            "converted_insert": insert_query,
            "mode": "dry_run"
        }, "SELECT query converted to INSERT format (dry run - not executed)")
    
    # Delegate to the standard add_transformation_step
    return await add_transformation_step(
        layer_name_or_uri=layer_name_or_uri,
        step_name=step_name,
        insert_query=insert_query,
        explanation=explanation,
        graphmart_uri=graphmart_uri,
        dry_run=False
    )
