import logging
from pathlib import Path
from typing import Optional
from urllib.parse import quote

from .config import Settings


logger = logging.getLogger(__name__)


class VolcanoOSSUploader:
    """Upload course videos to Volcano Engine Object Storage (TOS)."""

    def __init__(self, settings: Settings):
        self.settings = settings

    @property
    def enabled(self) -> bool:
        return self.settings.volcano_oss_enabled

    def object_key(self, video_hash: str, stored_filename: str) -> str:
        normalized_hash = video_hash.strip().lower()
        suffix = Path(stored_filename).suffix or ".mp4"
        return f"{self.settings.volcano_oss_key_prefix}{normalized_hash}{suffix}"

    def public_url(self, object_key: str) -> str:
        return self.settings.volcano_oss_public_url(object_key)

    def upload(
        self,
        *,
        video_hash: str,
        stored_filename: str,
        local_path: Path,
        content_type: Optional[str] = None,
    ) -> str:
        """Upload one local file and return its permanent public URL."""
        if not self.enabled:
            raise RuntimeError("Volcano OSS is not configured.")
        if not local_path.is_file():
            raise FileNotFoundError(f"Cannot upload a missing video: {local_path}")

        # Keep the SDK import optional for development machines that do not run
        # the production service. It is declared in sentence_api/requirements.txt.
        try:
            import tos
        except ImportError as exc:
            raise RuntimeError(
                "The Volcano TOS SDK is not installed. Run: pip install tos"
            ) from exc

        object_key = self.object_key(video_hash, stored_filename)
        endpoint = self.settings.volcano_oss_endpoint
        client = tos.TosClientV2(
            self.settings.volcano_oss_access_key,
            self.settings.volcano_oss_secret_key,
            endpoint,
            self.settings.volcano_oss_region,
        )
        try:
            client.put_object_from_file(
                self.settings.volcano_oss_bucket,
                object_key,
                str(local_path),
            )
        except Exception:
            logger.exception(
                "Volcano OSS upload failed: bucket=%s key=%s endpoint=%s",
                self.settings.volcano_oss_bucket,
                object_key,
                endpoint,
            )
            raise

        logger.info("Uploaded %s to Volcano OSS object %s", local_path.name, object_key)
        return self.public_url(object_key)
