import shlex
from .gcp_connector import GCPConnector

from .gcp_agents.compute_agent import ComputeAgent
from .gcp_agents.storage_agent import StorageAgent
from .gcp_agents.sql_agent import SQLAgent
from .gcp_agents.functions_agent import FunctionsAgent
from .gcp_agents.network_agent import NetworkAgent
from .gcp_agents.gke_agent import GKEAgent
from .gcp_agents.bigquery_agent import BigQueryAgent
from .gcp_agents.pubsub_agent import PubSubAgent
from .gcp_agents.vertexai_agent import VertexAIAgent
from .gcp_agents.visionai_agent import VisionAIAgent
from .gcp_agents.languageai_agent import LanguageAIAgent
from .gcp_agents.texttospeech_agent import TextToSpeechAgent
from .gcp_agents.iam_agent import IAMAgent
from .gcp_agents.scc_agent import SCCAgent
from .gcp_agents.cost_management_agent import CostManagementAgent

class GCPAgentManager:
    """
    The central orchestrator for all GCP agents.
    """

    def __init__(self):
        """
        Initializes the GCPAgentManager and registers the available agents.
        """
        self.agents = {
            'compute': ComputeAgent(),
            'storage': StorageAgent(),
            'sql': SQLAgent(),
            'functions': FunctionsAgent(),
            'network': NetworkAgent(),
            'gke': GKEAgent(),
            'bigquery': BigQueryAgent(),
            'pubsub': PubSubAgent(),
            'vertexai': VertexAIAgent(),
            'visionai': VisionAIAgent(),
            'languageai': LanguageAIAgent(),
            'texttospeech': TextToSpeechAgent(),
            'iam': IAMAgent(),
            'scc': SCCAgent(),
            'cost_management': CostManagementAgent(),
        }
        print("GCPAgentManager initialized with the following agents: " + ", ".join(self.agents.keys()))

    def get_available_services(self):
        """
        Returns a list of all services managed by this GCPAgentManager.
        """
        return list(self.agents.keys())

    def get_service_commands(self, service_name: str):
        """
        Returns a list of commands supported by a specific service agent.
        """
        parser_method = getattr(self, f'_parse_{service_name}_command', None)
        if parser_method:
            # Call the parser with dummy parts to get the command list
            # The parser now returns (command, args, commands_list)
            _, _, commands_list = parser_method([])
            if commands_list:
                return [cmd['usage'] for cmd in commands_list]
        return []

    def _get_service(self, parts):
        # Implement logic to determine GCP service from command parts
        if 'compute' in parts or 'instance' in parts or 'vm' in parts:
            return 'compute'
        if 'storage' in parts or 'bucket' in parts:
            return 'storage'
        if 'sql' in parts or 'database' in parts:
            return 'sql'
        if 'functions' in parts or 'function' in parts:
            return 'functions'
        if 'network' in parts or 'vpc' in parts:
            return 'network'
        if 'gke' in parts or 'kubernetes' in parts or 'cluster' in parts:
            return 'gke'
        if 'bigquery' in parts or 'bq' in parts or 'query' in parts:
            return 'bigquery'
        if 'pubsub' in parts or 'topic' in parts or 'message' in parts:
            return 'pubsub'
        if 'vertexai' in parts or 'notebook' in parts or 'ml' in parts:
            return 'vertexai'
        if 'visionai' in parts or 'vision' in parts or 'image' in parts:
            return 'visionai'
        if 'languageai' in parts or 'language' in parts or 'sentiment' in parts:
            return 'languageai'
        if 'texttospeech' in parts or 'tts' in parts or 'speech' in parts:
            return 'texttospeech'
        if 'iam' in parts or 'service-account' in parts or 'role' in parts:
            return 'iam'
        if 'scc' in parts or 'security-command-center' in parts:
            return 'scc'
        if 'cost-management' in parts or 'cost' in parts or 'billing' in parts:
            return 'cost_management'
        return None

    # Placeholder for GCP service command parsers
    def _parse_compute_command(self, parts):
        commands = [
            {"command": "list_instances", "usage": "compute list instances in <zone>"},
            {"command": "start_instance", "usage": "compute start <instance-name> in <zone>"},
            {"command": "stop_instance", "usage": "compute stop <instance-name> in <zone>"},
            {"command": "delete_instance", "usage": "compute delete <instance-name> in <zone>"},
            {"command": "smart_create_instance", "usage": "compute smart-create instance <name> type <machine-type> image-project <project> image-family <family> in <zone>"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()
            if 'in' in parts:
                args['zone'] = parts[parts.index('in') + 1]
            else:
                return None, {"error": "Zone not specified. Use 'in <zone>'."}, commands

            if 'list' in parts and ('instances' in parts or 'vms' in parts):
                command = 'list_instances'
            elif 'start' in parts:
                command = 'start_instance'
                args['instance_name'] = parts[parts.index('start') + 1]
            elif 'stop' in parts:
                command = 'stop_instance'
                args['instance_name'] = parts[parts.index('stop') + 1]
            elif 'delete' in parts:
                command = 'delete_instance'
                args['instance_name'] = parts[parts.index('delete') + 1]
            elif 'smart-create' in parts and ('instance' in parts or 'vm' in parts):
                command = 'smart_create_instance'
                args['instance_name'] = parts[parts.index('instance') + 1]
                args['machine_type'] = parts[parts.index('type') + 1]
                args['image_project'] = parts[parts.index('image-project') + 1]
                args['image_family'] = parts[parts.index('image-family') + 1]
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid Compute command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_storage_command(self, parts):
        commands = [
            {"command": "list_buckets", "usage": "storage list buckets"},
            {"command": "smart_create_bucket", "usage": "storage smart-create bucket <name> in <location>"},
            {"command": "delete_bucket", "usage": "storage delete bucket <name>"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'list' in parts and 'buckets' in parts:
                command = 'list_buckets'
            elif 'smart-create' in parts and 'bucket' in parts:
                command = 'smart_create_bucket'
                args['bucket_name'] = parts[parts.index('bucket') + 1]
                args['location'] = parts[parts.index('in') + 1]
            elif 'delete' in parts and 'bucket' in parts:
                command = 'delete_bucket'
                args['bucket_name'] = parts[parts.index('bucket') + 1]
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid Storage command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_sql_command(self, parts):
        commands = [
            {"command": "smart_create_instance", "usage": "sql smart-create instance <name> version <version> tier <tier> in <region>"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()
            if 'in' in parts:
                args['region'] = parts[parts.index('in') + 1]
            else:
                return None, {"error": "Region not specified. Use 'in <region>'."}, commands

            if 'smart-create' in parts and 'instance' in parts:
                command = 'smart_create_instance'
                args['instance_name'] = parts[parts.index('instance') + 1]
                args['database_version'] = parts[parts.index('version') + 1]
                args['tier'] = parts[parts.index('tier') + 1]
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid SQL command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_functions_command(self, parts):
        commands = [
            {"command": "smart_create_function", "usage": "functions smart-create function <name> runtime <runtime> trigger-topic <topic-name> in <region>"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()
            if 'in' in parts:
                args['region'] = parts[parts.index('in') + 1]
            else:
                return None, {"error": "Region not specified. Use 'in <region>'."}, commands

            if 'smart-create' in parts and 'function' in parts:
                command = 'smart_create_function'
                try:
                    args['function_name'] = parts[parts.index('function') + 1]
                    args['runtime'] = parts[parts.index('runtime') + 1]
                    args['trigger_topic'] = parts[parts.index('trigger-topic') + 1]
                except (ValueError, IndexError):
                    return None, {"error": "Usage: functions smart-create function <name> runtime <runtime> trigger-topic <topic-name> in <region>"}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid Functions command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_network_command(self, parts):
        commands = [
            {"command": "smart_create_network", "usage": "network smart-create network <name> [auto-create-subnetworks true/false]"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'smart-create' in parts and 'network' in parts:
                command = 'smart_create_network'
                try:
                    args['network_name'] = parts[parts.index('network') + 1]
                    if 'auto-create-subnetworks' in parts:
                        args['auto_create_subnetworks'] = parts[parts.index('auto-create-subnetworks') + 1].lower() == 'true'
                except (ValueError, IndexError):
                    return None, {"error": "Usage: network smart-create network <name> [auto-create-subnetworks true/false]"}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid Network command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_gke_command(self, parts):
        commands = [
            {"command": "smart_create_cluster", "usage": "gke smart-create cluster <name> in <region> [machine-type <type>] [num-nodes <count>] [anthos-enabled true/false]"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()
            if 'in' in parts:
                args['region'] = parts[parts.index('in') + 1]
            else:
                return None, {"error": "Region not specified. Use 'in <region>'."}, commands

            if 'smart-create' in parts and 'cluster' in parts:
                command = 'smart_create_cluster'
                try:
                    args['cluster_name'] = parts[parts.index('cluster') + 1]
                    if 'machine-type' in parts:
                        args['machine_type'] = parts[parts.index('machine-type') + 1]
                    if 'num-nodes' in parts:
                        args['num_nodes'] = int(parts[parts.index('num-nodes') + 1])
                    if 'anthos-enabled' in parts:
                        args['anthos_enabled'] = parts[parts.index('anthos-enabled') + 1].lower() == 'true'
                except (ValueError, IndexError):
                    return None, {"error": "Usage: gke smart-create cluster <name> in <region> [machine-type <type>] [num-nodes <count>] [anthos-enabled true/false]"}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid GKE command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_bigquery_command(self, parts):
        commands = [
            {"command": "run_query", "usage": "bigquery run query \"<query-string>\""},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'run' in parts and 'query' in parts:
                command = 'run_query'
                try:
                    args['query_string'] = parts[parts.index('query') + 1]
                except (ValueError, IndexError):
                    return None, {"error": "Usage: bigquery run query \"<query-string>\""}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid BigQuery command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_pubsub_command(self, parts):
        commands = [
            {"command": "smart_create_topic", "usage": "pubsub smart-create topic <topic-name>"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'smart-create' in parts and 'topic' in parts:
                command = 'smart_create_topic'
                try:
                    args['topic_name'] = parts[parts.index('topic') + 1]
                except (ValueError, IndexError):
                    return None, {"error": "Usage: pubsub smart-create topic <topic-name>"}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid PubSub command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_vertexai_command(self, parts):
        commands = [
            {"command": "smart_create_notebook", "usage": "vertexai smart-create notebook <name> in <location> [machine-type <type>] [image-project <project>] [image-family <family>]"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()
            if 'in' in parts:
                args['location'] = parts[parts.index('in') + 1]
            else:
                return None, {"error": "Location not specified. Use 'in <location>'."}, commands

            if 'smart-create' in parts and 'notebook' in parts:
                command = 'smart_create_notebook'
                try:
                    args['notebook_name'] = parts[parts.index('notebook') + 1]
                    if 'machine-type' in parts:
                        args['machine_type'] = parts[parts.index('machine-type') + 1]
                    if 'image-project' in parts:
                        args['vm_image_project'] = parts[parts.index('image-project') + 1]
                    if 'image-family' in parts:
                        args['vm_image_family'] = parts[parts.index('image-family') + 1]
                except (ValueError, IndexError):
                    return None, {"error": "Usage: vertexai smart-create notebook <name> in <location> [machine-type <type>] [image-project <project>] [image-family <family>]"}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid Vertex AI command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_visionai_command(self, parts):
        commands = [
            {"command": "analyze_image_labels", "usage": "visionai analyze image-labels in bucket <bucket-name> object <object-name> [max-labels <count>]"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'analyze' in parts and 'image-labels' in parts:
                command = 'analyze_image_labels'
                try:
                    args['bucket_name'] = parts[parts.index('bucket') + 1]
                    args['object_name'] = parts[parts.index('object') + 1]
                    if 'max-labels' in parts:
                        args['max_labels'] = int(parts[parts.index('max-labels') + 1])
                except (ValueError, IndexError):
                    return None, {"error": "Usage: visionai analyze image-labels in bucket <bucket-name> object <object-name> [max-labels <count>]"}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid Vision AI command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_languageai_command(self, parts):
        commands = [
            {"command": "analyze_sentiment", "usage": "languageai analyze sentiment for text \"<text>\""},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'analyze' in parts and 'sentiment' in parts:
                command = 'analyze_sentiment'
                try:
                    args['text'] = parts[parts.index('text') + 1]
                except (ValueError, IndexError):
                    return None, {"error": "Usage: languageai analyze sentiment for text \"<text>\""}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid Language AI command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_texttospeech_command(self, parts):
        commands = [
            {"command": "synthesize_speech", "usage": "texttospeech synthesize speech for text \"<text>\" [output-file <file>] [language-code <code>] [gender <gender>]"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'synthesize' in parts and 'speech' in parts:
                command = 'synthesize_speech'
                try:
                    args['text'] = parts[parts.index('text') + 1]
                    if 'output-file' in parts:
                        args['output_file'] = parts[parts.index('output-file') + 1]
                    if 'language-code' in parts:
                        args['language_code'] = parts[parts.index('language-code') + 1]
                    if 'gender' in parts:
                        args['ssml_gender'] = parts[parts.index('gender') + 1]
                except (ValueError, IndexError):
                    return None, {"error": "Usage: texttospeech synthesize speech for text \"<text>\" [output-file <file>] [language-code <code>] [gender <gender>]"}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid Text-to-Speech command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_iam_command(self, parts):
        commands = [
            {"command": "smart_create_service_account", "usage": "iam smart-create service-account <id> [display-name \"<name>\"] [role <role-name>]"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'smart-create' in parts and 'service-account' in parts:
                command = 'smart_create_service_account'
                try:
                    args['service_account_id'] = parts[parts.index('service-account') + 1]
                    if 'display-name' in parts:
                        args['display_name'] = parts[parts.index('display-name') + 1]
                    if 'role' in parts:
                        args['role'] = parts[parts.index('role') + 1]
                except (ValueError, IndexError):
                    return None, {"error": "Usage: iam smart-create service-account <id> [display-name \"<name>\"] [role <role-name>]"}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid IAM command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_scc_command(self, parts):
        commands = [
            {"command": "smart_enable_scc", "usage": "scc smart-enable scc"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'smart-enable' in parts and ('scc' in parts or 'security-command-center' in parts):
                command = 'smart_enable_scc'
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid SCC command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_cost_management_command(self, parts):
        commands = [
            {"command": "get_cost_trends", "usage": "cost-management get cost-trends [for <days> days]"},
        ]

        command, args = None, {}
        try:
            args['project_id'] = GCPConnector.get_project_id()

            if 'get' in parts and 'cost-trends' in parts:
                command = 'get_cost_trends'
                try:
                    if 'for' in parts and 'days' in parts:
                        args['days'] = int(parts[parts.index('for') + 1])
                except (ValueError, IndexError):
                    return None, {"error": "Usage: cost-management get cost-trends [for <days> days]"}, commands
        except (ValueError, IndexError) as e:
            return None, {"error": f"Invalid Cost Management command usage: {e}. Refer to help for correct syntax."}
        return command, args, commands

    def _parse_command(self, user_command: str):
        parts = shlex.split(user_command)
        if not parts:
            return None, None, None

        service = self._get_service(parts)
        if not service:
            return None, None, {}

        parser_map = {
            'compute': self._parse_compute_command,
            'storage': self._parse_storage_command,
            'sql': self._parse_sql_command,
            'functions': self._parse_functions_command,
            'network': self._parse_network_command,
            'gke': self._parse_gke_command,
            'bigquery': self._parse_bigquery_command,
            'pubsub': self._parse_pubsub_command,
            'vertexai': self._parse_vertexai_command,
            'visionai': self._parse_visionai_command,
            'languageai': self._parse_languageai_command,
            'texttospeech': self._parse_texttospeech_command,
            'iam': self._parse_iam_command,
            'scc': self._parse_scc_command,
            'cost_management': self._parse_cost_management_command,
        }

        parser = parser_map.get(service)
        if parser:
            command, args, commands_list = parser(parts)
            return service, command, args, commands_list
        
        return None, None, {}, []

    def execute_command(self, user_command: str):
        """
        Parses and executes a user command, routing to GCP agents.
        """
        print(f"\nReceived GCP command: '{user_command}'")
        parts = shlex.split(user_command)

        service, command, args, commands_list = self._parse_command(user_command)

        if args and 'error' in args:
            return {"status": "error", "message": args['error']}

        if not service or not command:
            error_message = "Could not understand the GCP command. Please be more specific."
            if commands_list:
                error_message += "\nAvailable commands for this service:\n" + "\n".join([cmd['usage'] for cmd in commands_list])
            return {"status": "error", "message": error_message}

        if service in self.agents:
            agent = self.agents[service]
            try:
                print(f"Routing to {service.upper()}Agent with command '{command}' and args {args}")
                return agent.execute(command, **args)
            except Exception as e:
                return {"status": "error", "message": str(e)}
        else:
            return {"status": "error", "message": f"No agent found for GCP service '{service}'."}
