import json
import boto3
import psycopg
import requests
from botocore.exceptions import ClientError
from datetime import datetime, timezone
from uuid import UUID

# Secrets Manager client
secrets_client = boto3.client("secretsmanager")
s3 = boto3.client("s3")
# Target bucket and file details
bucket_name = "suno-database-monior-log"
now = datetime.now(timezone.utc)
webhook_url = (
    "https://hooks.slack.com/services/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"
)
# Format as "YYYY-MM-DD HH"
date = now.strftime("%Y-%m-%d")
file_name = (
    str(date) + "/" + str(datetime.now(timezone.utc).hour) + "/" + now.strftime("%M:%S")
)


class UUIDEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, UUID):
            # if the obj is uuid, we simply return the value of uuid
            return obj.hex
        if isinstance(obj, datetime):
            return obj.isoformat()
        return json.JSONEncoder.default(self, obj)


def get_db_credentials(secret_name):
    """
    Retrieve database credentials from AWS Secrets Manager.
    """
    try:
        response = secrets_client.get_secret_value(SecretId=secret_name)
        secret = json.loads(response["SecretString"])
        return secret
    except ClientError as e:
        print(f"Error retrieving secret: {e}")
        raise e


def handler(event, context):
    # Name of the secret where RDS credentials are stored
    secret_name = "app-user-main-db-secret"

    # Retrieve credentials from Secrets Manager
    credentials = get_db_credentials(secret_name)

    is_reader = event.get("is_reader", False)

    # Database connection parameters
    if is_reader:
        db_host = "suno-main-postgres-prod-proxy-read-only.endpoint.proxy-cnfvffydbwvc.us-east-2.rds.amazonaws.com"
    else:
        db_host = "suno-main-postgres-prod-proxy.proxy-cnfvffydbwvc.us-east-2.rds.amazonaws.com"
    db_user = credentials["username"]
    db_password = credentials["password"]
    db_name = "suno_main"
    db_port = credentials.get("port", 5432)  # Default port for PostgreSQL

    # Get the query from the event object
    query = event.get("query", "")
    values = event.get("values", [])

    if not query:
        return {"statusCode": 400, "body": json.dumps({"message": "No query provided"})}

    # Connect to the RDS instance
    try:
        connection = psycopg.connect(
            host=db_host,
            user=db_user,
            password=db_password,
            dbname=db_name,
            port=db_port,
            connect_timeout=10,  # Set connection timeout to 10 seconds
        )
        connection.autocommit = True  # Enable autocommit mode for termination

        # Execute the query with a timeout of 10 seconds
        cursor = connection.cursor()
        cursor.execute(
            f"SET statement_timeout = 60000"
        )  # Set query timeout to 60 seconds
        if values:
            cursor.executemany(query, values)
            # Close the cursor and connection
            cursor.close()
            connection.close()
            return {
                "statusCode": 200,
                "body": json.dumps({"message": "Query executed successfully"}),
            }
        else:
            cursor.execute(query)
            results = cursor.fetchall()

            # Close the cursor and connection
            cursor.close()
            connection.close()
            return {"statusCode": 200, "body": json.dumps(results, cls=UUIDEncoder)}
    except psycopg.errors.SyntaxError as e:
        print(f"Syntax error in query: {e}")
        return {
            "statusCode": 400,
            "body": json.dumps({"message": "Syntax error in query", "error": str(e)}),
        }
    except psycopg.errors.DatabaseError as e:
        print(f"Database error: {e}")
        return {
            "statusCode": 500,
            "body": json.dumps({"message": "Database error", "error": str(e)}),
        }
    except Exception as e:
        print(f"Unexpected error: {e}")
        return {
            "statusCode": 500,
            "body": json.dumps({"message": "Unexpected error", "error": str(e)}),
        }
