import boto3, os, io, logging, re

LOGGER = logging.getLogger(__name__)


class R2:
    def __init__(self, file=None, main_folder_name=None):
        self.client = boto3.client(
            service_name="s3",
            endpoint_url=f"https://{os.getenv('CLOUDFLARE_API_ACCOUNT_ID')}.r2.cloudflarestorage.com/caracole",
            aws_access_key_id=os.getenv("CLOUDFLARE_ACCESS_KEY"),
            aws_secret_access_key=os.getenv("CLOUDFLARE_SECRET_KEY"),
            region_name="apac",
        )
        self.bucket = "caracole"
        self.file = file
        self.main_folder_name = main_folder_name or os.getenv(
            "CLOUDFLARE_PRODUCTS_FOLDER"
        )
        self.base_domain_url = (
            os.getenv("CLOUDFLARE_BASE_DOMAIN") + self.main_folder_name
        )

    def convert_file_to_bytesio(self):
        if not self.file:
            raise Exception("File to convert does not exists.")

        file = self.file

        LOGGER.info("Converting file to bytes...")
        try:
            with open(file, "rb") as file:
                return io.BytesIO(file.read())
        except TypeError as e:
            LOGGER.info("File already in proper format")
            return file

    def upload_fileobj(self, object_key=None, sub_folder_path=None):
        if not self.file:
            raise Exception("File to upload does not exists.")

        if "https://cdn.caracole.ph/" in str(self.file):
            return str(self.file)

        file_data = self.convert_file_to_bytesio()

        if "InMemoryUploadedFile" in str(type(self.file)):
            file_name = str(self.file)
        else:
            file_name = os.path.basename(self.file)

        try:
            LOGGER.info(f"Uploading file '{str(self.file)} to R2...")

            if sub_folder_path:
                if not sub_folder_path.endswith("/"):
                    sub_folder_path += "/"

                object_key = f"{sub_folder_path.replace(" ", "_")}{file_name}"
            elif not object_key:
                object_key = str(self.file)

            self.client.upload_fileobj(file_data, self.main_folder_name, object_key)

            return f"{self.base_domain_url}/{object_key}"
        except Exception as e:
            LOGGER.error(f"Error uploading file: {str(e)}")
            raise Exception(f"Error uploading file: {str(e)}")

    def delete_object(self, r2_path):
        if "image-not-found.jpg" in r2_path:
            return None

        pattern = r"https://cdn\.caracole\.ph/([^/]+)/(.*)"
        match = re.search(pattern, r2_path)

        if match:
            bucket = match.group(1)
            object_key = match.group(2)

            try:
                self.client.delete_object(
                    Bucket=bucket,
                    Key=object_key,
                )

                LOGGER.info(f"Deleted object: {r2_path}")
                return True
            except:
                LOGGER.error(f"Error deleting object: {r2_path}")
                return False
        else:
            return None

    def delete_objects(self, r2_path_list):
        pattern = r"https://cdn\.caracole\.ph/([^/]+)/(.*)"
        objects_to_delete = {"Objects": []}

        for r2_path in r2_path_list:
            match = re.search(pattern, r2_path)

            if match:
                bucket = match.group(1)
                object_key = match.group(2)
                objects_to_delete["Objects"].append({"Key": f"{bucket}/{object_key}"})

        if len(objects_to_delete["Objects"]) > 0:
            self.client.delete_objects(
                Bucket=self.bucket,
                Delete=objects_to_delete,
            )

            LOGGER.info(f"Deleted {len(r2_path_list)} objects.")
            return True
