import json
from datetime import UTC, datetime, timedelta

from google.cloud import storage
from google.cloud.storage.blob import Blob
from google.oauth2 import service_account


class GcpStorage:
    def __init__(self, credentials: str | dict | None = None):
        """
        Initialize GCP Storage client using either:
        - A JSON string containing service account credentials
        - A dict containing service account credentials
        - None (will attempt to use default credentials)
        """
        if credentials:
            # Convert string to dict if needed
            if isinstance(credentials, str):
                try:
                    credentials_dict = json.loads(credentials)
                except json.JSONDecodeError as e:
                    raise ValueError(
                        "Invalid JSON string provided for credentials"
                    ) from e
            else:
                credentials_dict = credentials

            # Create credentials object from dict
            credentials_obj = service_account.Credentials.from_service_account_info(
                credentials_dict
            )
            self.client = storage.Client(credentials=credentials_obj)
        else:
            # Use default credentials if none provided
            self.client = storage.Client()

    def _generate_signed_url(self, blob: Blob, minute_duration: int) -> str:
        expiration_time = datetime.now(UTC) + timedelta(minutes=minute_duration)

        url = blob.generate_signed_url(
            version="v4", expiration=expiration_time, method="GET"
        )

        return url

    async def get_file_url(
        self, filename: str, bucket: str, minute_duration: int, image: bool
    ) -> str:
        stock_url = (
            "https://t3.ftcdn.net/jpg/04/34/72/82/360_F_434728286_OWQQvAFoXZLdGHlObozsolNeuSxhpr84.jpg"
            if image
            else "https://www.banorte.com"
        )

        if not hasattr(self, "client"):
            return stock_url

        bucket_client = self.client.bucket(bucket)
        blob = bucket_client.blob(filename)

        if blob.exists():
            return self._generate_signed_url(blob, minute_duration)
        else:
            return stock_url

    async def get_blob_bytes(self, bucket: str, filename: str) -> bytes:
        if not hasattr(self, "client"):
            raise ValueError("No credentials provided to GCPStorage object.")

        bucket_client = self.client.bucket(bucket)
        blob = bucket_client.blob(filename)

        return blob.download_as_bytes()
