"""
Why Analysis Tool - Exposes the explainability system to the LangGraph agent.

This tool provides the agent with the ability to answer "why" questions
about chess moves and positions using the comprehensive Why Engine.
"""

import chess
import json
import sys
import os

sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))

from explainability_service import ExplainabilityService, ExplanationResult


# Singleton service for reuse
_service = None


def get_service() -> ExplainabilityService:
    """Get or create the explainability service."""
    global _service
    if _service is None:
        _service = ExplainabilityService(engine_depth=16)
    return _service


def cleanup_service():
    """Clean up the explainability service and release resources."""
    global _service
    if _service is not None:
        _service.close()
        _service = None


def explain_move(fen: str, move: str) -> dict:
    """
    Explain why a specific move is good or bad.
    
    Provides comprehensive analysis including:
    - What the move achieves
    - Its strategic/tactical intent
    - Comparison to the best move
    - Evidence from evaluation
    
    Args:
        fen: Position in FEN notation
        move: Move to analyze (SAN notation, e.g., "Nf3", "Bxh7+")
        
    Returns:
        Dictionary with full move explanation
    """
    try:
        service = get_service()
        
        # Analyze the move
        question = f"Why is {move} good or bad in this position?"
        result = service.explain(question, fen, played_move=move)
        
        return {
            'success': True,
            'move': move,
            'is_best_move': result.detailed_analysis.get('is_best', False),
            'intent': result.detailed_analysis.get('intent', 'unknown'),
            'evaluation': result.evaluation,
            'evaluation_description': result.evaluation_description,
            'summary': result.answer_summary,
            'achievements': result.detailed_analysis.get('achievements', []),
            'threats_created': result.detailed_analysis.get('threats_created', []),
            'is_sacrifice': result.detailed_analysis.get('is_sacrifice', False),
            'tactical_patterns': result.detailed_analysis.get('tactical_patterns', []),
            'evidence': result.evidence,
            'best_move': result.best_move,
            'principal_variation': result.principal_variation,
            'learning_points': result.learning_points,
        }
        
    except Exception as e:
        return {
            'success': False,
            'error': str(e),
            'move': move
        }


def explain_why_bad(fen: str, move: str) -> dict:
    """
    Explain specifically why a move is a mistake.
    
    Analyzes:
    - What's wrong with the move
    - What the refutation is
    - What would be better
    - How much advantage is lost
    
    Args:
        fen: Position in FEN notation
        move: The questionable move (SAN notation)
        
    Returns:
        Dictionary explaining why the move is problematic
    """
    try:
        service = get_service()
        
        from query_understanding import ParsedQuery, QueryType
        query = ParsedQuery(
            query_type=QueryType.WHY_BAD,
            original_question=f"Why is {move} bad?",
            primary_move=move
        )
        
        result = service._explain_why_bad(query, fen, move)
        
        return {
            'success': True,
            'move': move,
            'summary': result.answer_summary,
            'mistake_category': result.detailed_analysis.get('mistake_category', 'unknown'),
            'refutation': result.detailed_analysis.get('refutation'),
            'eval_loss': result.comparison.get('eval_loss', 0),
            'better_move': result.comparison.get('best_move'),
            'reasons': result.comparison.get('reasons', []),
            'learning_points': result.learning_points,
        }
        
    except Exception as e:
        return {
            'success': False,
            'error': str(e),
            'move': move
        }


