# services/SSM.py
import os
import logging
from typing import Dict, Any, List, Optional

import boto3
from botocore.exceptions import ClientError

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

class SSM:
   
    """
    SSM helper that reads parameters from Parameter Store.
    Usage:
        ssm = SSM()  # optional: SSM(region_name="us-east-1", environment="dev")
        values = ssm.get_ssm_parameter(ssm_parameters)
        # or
        values = ssm.get_ssm(ssm_parameters)
    """

    def __init__(self, region_name: Optional[str] = None, environment: Optional[str] = None):
        self.environment = environment or os.getenv("NODE_ENVIRONMENT")
        # Note: if NODE_ENVIRONMENT not set, the original code used ssm_parameters['awsEnvt'] as fallback,
        # that fallback logic is kept inside each method to match original behaviour.
        self.region = region_name or os.getenv("AWS_DEFAULT_REGION", "us-east-1")
        self.client = boto3.client("ssm", region_name=self.region)

    def _build_names_array(self, ssm_parameters: Dict[str, Any]) -> List[str]:
        """
        Helper to construct parameter paths from ssm_parameters["ssmMap"].
        """
        aws_env = os.getenv("NODE_ENVIRONMENT", ssm_parameters.get("awsEnvt"))
        names: List[str] = []
        for param in ssm_parameters.get("ssmMap", []):
            names.append(f"/{aws_env}/{param['Name']}")
        return names

    def _map_response_to_dict(self, ssm_parameters: Dict[str, Any], response: Dict[str, Any]) -> Dict[str, str]:
        """
        Map boto3 get_parameters() response to the desired shape:
        parameter_store_json[param['Value']] = record['Value']
        """
        parameter_store_json: Dict[str, str] = {}
        for record in response.get("Parameters", []):
            # record["Name"] like "/env/SomeName"
            name_path = record["Name"].lstrip("/")  # remove leading slash
            key = name_path.split("/")[0]  # env
            ssm_name = name_path.replace(key, "", 1).lstrip("/")
            # find matching map entry
            for param in ssm_parameters.get("ssmMap", []):
                if ssm_name == param["Name"]:
                    parameter_store_json[param["Value"]] = record.get("Value", "")
                    break
        return parameter_store_json

    def get_ssm_parameter(self, ssm_parameters: Dict[str, Any]) -> Dict[str, str]:
        """
        Get SSM Parameter list from Parameter Store.
        Mirrors get_ssm_parameter in your original module.

        Returns an empty dict on error (keeps parity with your JS code).
        """
        try:
            names_array = self._build_names_array(ssm_parameters)

            if not names_array:
                logger.warning("No parameters requested (ssm_parameters['ssmMap'] empty or missing).")
                return {}

            response = self.client.get_parameters(Names=names_array, WithDecryption=True)
            result = self._map_response_to_dict(ssm_parameters, response)
            return result
        except ClientError as e:
            logger.exception("SSM ClientError while fetching parameters: %s", e)
            return {}
        except Exception as e:
            logger.exception("Unexpected error while fetching SSM parameters: %s", e)
            return {}

    def get_ssm(self, ssm_parameters: Dict[str, Any]) -> Dict[str, str]:
        """
        Fire-and-return version (keeps exact behaviour of your JS getSSM).
        In the JS version this returned immediately; in Python both methods run synchronously,
        but we preserve the same return/error semantics (return {} on error).
        """
        # Implementation is effectively the same; kept separate for API parity
        try:
            names_array = self._build_names_array(ssm_parameters)

            if not names_array:
                logger.warning("No parameters requested (ssm_parameters['ssmMap'] empty or missing).")
                return {}

            response = self.client.get_parameters(Names=names_array, WithDecryption=True)
            result = self._map_response_to_dict(ssm_parameters, response)
            return result
        except ClientError as e:
            logger.exception("SSM ClientError while fetching parameters (get_ssm): %s", e)
            return {}
        except Exception as e:
            logger.exception("Unexpected error while fetching SSM parameters (get_ssm): %s", e)
            return {}
