"""DynamoDB service for transaction storage."""

import boto3
import logging
from typing import Optional, List, Dict, Any
from botocore.exceptions import ClientError
from decimal import Decimal

logger = logging.getLogger(__name__)


class TransactionStore:
    """Repository for transaction data in DynamoDB."""
    
    def __init__(self, table_name: str, region: str = "us-east-1"):
        self.table_name = table_name
        self.region = region
        self.dynamodb_client = boto3.client("dynamodb", region_name=region)
        self.dynamodb_resource = boto3.resource("dynamodb", region_name=region)
        self.table = self.dynamodb_resource.Table(table_name)
        logger.info(f"TransactionStore initialized with table: {table_name}")
    
    def save_transaction(self, transaction_data: dict) -> bool:
        """Save transaction record to DynamoDB."""
        try:
            item = self._convert_to_dynamodb_item(transaction_data)
            response = self.table.put_item(Item=item)
            logger.info(f"Transaction saved: {transaction_data.get('transaction_id')}")
            return True
        except ClientError as e:
            logger.error(f"DynamoDB put_item failed: {e}")
            return False
        except Exception as e:
            logger.error(f"Unexpected error saving transaction: {e}")
            return False
    
    def get_transaction(self, transaction_id: str) -> Optional[dict]:
        """Retrieve transaction by ID."""
        try:
            response = self.table.get_item(Key={"transaction_id": transaction_id})
            item = response.get("Item")
            if item:
                logger.info(f"Transaction retrieved: {transaction_id}")
                return self._convert_from_dynamodb_item(item)
            return None
        except ClientError as e:
            logger.error(f"DynamoDB get_item failed: {e}")
            return None
    
    def get_all_transactions(self, email: Optional[str] = None) -> List[dict]:
        """Get all transactions, optionally filtered by email."""
        try:
            if email:
                response = self.table.scan(
                    FilterExpression="email = :email",
                    ExpressionAttributeValues={":email": email}
                )
            else:
                response = self.table.scan()
            
            items = response.get("Items", [])
            transactions = [self._convert_from_dynamodb_item(item) for item in items]
            logger.info(f"Retrieved {len(transactions)} transactions")
            return transactions
        except ClientError as e:
            logger.error(f"DynamoDB scan failed: {e}")
            return []
    
    def update_transaction_status(self, transaction_id: str, status: str, 
                                  error_message: Optional[str] = None) -> bool:
        """Update transaction status."""
        try:
            update_expression = "SET #status = :status"
            expression_values = {":status": status}
            
            if error_message:
                update_expression += ", error_message = :error"
                expression_values[":error"] = error_message
            
            response = self.table.update_item(
                Key={"transaction_id": transaction_id},
                UpdateExpression=update_expression,
                ExpressionAttributeNames={"#status": "status"},
                ExpressionAttributeValues=expression_values
            )
            logger.info(f"Transaction status updated: {transaction_id} -> {status}")
            return True
        except ClientError as e:
            logger.error(f"DynamoDB update failed: {e}")
            return False
    
    def _convert_to_dynamodb_item(self, data: dict) -> dict:
        """Convert Python types to DynamoDB types."""
        item = {}
        for key, value in data.items():
            if isinstance(value, (int, float)):
                item[key] = Decimal(str(value))
            else:
                item[key] = value
        return item
    
    def _convert_from_dynamodb_item(self, item: dict) -> dict:
        """Convert DynamoDB types to Python types."""
        result = {}
        for key, value in item.items():
            if isinstance(value, Decimal):
                result[key] = int(value) if value % 1 == 0 else float(value)
            else:
                result[key] = value
        return result
