"""S3 operations for uploading and downloading files"""

import logging
from pathlib import Path

import boto3

logger = logging.getLogger(__name__)


class S3Client:
    """Client for S3 operations"""

    def __init__(self, region: str = "us-east-1"):
        self.client = boto3.client("s3", region_name=region)

    def upload_file(self, local_file: Path, s3_bucket: str, s3_key: str) -> str:
        """Upload a local file to S3 and return the S3 key

        Args:
            local_file: Path to local file
            s3_key: S3 key to upload to

        Returns:
            The S3 key of the uploaded file
        """
        logger.info(f"Uploading {local_file.name} to s3://{s3_bucket}/{s3_key}")

        with open(local_file, "rb") as f:
            self.client.upload_fileobj(f, s3_bucket, s3_key)

        logger.info(f"Upload complete: {s3_key}")
        return s3_key

    def download_file(
        self,
        s3_bucket: str,
        s3_key: str,
        local_path: Path,
        replace_existing: bool = True,
    ) -> Path:
        """Download a file from S3 to local directory

        Args:
            s3_key: S3 key to download
            local_path: Local path to save file

        Returns:
            Path to the downloaded file
        """
        if local_path.exists() and not replace_existing:
            logger.info(f"File {local_path} already exists, skipping download")
            return local_path

        logger.info(f"Downloading s3://{s3_bucket}/{s3_key} to {local_path}")

        try:
            self.client.download_file(s3_bucket, s3_key, str(local_path))
            logger.info(f"Download complete: {local_path}")
        except Exception as e:
            logger.error(f"Failed to download {s3_key}: {e}")
            raise

        return local_path

    def copy_file(
        self, s3_bucket: str, s3_key: str, s3_bucket_dest: str, s3_key_dest: str
    ) -> str:
        """Copy a file from one S3 bucket to another"""
        try:
            self.client.copy_object(
                Bucket=s3_bucket_dest,
                Key=s3_key_dest,
                CopySource={"Bucket": s3_bucket, "Key": s3_key},
            )
        except Exception as e:
            logger.error(f"Failed to copy {s3_key}: {e}")
            raise
        return s3_key_dest

    def file_exists(self, s3_bucket: str, s3_key: str) -> bool:
        """Check if a file exists in S3

        Args:
            s3_key: S3 key to check

        Returns:
            True if file exists, False otherwise
        """
        try:
            self.client.head_object(Bucket=s3_bucket, Key=s3_key)
            return True
        except Exception:
            return False
