from fastapi import UploadFile, HTTPException
import boto3
from botocore.exceptions import BotoCoreError, ClientError
import os
from datetime import datetime
from dotenv import load_dotenv
import json

load_dotenv()
AWS_REGION = os.getenv('AWS_REGION')
BUCKET_NAME = os.getenv('BUCKET_NAME')
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')

class S3Service:
    def __init__(self):
        """
        Initialize the AWS client
        """
        self.bucket_name = BUCKET_NAME
        self.s3_client = boto3.client(
            's3',
            region_name=AWS_REGION,
            aws_access_key_id=AWS_ACCESS_KEY_ID,
            aws_secret_access_key=AWS_SECRET_ACCESS_KEY
        )

    def create_directory(self, directory_name: str):
        """
        Create a 'directory' in S3 (actually a prefix ending with '/')
        """
        try:
            self.s3_client.put_object(Bucket=self.bucket_name, Key=f"{directory_name}/")
            return {"message": f"Directory '{directory_name}' created successfully."}
        except (BotoCoreError, ClientError) as e:
            raise HTTPException(status_code=400, detail=str(e))

    def upload_object(self, directory_name: str, sanitized_name: str, file: UploadFile):
        """
        Upload a file to the specified S3 directory
        """
        try:
            file_extension = os.path.splitext(file.filename)[1]
            file_key = f"{directory_name}/{sanitized_name}{file_extension}"
            extra_args = {"ACL": "public-read"}
            self.s3_client.upload_fileobj(file.file, self.bucket_name, file_key)
            file_url = f"https://{self.bucket_name}.s3.{self.s3_client.meta.region_name}.amazonaws.com/{file_key}"
            return {"message": f"File '{file.filename}' uploaded to '{directory_name}' successfully.","file_url": file_url}
        except (BotoCoreError, ClientError) as e:
            raise HTTPException(status_code=400, detail=str(e))

    def fetch_object(self,directory_name: str):
        """
        Fetch files in a specific S3 directory
        """
        try:
            response = self.s3_client.list_objects_v2(Bucket=self.bucket_name, Prefix=f"{directory_name}/")
            if 'Contents' not in response:
                return {"files": []}
            
            files = [obj['Key'] for obj in response['Contents']]
            return {"files": files}
        except (BotoCoreError, ClientError) as e:
            raise HTTPException(status_code=400, detail=str(e))

    def get_directory_size(directory_name: str):
        """
        Get the total size of files in a directory
        """
        try:
            response = self.s3_client.list_objects_v2(Bucket=self.bucket_name, Prefix=f"{directory_name}/")
            if 'Contents' not in response:
                return {"directory_size": 0}
            
            total_size = sum(obj['Size'] for obj in response['Contents'])
            return {"directory_size": total_size}
        except (BotoCoreError, ClientError) as e:
            raise HTTPException(status_code=400, detail=str(e))

    def get_object_url(self, file_key):
        file_url = f"https://{self.bucket_name}.s3.{self.s3_client.meta.region_name}.amazonaws.com/{file_key}"
        return file_url

    def delete_file(self, file_key: str):
        """
        Delete a file from the S3 bucket.

        Args:
            file_key (str): The key (path) of the file to delete in the S3 bucket.

        Returns:
            dict: Success message.
        """
        try:
            self.s3_client.delete_object(Bucket=self.bucket_name, Key=file_key)
            return {"message": f"File '{file_key}' deleted successfully."}
        except Exception as e:
            raise HTTPException(status_code=400, detail=str(e))