import boto3
from botocore.exceptions import ClientError


class S3Client:
    def __init__(self, config):
        self.client = boto3.client("s3", region_name=config.region)
        self.config = config

    def upload(self, key, file_obj):
        extra_args = {"ServerSideEncryption": "aws:kms"}
        if self.config.kms_key_id:
            extra_args["SSEKMSKeyId"] = self.config.kms_key_id

        self.client.upload_fileobj(
            file_obj,
            self.config.bucket,
            key,
            ExtraArgs=extra_args
        )
        return self.client.head_object(Bucket=self.config.bucket, Key=key)

    def download(self, key):
        return self.client.get_object(
            Bucket=self.config.bucket,
            Key=key,
        )

    def delete(self, key):
        return self.client.delete_object(
            Bucket=self.config.bucket,
            Key=key,
        )

    def exists(self, key):
        try:
            self.client.head_object(Bucket=self.config.bucket, Key=key)
            return True
        except ClientError as e:
            if e.response.get('Error', {}).get('Code') == '404':
                return False
            raise e

    def generate_url(self, key, expires):
        return self.client.generate_presigned_url(
            "get_object",
            Params={"Bucket": self.config.bucket, "Key": key},
            ExpiresIn=expires,
        )