from __future__ import annotations

from pathlib import Path
from typing import Any

from niannian.storage.cloud_base import CloudBackend, FileCloudBackend
from niannian.storage.onedrive_live import OneDriveLiveBackend, build_onedrive_backend


class OneDriveBackend:
    """OneDrive L1 — OAuth bearer 鉴权；live 或 mirror。"""

    def __init__(
        self,
        root: Path,
        *,
        access_token: str | None = None,
        refresh_token: str | None = None,
        force_mirror: bool = False,
        graph_base: str | None = None,
        upload_max_bytes: int | None = None,
        http_opener: Any | None = None,
        credential_manager: Any | None = None,
        **kwargs: Any,
    ) -> None:
        token = access_token or refresh_token
        self._delegate: CloudBackend = build_onedrive_backend(
            root,
            access_token=token,
            refresh_token=refresh_token,
            force_mirror=force_mirror,
            graph_base=graph_base,
            upload_max_bytes=upload_max_bytes,
            http_opener=http_opener,
            credential_manager=credential_manager,
            **kwargs,
        )

    @property
    def name(self) -> str:
        return self._delegate.name

    @property
    def root(self) -> Path:
        return self._delegate.root

    @property
    def token(self) -> str | None:
        delegate = self._delegate
        if isinstance(delegate, (FileCloudBackend, OneDriveLiveBackend)):
            return delegate.token
        return None

    @property
    def last_upload_degraded(self) -> bool:
        return bool(getattr(self._delegate, "last_upload_degraded", False))

    def is_configured(self) -> bool:
        return self._delegate.is_configured()

    def status(self) -> str:
        return self._delegate.status()

    def primary_mode(self) -> str:
        return self._delegate.primary_mode()

    def tier_ping(self) -> bool:
        custom = getattr(self._delegate, "tier_ping", None)
        if callable(custom):
            return bool(custom())
        return self.is_configured()

    def upload(self, rel_path: str, data: bytes) -> bool:
        return self._delegate.upload(rel_path, data)

    def download(self, rel_path: str) -> bytes | None:
        return self._delegate.download(rel_path)
