# Copyright OpenSearch Contributors
# SPDX-License-Identifier: Apache-2.0

import json
import logging
from semver import Version
from tools.tool_params import *

# Configure logging
logger = logging.getLogger(__name__)


# List all the helper functions, these functions perform a single rest call to opensearch
# these functions will be used in tools folder to eventually write more complex tools
def list_indices(args: ListIndicesArgs) -> json:
    from .client import initialize_client

    client = initialize_client(args)
    response = client.cat.indices(format='json')
    return response


def get_index(args: ListIndicesArgs) -> json:
    """Get detailed information about a specific index.

    Args:
        args: ListIndicesArgs containing the index name

    Returns:
        json: Detailed index information including settings and mappings
    """
    from .client import initialize_client

    client = initialize_client(args)
    response = client.indices.get(index=args.index)
    return response


def get_index_mapping(args: GetIndexMappingArgs) -> json:
    from .client import initialize_client

    client = initialize_client(args)
    response = client.indices.get_mapping(index=args.index)
    return response


def search_index(args: SearchIndexArgs) -> json:
    from .client import initialize_client

    client = initialize_client(args)
    response = client.search(index=args.index, body=args.query)
    return response


def get_shards(args: GetShardsArgs) -> json:
    from .client import initialize_client

    client = initialize_client(args)
    response = client.cat.shards(index=args.index, format='json')
    return response


def get_segments(args: GetSegmentsArgs) -> json:
    """Get information about Lucene segments in indices.
    
    Args:
        args: GetSegmentsArgs containing optional index filter
        
    Returns:
        json: Segment information for the specified indices or all indices
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    
    # If index is provided, filter by that index
    index_param = args.index if args.index else None
    
    response = client.cat.segments(index=index_param, format='json')
    return response


def get_cluster_state(args: GetClusterStateArgs) -> json:
    """Get the current state of the cluster.
    
    Args:
        args: GetClusterStateArgs containing optional metric and index filters
        
    Returns:
        json: Cluster state information based on the requested metrics and indices
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    
    # Build parameters dictionary with non-None values
    params = {}
    if args.metric:
        params['metric'] = args.metric
    if args.index:
        params['index'] = args.index
        
    response = client.cluster.state(**params)
    return response


def get_nodes(args: CatNodesArgs) -> json:
    """Get information about nodes in the cluster.
    
    Args:
        args: GetNodesArgs containing optional metrics filter
        
    Returns:
        json: Node information for the cluster
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    
    # If metrics is provided, use it as a parameter
    metrics_param = args.metrics if args.metrics else None
    
    response = client.cat.nodes(format='json', h=metrics_param)
    return response


def get_index_info(args: GetIndexInfoArgs) -> json:
    """Get detailed information about an index including mappings, settings, and aliases.
    
    Args:
        args: GetIndexInfoArgs containing the index name
        
    Returns:
        json: Detailed index information
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    response = client.indices.get(index=args.index)
    return response


def get_index_stats(args: GetIndexStatsArgs) -> json:
    """Get statistics about an index.
    
    Args:
        args: GetIndexStatsArgs containing the index name and optional metric filter
        
    Returns:
        json: Index statistics
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    
    # Build parameters dictionary with non-None values
    params = {}
    if args.metric:
        params['metric'] = args.metric
        
    response = client.indices.stats(index=args.index, **params)
    return response


def get_query_insights(args: GetQueryInsightsArgs) -> json:
    """Get insights about top queries in the cluster.
    
    Args:
        args: GetQueryInsightsArgs containing connection parameters
        
    Returns:
        json: Query insights from the /_insights/top_queries endpoint
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    
    # Use the transport.perform_request method to make a direct REST API call
    # since the Python client might not have a dedicated method for this endpoint
    response = client.transport.perform_request(
        method='GET',
        url='/_insights/top_queries'
    )
    
    return response


def get_nodes_hot_threads(args: GetNodesHotThreadsArgs) -> str:
    """Get information about hot threads in the cluster nodes.
    
    Args:
        args: GetNodesHotThreadsArgs containing connection parameters
        
    Returns:
        str: Hot threads information from the /_nodes/hot_threads endpoint
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    
    # Use the transport.perform_request method to make a direct REST API call
    # The hot_threads API returns text, not JSON
    response = client.transport.perform_request(
        method='GET',
        url='/_nodes/hot_threads'
    )
    
    return response


def get_allocation(args: GetAllocationArgs) -> json:
    """Get information about shard allocation across nodes in the cluster.
    
    Args:
        args: GetAllocationArgs containing connection parameters
        
    Returns:
        json: Allocation information from the /_cat/allocation endpoint
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    
    # Use the cat.allocation method with JSON format
    response = client.cat.allocation(format='json')
    
    return response


def get_long_running_tasks(args: GetLongRunningTasksArgs) -> json:
    """Get information about long-running tasks in the cluster, sorted by running time.
    
    Args:
        args: GetLongRunningTasksArgs containing limit parameter
        
    Returns:
        json: Task information from the /_cat/tasks endpoint, sorted by running time
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    
    # Use the transport.perform_request method to make a direct REST API call
    # since we need to sort by running_time which might not be directly supported by the client
    response = client.transport.perform_request(
        method='GET',
        url='/_cat/tasks',
        params={
            's': 'running_time:desc',  # Sort by running time in descending order
            'format': 'json'
        }
    )
    
    # Limit the number of tasks returned if specified
    if args.limit and isinstance(response, list):
        return response[:args.limit]
    
    return response


def get_nodes_info(args: GetNodesArgs) -> json:
    """Get detailed information about nodes in the cluster.
    
    Args:
        args: GetNodesArgs containing optional node_id, metric filters, and other parameters
        
    Returns:
        json: Detailed node information from the /_nodes endpoint
    """
    from .client import initialize_client
    
    client = initialize_client(args)
    
    # Build the URL path based on provided parameters
    url_parts = ['/_nodes']
    
    # Add node_id if provided
    if args.node_id:
        url_parts.append(args.node_id)
    
    # Add metric if provided
    if args.metric:
        url_parts.append(args.metric)
    
    url = '/'.join(url_parts)
    
    # Use the transport.perform_request method to make a direct REST API call
    response = client.transport.perform_request(
        method='GET',
        url=url
    )
    
    return response


def get_opensearch_version(args: baseToolArgs) -> Version:
    """Get the version of OpenSearch cluster.

    Returns:
        Version: The version of OpenSearch cluster (SemVer style)
    """
    from .client import initialize_client

    try:
        client = initialize_client(args)
        response = client.info()
        return Version.parse(response['version']['number'])
    except Exception as e:
        logger.error(f'Error getting OpenSearch version: {e}')
        return None