def compare_moves(fen: str, move1: str, move2: str) -> dict:
    """
    Compare two moves and explain which is better and why.
    
    Args:
        fen: Position in FEN notation
        move1: First move to compare (SAN)
        move2: Second move to compare (SAN)
        
    Returns:
        Dictionary with move comparison analysis
    """
    try:
        service = get_service()
        
        from query_understanding import ParsedQuery, QueryType
        query = ParsedQuery(
            query_type=QueryType.COMPARE_MOVES,
            original_question=f"Compare {move1} vs {move2}",
            primary_move=move1,
            comparison_move=move2
        )
        
        result = service._compare_moves(query, fen)
        
        return {
            'success': True,
            'move1': move1,
            'move2': move2,
            'summary': result.answer_summary,
            'better_move': result.comparison.get('better_move'),
            'eval_difference': result.comparison.get('eval_difference', 0),
            'move1_eval': result.detailed_analysis.get('move1_eval'),
            'move2_eval': result.detailed_analysis.get('move2_eval'),
            'move1_intent': result.detailed_analysis.get('move1_intent'),
            'move2_intent': result.detailed_analysis.get('move2_intent'),
            'key_differences': result.comparison.get('key_differences', []),
            'learning_points': result.learning_points,
        }
        
    except Exception as e:
        return {
            'success': False,
            'error': str(e)
        }


def what_to_play(fen: str) -> dict:
    """
    Recommend the best move and explain why.
    
    Args:
        fen: Position in FEN notation
        
    Returns:
        Dictionary with move recommendation and explanation
    """
    try:
        service = get_service()
        
        from query_understanding import ParsedQuery, QueryType
        query = ParsedQuery(
            query_type=QueryType.WHAT_TO_PLAY,
            original_question="What should I play?"
        )
        
        result = service._what_to_play(query, fen)
        
        return {
            'success': True,
            'summary': result.answer_summary,
            'best_move': result.best_move,
            'intent': result.detailed_analysis.get('intent'),
            'achievements': result.detailed_analysis.get('achievements', []),
            'alternatives': result.detailed_analysis.get('alternatives', []),
            'evaluation': result.evaluation,
            'evaluation_description': result.evaluation_description,
            'principal_variation': result.principal_variation,
            'learning_points': result.learning_points,
        }
        
    except Exception as e:
        return {
            'success': False,
            'error': str(e)
        }


def find_tactics(fen: str) -> dict:
    """
    Search for tactical opportunities in the position.
    
    Args:
        fen: Position in FEN notation
        
    Returns:
        Dictionary with tactical findings
    """
    try:
        service = get_service()
        
        from query_understanding import ParsedQuery, QueryType
        query = ParsedQuery(
            query_type=QueryType.FIND_TACTIC,
            original_question="Is there a tactic here?"
        )
        
        result = service._find_tactics(query, fen)
        
        return {
            'success': True,
            'summary': result.answer_summary,
            'has_tactic': result.detailed_analysis.get('has_tactic', False),
            'tactical_move': result.detailed_analysis.get('tactical_move'),
            'patterns': result.detailed_analysis.get('patterns', []),
            'evaluation': result.evaluation,
            'principal_variation': result.principal_variation,
            'learning_points': result.learning_points,
        }
        
    except Exception as e:
        return {
            'success': False,
            'error': str(e)
        }


def evaluate_position(fen: str) -> dict:
    """
    Provide a comprehensive position evaluation.
    
    Analyzes:
    - Who is better and by how much
    - Material balance
    - Piece activity
    - King safety
    - Pawn structure
    
    Args:
        fen: Position in FEN notation
        
    Returns:
        Dictionary with position evaluation
    """
    try:
        service = get_service()
        
        from query_understanding import ParsedQuery, QueryType
        query = ParsedQuery(
            query_type=QueryType.EVALUATE,
            original_question="Evaluate this position"
        )
        
        result = service._evaluate_position(query, fen)
        
        return {
            'success': True,
            'summary': result.answer_summary,
            'evaluation': result.evaluation,
            'evaluation_description': result.evaluation_description,
            'material_balance': result.detailed_analysis.get('material_balance', 0),
            'white_mobility': result.detailed_analysis.get('white_mobility', 0),
            'black_mobility': result.detailed_analysis.get('black_mobility', 0),
            'white_development': result.detailed_analysis.get('white_development', 0),
            'black_development': result.detailed_analysis.get('black_development', 0),
            'white_king_attackers': result.detailed_analysis.get('white_king_attackers', 0),
            'black_king_attackers': result.detailed_analysis.get('black_king_attackers', 0),
            'learning_points': result.learning_points,
        }
        
    except Exception as e:
        return {
            'success': False,
            'error': str(e)
        }


