import os
import boto3
from botocore.exceptions import ClientError
from typing import Dict, Any, Optional

class DynamoDb:
    def __init__(self, region_name: str = None):
        region = region_name or os.getenv("AWS_DEFAULT_REGION", "us-east-1")
        self.client = boto3.client("dynamodb", region_name=region)

    def add(self, table_name: str, ddb_item: Dict[str, Any]) -> Optional[Dict[str, Any]]:
        """Put an item into DynamoDB."""
        print("adding item to db")
        try:
            params = {
                "TableName": table_name,
                "Item": ddb_item
            }
            self.client.put_item(**params)
            print("Get Response from dbItem")
            return params["Item"]
        except ClientError as e:
            print("AWS ClientError:", e)
            return None
        except Exception as e:
            print("Error:", e)
            return None

    def update(
        self,
        table_name: str,
        key: Dict[str, Any],
        update_expression: Optional[str] = None,
        expression_attribute_values: Optional[Dict[str, Any]] = None,
        expression_attribute_names: Optional[Dict[str, str]] = None,
        return_values: str = "ALL_NEW"
    ) -> Optional[Dict[str, Any]]:
        """Update an item in DynamoDB."""
        try:
            params: Dict[str, Any] = {
                "TableName": table_name,
                "Key": key,
                "ReturnValues": return_values
            }

            if update_expression:
                params["UpdateExpression"] = update_expression
            if expression_attribute_values:
                params["ExpressionAttributeValues"] = expression_attribute_values
            if expression_attribute_names:
                params["ExpressionAttributeNames"] = expression_attribute_names

            resp = self.client.update_item(**params)
            print("update Db info result")
            return resp
        except ClientError as e:
            print("AWS ClientError:", e)
            return None
        except Exception as e:
            print("Error:", e)
            return None

    def get(
        self,
        table_name: str,
        key_condition_expression: Optional[str] = None,
        expression_attribute_values: Optional[Dict[str, Any]] = None,
        expression_attribute_names: Optional[Dict[str, str]] = None,
        filter_expression: Optional[str] = None,
        exclusive_start_key: Optional[Dict[str, Any]] = None,
        limit: Optional[int] = None
    ) -> Dict[str, Any]:
        """Query the table."""
        try:
            params: Dict[str, Any] = {
                "TableName": table_name
            }

            if key_condition_expression:
                params["KeyConditionExpression"] = key_condition_expression
            if expression_attribute_values:
                params["ExpressionAttributeValues"] = expression_attribute_values
            if expression_attribute_names:
                params["ExpressionAttributeNames"] = expression_attribute_names
            if filter_expression:
                params["FilterExpression"] = filter_expression
            if exclusive_start_key:
                params["ExclusiveStartKey"] = exclusive_start_key
            if limit:
                params["Limit"] = limit

            print("DB query params")
            resp = self.client.query(**params)
            print("dbItem after fetching details")
            return resp

        except ClientError as e:
            print("AWS ClientError:", e)
            print("error occurred while fetching items from table")
            raise
        except Exception as e:
            print("Error:", e)
            print("error occurred while fetching items from table")
            raise
