"""
File service for handling file operations and AWS S3 integration.
"""

import os
import tempfile

from app.core.config import settings
from app.core.logging import get_logger
from app.services.aws_service import AWSService
from app.utils.s3_utils import normalize_key

logger = get_logger("file_service")


class FileService:
    """Service for file operations and AWS S3 integration."""

    def __init__(self):
        self.aws_service = AWSService()
        self.temp_dir = tempfile.gettempdir()

    async def upload_file_to_s3(
        self, file_path: str, bucket: str, key: str, content_type: str | None = None
    ) -> bool:
        """Upload a file to AWS S3."""
        try:
            if not os.path.exists(file_path):
                logger.error(f"File not found: {file_path}")
                return False

            success = await self.aws_service.upload_file(
                file_path, bucket, key, content_type
            )

            if success:
                logger.info(f"Successfully uploaded {file_path} to s3://{bucket}/{key}")
            else:
                logger.error(f"Failed to upload {file_path} to s3://{bucket}/{key}")

            return success

        except Exception as e:
            logger.error(f"Error uploading file to S3: {e}")
            return False

    async def download_file_from_s3(
        self, bucket: str, key: str, local_path: str
    ) -> bool:
        """Download a file from AWS S3."""
        try:
            # Normalize legacy keys consistently
            norm_key = normalize_key(key)

            # Ensure the directory exists
            os.makedirs(os.path.dirname(local_path), exist_ok=True)

            success = await self.aws_service.download_file_with_fallback(
                bucket, norm_key, local_path
            )

            if success:
                logger.info(
                    f"Successfully downloaded s3://{bucket}/{norm_key} to {local_path}"
                )
            else:
                logger.error(
                    f"Failed to download s3://{bucket}/{norm_key} to {local_path}"
                )

            return success

        except Exception as e:
            logger.error(f"Error downloading file from S3: {e}")
            return False

    async def download_from_s3_path(self, s3_path: str, file_type: str) -> str | None:
        """Download a file given either an s3:// URL or a raw key.

        Returns the local path on success, None otherwise.
        """
        try:
            # Extract bucket and key from S3 path or use defaults
            if s3_path.startswith("s3://"):
                parts = s3_path[5:].split("/", 1)
                bucket = parts[0]
                key = parts[1] if len(parts) > 1 else ""
            else:
                bucket = settings.AWS_S3_BUCKET
                key = s3_path

            with tempfile.NamedTemporaryFile(
                delete=False, suffix=f"_{os.path.basename(key)}"
            ) as temp_file:
                local_path = temp_file.name
            success = await self.download_file_from_s3(bucket, key, local_path)
            if success:
                logger.info(
                    f"Downloaded {file_type} from S3: s3://{bucket}/{key} -> {local_path}"
                )
                return local_path
            logger.error(f"Failed to download {file_type} from S3: s3://{bucket}/{key}")
            return None
        except Exception as e:
            logger.error(f"Failed to download {file_type} from S3: {e}")
            return None

    async def get_file_url(
        self, bucket: str, key: str, expires_in: int = 3600
    ) -> str | None:
        """Generate a presigned URL for a file in S3."""
        try:
            url = await self.aws_service.generate_presigned_url(bucket, key, expires_in)

            if url:
                logger.info(f"Generated presigned URL for s3://{bucket}/{key}")
            else:
                logger.error(
                    f"Failed to generate presigned URL for s3://{bucket}/{key}"
                )

            return url

        except Exception as e:
            logger.error(f"Error generating presigned URL: {e}")
            return None

    def cleanup_temp_file(self, file_path: str) -> bool:
        """Clean up a temporary file."""
        try:
            if os.path.exists(file_path):
                os.unlink(file_path)
                logger.info(f"Cleaned up temporary file: {file_path}")
                return True
            return False

        except Exception as e:
            logger.error(f"Error cleaning up temp file {file_path}: {e}")
            return False