def get_plan(fen: str) -> dict:
    """
    Explain the strategic plan in the position.
    
    Args:
        fen: Position in FEN notation
        
    Returns:
        Dictionary with strategic plans
    """
    try:
        service = get_service()
        
        from query_understanding import ParsedQuery, QueryType
        query = ParsedQuery(
            query_type=QueryType.EXPLAIN_PLAN,
            original_question="What is the plan here?"
        )
        
        result = service._explain_plan(query, fen)
        
        return {
            'success': True,
            'summary': result.answer_summary,
            'plans': result.detailed_analysis.get('plans', []),
            'suggested_move': result.detailed_analysis.get('suggested_move'),
            'best_move': result.best_move,
            'learning_points': result.learning_points,
        }
        
    except Exception as e:
        return {
            'success': False,
            'error': str(e)
        }


def explain_concept(concept_name: str) -> dict:
    """
    Explain a chess concept (fork, pin, sacrifice, etc.)
    
    Args:
        concept_name: Name of the concept (e.g., "fork", "pin", "sacrifice")
        
    Returns:
        Dictionary with concept explanation
    """
    try:
        service = get_service()
        
        from query_understanding import ParsedQuery, QueryType
        query = ParsedQuery(
            query_type=QueryType.EXPLAIN_CONCEPT,
            original_question=f"What is a {concept_name}?",
            concept_asked=concept_name
        )
        
        # Use starting position FEN (concept explanations don't need a real position)
        result = service._explain_concept(query, chess.STARTING_FEN)
        
        return {
            'success': True,
            'concept': concept_name,
            'summary': result.answer_summary,
            'category': result.detailed_analysis.get('category'),
            'typical_signs': result.detailed_analysis.get('typical_signs', []),
            'common_patterns': result.detailed_analysis.get('common_patterns', []),
            'learning_points': result.learning_points,
        }
        
    except Exception as e:
        return {
            'success': False,
            'error': str(e),
            'concept': concept_name
        }


def answer_chess_question(fen: str, question: str) -> dict:
    """
    Answer any chess question using the full explainability system.
    
    This is the general-purpose entry point that automatically routes
    to the appropriate analysis based on the question.
    
    Args:
        fen: Current position in FEN notation
        question: User's question about the position
        
    Returns:
        Dictionary with comprehensive answer
    """
    try:
        service = get_service()
        result = service.explain(question, fen)
        
        return {
            'success': True,
            'question': question,
            'question_type': result.question_type,
            'interpreted_as': result.question_interpreted,
            'summary': result.answer_summary,
            'evaluation': result.evaluation,
            'evaluation_description': result.evaluation_description,
            'best_move': result.best_move,
            'evidence': result.evidence,
            'concepts_involved': result.concepts_involved,
            'learning_points': result.learning_points,
            'detailed_analysis': result.detailed_analysis,
        }
        
    except Exception as e:
        return {
            'success': False,
            'error': str(e),
            'question': question
        }


