import requests
import json
import logging

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


class ToolRegistryValidator:
    """
    Validates tool registrations across multiple servers by checking their availability.
    """

    def __init__(self, registry_urls: list[str]):
        """
        Initializes the validator with a list of registry URLs.

        Args:
            registry_urls (list[str]): A list of URLs pointing to MCP tool registry endpoints.
        """
        self.registry_urls = registry_urls
        self.tool_registrations = {}
        self.validation_results = {}

    def fetch_tool_registrations(self) -> None:
        """
        Fetches tool registrations from all configured registry URLs.
        Populates the `tool_registrations` dictionary.
        """
        logging.info("Fetching tool registrations from registry URLs...")
        for url in self.registry_urls:
            try:
                response = requests.get(url)
                response.raise_for_status()  # Raise HTTPError for bad responses (4xx or 5xx)

                try:
                    data = response.json()
                    if isinstance(data, list):  # Expecting a list of tool registrations
                        self.tool_registrations[url] = data
                        logging.info(f"Successfully fetched {len(data)} tool registrations from {url}")
                    else:
                        logging.error(f"Unexpected data format from {url}. Expected a list.")
                        self.tool_registrations[url] = [] # Ensure its an empty list to prevent errors later.

                except json.JSONDecodeError:
                    logging.error(f"Failed to decode JSON from {url}.  Response content: {response.text}")
                    self.tool_registrations[url] = [] #  Ensure its an empty list to prevent errors later.


            except requests.exceptions.RequestException as e:
                logging.error(f"Error fetching tool registrations from {url}: {e}")
                self.tool_registrations[url] = [] #  Ensure its an empty list to prevent errors later.



    def validate_tool_availability(self) -> None:
        """
        Validates the availability of each registered tool by making a request to its endpoint.
        Populates the `validation_results` dictionary.
        """
        logging.info("Validating tool availability...")
        self.validation_results = {}
        for registry_url, registrations in self.tool_registrations.items():
            self.validation_results[registry_url] = {}
            for tool in registrations:
                tool_name = tool.get("name", "Unknown Tool")
                endpoint = tool.get("endpoint")

                if not endpoint:
                    logging.warning(f"Tool '{tool_name}' in {registry_url} has no endpoint. Skipping validation.")
                    self.validation_results[registry_url][tool_name] = {"status": "skipped", "reason": "No endpoint provided"}
                    continue

                try:
                    response = requests.get(endpoint, timeout=5)  # Add timeout to prevent indefinite hanging
                    response.raise_for_status()  # Raise HTTPError for bad responses (4xx or 5xx)
                    self.validation_results[registry_url][tool_name] = {"status": "available", "http_status": response.status_code}
                    logging.info(f"Tool '{tool_name}' at {endpoint} is available (Status: {response.status_code})")

                except requests.exceptions.RequestException as e:
                    self.validation_results[registry_url][tool_name] = {"status": "unavailable", "reason": str(e)}
                    logging.error(f"Tool '{tool_name}' at {endpoint} is unavailable: {e}")

    def generate_report(self) -> dict:
        """
        Generates a summary report of the validation results.

        Returns:
            dict: A dictionary containing the validation report.
        """
        report = {}
        for registry_url, results in self.validation_results.items():
            report[registry_url] = {
                "available_tools": [],
                "unavailable_tools": [],
                "skipped_tools": [],
                "errors": []
            }

            for tool_name, validation_data in results.items():
                if validation_data["status"] == "available":
                    report[registry_url]["available_tools"].append(tool_name)
                elif validation_data["status"] == "unavailable":
                    report[registry_url]["unavailable_tools"].append({tool_name: validation_data["reason"]})
                    report[registry_url]["errors"].append(f"Tool {tool_name} unavailable at {registry_url}: {validation_data['reason']}")
                elif validation_data["status"] == "skipped":
                    report[registry_url]["skipped_tools"].append(tool_name)
        return report

    def run_validation(self) -> dict:
        """
        Runs the entire validation process.

        Returns:
            dict: A dictionary containing the validation report.
        """
        self.fetch_tool_registrations()
        self.validate_tool_availability()
        report = self.generate_report()
        return report


if __name__ == '__main__':
    # Example Usage:
    registry_urls = [
        "http://localhost:8000/tools",  # Replace with your actual registry URLs
        "http://localhost:8001/tools"   # Replace with your actual registry URLs
    ]

    validator = ToolRegistryValidator(registry_urls)
    report = validator.run_validation()

    print(json.dumps(report, indent=4))

    # Example of iterating and reporting errors.
    for registry_url, registry_data in report.items():
        if registry_data["errors"]:
            print(f"\nErrors found in registry: {registry_url}")
            for error in registry_data["errors"]:
                print(f"- {error}")