from loguru import logger
from minio import Minio
from minio.commonconfig import CopySource

from src.core.config import S3_HOST, S3_ACCESS_KEY, S3_SECRET_KEY, S3_BUCKET_NAME


class S3Client:
    HOST = S3_HOST
    ACCESS_KEY = S3_ACCESS_KEY
    SECRET_KEY = S3_SECRET_KEY
    BUCKET_NAME = S3_BUCKET_NAME

    def __init__(self):
        self.client = Minio(
            self.HOST,
            access_key=self.ACCESS_KEY,
            secret_key=self.SECRET_KEY,
            secure=True
        )

    def _make_sure_bucket_exist(self):
        found = self.client.bucket_exists(self.BUCKET_NAME)
        if not found:
            self.client.make_bucket(self.BUCKET_NAME)
        else:
            logger.info(f"Bucket {self.BUCKET_NAME} already exists")

    def upload(self, file_name: str, file_path: str | list[str]):
        self._make_sure_bucket_exist()
        if isinstance(file_name, str):
            file_path = file_path + file_name
            self.client.fput_object(self.BUCKET_NAME, file_name, file_path)
            logger.info(f"{file_path} is successfully uploaded as object {file_name} to bucket {self.BUCKET_NAME}.")
            link_to_download = self.get(file_name)
            return link_to_download
        else:
            result = []
            for file_name_part in file_name:
                current_file_path = file_path + file_name_part
                self.client.fput_object(self.BUCKET_NAME, file_name_part, current_file_path)
                logger.info(f"{current_file_path} is successfully uploaded as object {file_name_part} to bucket {self.BUCKET_NAME}.")
                link_to_download = self.get(file_name_part)
                result.append(link_to_download)
            return result

    def get(self, file_name: str):
        self._make_sure_bucket_exist()
        result = self.client.get_presigned_url(
            "GET",
            self.BUCKET_NAME,
            file_name,
        )
        return result

    def delete(self, file_name: str):
        result = self.client.remove_object(self.BUCKET_NAME, file_name)
        return result

    def copy_to_another_bucket(self, file_name: str, bucket_name):
        result = self.client.copy_object(
            bucket_name,
            file_name,
            CopySource(self.BUCKET_NAME, file_name),
        )
        return result