# Tool schemas for LangGraph integration
WHY_TOOL_SCHEMAS = {
    'explain_move': {
        'name': 'explain_move',
        'description': 'Explain why a specific chess move is good or bad. Provides intent, achievements, tactical patterns, and evaluation.',
        'parameters': {
            'type': 'object',
            'properties': {
                'fen': {
                    'type': 'string',
                    'description': 'Position in FEN notation'
                },
                'move': {
                    'type': 'string',
                    'description': 'Move to analyze in SAN notation (e.g., Nf3, Bxh7+)'
                }
            },
            'required': ['fen', 'move']
        }
    },
    'explain_why_bad': {
        'name': 'explain_why_bad',
        'description': 'Explain specifically why a move is a mistake. Shows refutation and better alternatives.',
        'parameters': {
            'type': 'object',
            'properties': {
                'fen': {'type': 'string', 'description': 'Position in FEN notation'},
                'move': {'type': 'string', 'description': 'The questionable move in SAN notation'}
            },
            'required': ['fen', 'move']
        }
    },
    'compare_moves': {
        'name': 'compare_moves',
        'description': 'Compare two moves and explain which is better and why.',
        'parameters': {
            'type': 'object',
            'properties': {
                'fen': {'type': 'string', 'description': 'Position in FEN notation'},
                'move1': {'type': 'string', 'description': 'First move to compare'},
                'move2': {'type': 'string', 'description': 'Second move to compare'}
            },
            'required': ['fen', 'move1', 'move2']
        }
    },
    'what_to_play': {
        'name': 'what_to_play',
        'description': 'Recommend the best move and explain why it is good.',
        'parameters': {
            'type': 'object',
            'properties': {
                'fen': {'type': 'string', 'description': 'Position in FEN notation'}
            },
            'required': ['fen']
        }
    },
    'find_tactics': {
        'name': 'find_tactics',
        'description': 'Search for tactical opportunities (forks, pins, sacrifices, etc.) in the position.',
        'parameters': {
            'type': 'object',
            'properties': {
                'fen': {'type': 'string', 'description': 'Position in FEN notation'}
            },
            'required': ['fen']
        }
    },
    'evaluate_position': {
        'name': 'evaluate_position',
        'description': 'Provide comprehensive position evaluation including material, activity, king safety, and overall assessment.',
        'parameters': {
            'type': 'object',
            'properties': {
                'fen': {'type': 'string', 'description': 'Position in FEN notation'}
            },
            'required': ['fen']
        }
    },
    'get_plan': {
        'name': 'get_plan',
        'description': 'Explain the strategic plan and typical ideas in the position.',
        'parameters': {
            'type': 'object',
            'properties': {
                'fen': {'type': 'string', 'description': 'Position in FEN notation'}
            },
            'required': ['fen']
        }
    },
    'explain_concept': {
        'name': 'explain_concept',
        'description': 'Explain a chess concept like fork, pin, sacrifice, initiative, tempo, etc.',
        'parameters': {
            'type': 'object',
            'properties': {
                'concept_name': {'type': 'string', 'description': 'Name of the concept (fork, pin, sacrifice, etc.)'}
            },
            'required': ['concept_name']
        }
    },
    'answer_chess_question': {
        'name': 'answer_chess_question',
        'description': 'General-purpose tool to answer any chess question. Automatically routes to appropriate analysis.',
        'parameters': {
            'type': 'object',
            'properties': {
                'fen': {'type': 'string', 'description': 'Current position in FEN notation'},
                'question': {'type': 'string', 'description': 'The chess question to answer'}
            },
            'required': ['fen', 'question']
        }
    }
}


# Function registry for tool dispatch
WHY_TOOL_FUNCTIONS = {
    'explain_move': explain_move,
    'explain_why_bad': explain_why_bad,
    'compare_moves': compare_moves,
    'what_to_play': what_to_play,
    'find_tactics': find_tactics,
    'evaluate_position': evaluate_position,
    'get_plan': get_plan,
    'explain_concept': explain_concept,
    'answer_chess_question': answer_chess_question,
}


def dispatch_why_tool(tool_name: str, **kwargs) -> dict:
    """
    Dispatch a tool call to the appropriate function.
    
    Args:
        tool_name: Name of the tool to call
        **kwargs: Arguments for the tool
        
    Returns:
        Tool result dictionary
    """
    if tool_name not in WHY_TOOL_FUNCTIONS:
        return {'success': False, 'error': f'Unknown tool: {tool_name}'}
    
    return WHY_TOOL_FUNCTIONS[tool_name](**kwargs)


# Export cleanup function
__all__ = [
    'explain_move', 'explain_why_bad', 'compare_moves', 'what_to_play',
    'find_tactics', 'evaluate_position', 'get_plan', 'explain_concept',
    'answer_chess_question', 'dispatch_why_tool', 'cleanup_service'
]
