import subprocess
import socket
import requests
import json
from retry import retry

from pre_wigs_validation.enums import ValidationEnforcement, ValidationResult
from pre_wigs_validation.instance import ValidationInstance
from pre_wigs_validation.dataclasses import ValidationOutput
from pre_wigs_validation.utils import check_validation_config

class EndPointUnReachable(Exception):
    pass


class EndpointConnectivity:
    """Validate AWS service endpoint connectivity with s3,CFN and SSM"""

    validation = "ENDPOINT Connectivity"
    enforcement = ValidationEnforcement.RECOMMENDED

    @classmethod
    def validate(
        cls, *, enabled: bool = True, instance: ValidationInstance
    ) -> ValidationOutput:

        """
        Parameters:
        enabled (bool): whether or not to run this validation function
        instance (ValidationInstance): the instance object being validated

        Returns:
        ValidationOutput: output of validation
        """

        if not enabled:
            return ValidationOutput(
                validation=cls.validation,
                result=ValidationResult.NOT_RUN,
                enforcement=cls.enforcement,
            )

        config = check_validation_config(
            default_params=cls.validate.__kwdefaults__, local_params=locals()
        )

        fail_message = "Endpoint not reachable for service:  "

        '''
        List of services for testing reachability
        '''

        service_list = [
        "s3",
        "ssm",
        "cloudformation",
        ]

        connection_good = False

        '''
        Parameter : service URL 
        Return: Endpoint reachability bool , True/False
        '''
        @retry(EndPointUnReachable, tries=3, delay=3)
        def endpoint_check(endpoint_url):
            test_connectivity = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            test_connectivity.settimeout(10)
            try:
              test_connectivity.connect((endpoint_url, int(443)))
              test_connectivity.shutdown(2)
              return True
            except socket.timeout:
              raise EndPointUnReachable
        
          

        instance_identity_document = 'http://169.254.169.254/latest/dynamic/instance-identity/document'
        r = requests.get(instance_identity_document)
        doc = r.json()
        region = doc['region']
        failed = False
        for service in service_list:
           end_point = f"{service}.{region}.amazonaws.com"
           try:
             connection_good = endpoint_check(end_point)
           except:
             connection_good = False

           if not connection_good:
              fail_message += f" {service}"
              failed = True

        if not failed:
            return ValidationOutput(
              validation=cls.validation,
              result=ValidationResult.PASS,
              enforcement=cls.enforcement,
              config=config,
            )

        return ValidationOutput(
                  validation=cls.validation,
                  result=ValidationResult.FAIL,
                  enforcement=cls.enforcement,
                  config=config,
                  message=fail_message,
           )
