from __future__ import annotations

from pathlib import Path
from typing import Any

from niannian.storage.baidu_pcs import (
    BaiduPCSClient,
    DEFAULT_CHUNK_SIZE_BYTES,
    DEFAULT_MAX_UPLOAD_BYTES,
    DEFAULT_PCS_API_BASE,
    DEFAULT_PCS_SUPERFILE_BASE,
    DEFAULT_UPLOAD_MAX_BYTES,
)
from niannian.storage.cloud_base import FileCloudBackend, HttpOpener, LiveCloudBackend

DEFAULT_BAIDU_API_BASE = "https://pan.baidu.com"


class BaiduLiveBackend(LiveCloudBackend):
    """百度 L1 live — Vault refresh + PCS upload/download。"""

    def __init__(
        self,
        mirror_root: Path,
        *,
        access_token: str | None,
        api_base: str | None = None,
        pcs_api_base: str | None = None,
        pcs_superfile_base: str | None = None,
        upload_max_bytes: int | None = None,
        chunk_size_bytes: int | None = None,
        max_upload_bytes: int | None = None,
        timeout: float = 30.0,
        http_opener: HttpOpener | None = None,
        credential_manager: Any | None = None,
        remote_root: str | None = None,
    ) -> None:
        self._pcs_client: BaiduPCSClient | None = None
        if access_token:
            state_path = mirror_root.parent.parent / "sync" / "baidu_pcs_state.json"
            self._pcs_client = BaiduPCSClient(
                access_token,
                remote_root=remote_root,
                pcs_api_base=pcs_api_base or DEFAULT_PCS_API_BASE,
                pcs_superfile_base=pcs_superfile_base or DEFAULT_PCS_SUPERFILE_BASE,
                upload_max_bytes=upload_max_bytes or DEFAULT_UPLOAD_MAX_BYTES,
                chunk_size_bytes=chunk_size_bytes or DEFAULT_CHUNK_SIZE_BYTES,
                max_upload_bytes=max_upload_bytes or DEFAULT_MAX_UPLOAD_BYTES,
                timeout=timeout,
                http_opener=http_opener,
                state_path=state_path,
                credential_manager=credential_manager,
            )
        super().__init__(
            "baidu",
            mirror_root,
            token=access_token,
            api_base=api_base or DEFAULT_BAIDU_API_BASE,
            timeout=timeout,
            http_opener=http_opener,
            credential_manager=credential_manager,
            provider="baidu",
            remote_root=remote_root,
        )

    def _remote_put(self, rel_path: str, data: bytes) -> None:
        if self._pcs_client is not None:
            self._pcs_client.upload_object(rel_path, data)
            if self._credential_manager is not None:
                new_token = self._credential_manager.get_access_token("baidu")
                if new_token:
                    self.token = new_token
                    self._pcs_client._access_token = new_token
            return
        super()._remote_put(rel_path, data)

    def _remote_get(self, rel_path: str) -> bytes | None:
        if self._pcs_client is not None:
            if self._credential_manager is not None:
                new_token = self._credential_manager.get_access_token("baidu")
                if new_token:
                    self.token = new_token
                    self._pcs_client._access_token = new_token
            return self._pcs_client.download_object(rel_path)
        return super()._remote_get(rel_path)


def build_baidu_backend(
    root: Path,
    *,
    access_token: str | None = None,
    refresh_token: str | None = None,
    force_mirror: bool = False,
    api_base: str | None = None,
    pcs_api_base: str | None = None,
    pcs_superfile_base: str | None = None,
    upload_max_bytes: int | None = None,
    chunk_size_bytes: int | None = None,
    max_upload_bytes: int | None = None,
    http_opener: HttpOpener | None = None,
    credential_manager: Any | None = None,
    **kwargs: Any,
) -> FileCloudBackend | BaiduLiveBackend:
    token = access_token or refresh_token
    if credential_manager is not None:
        token = credential_manager.get_access_token("baidu") or token
    if token and not force_mirror:
        return BaiduLiveBackend(
            root,
            access_token=token,
            api_base=api_base,
            pcs_api_base=pcs_api_base,
            pcs_superfile_base=pcs_superfile_base,
            upload_max_bytes=upload_max_bytes,
            chunk_size_bytes=chunk_size_bytes,
            max_upload_bytes=max_upload_bytes,
            http_opener=http_opener,
            credential_manager=credential_manager,
            **{k: v for k, v in kwargs.items() if k in ("timeout", "remote_root")},
        )
    return FileCloudBackend("baidu", root, token=token)
