from __future__ import annotations

import logging
from pathlib import Path
from typing import Any

from niannian.storage.baidu import BaiduBackend
from niannian.storage.cloud_auth.manager import CloudCredentialManager
from niannian.storage.cloud_base import resolve_cloud_root, resolve_remote_root
from niannian.storage.cloud_dual import CloudDualBackend
from niannian.storage.cloud_tier import CloudTierRouter
from niannian.storage.feimao import FeimaoBackend
from niannian.storage.feimao_http import feimao_connectivity_options
from niannian.storage.onedrive import OneDriveBackend
from niannian.storage.primary_backup import PrimaryBackupBackend
from niannian.storage.quark import QuarkBackend
from niannian.storage.tier_chain import is_feimao_disabled

logger = logging.getLogger(__name__)

CloudBackendUnion = CloudDualBackend | PrimaryBackupBackend | CloudTierRouter


def _resolve_primary_mode(primary_cfg: dict[str, Any]) -> str:
    mode = primary_cfg.get("mode", "tiered")
    if mode in ("primary_backup", "dual_cloud"):
        logger.warning("storage.primary.mode=%s is deprecated — use tiered", mode)
        if mode == "dual_cloud":
            return "dual_cloud"
        return "primary_backup"
    return "tiered"


def build_feimao_shim(
    home: Path,
    *,
    config: dict[str, Any],
    providers: dict[str, Any],
    tier_cfg: dict[str, Any],
    cred_mgr: CloudCredentialManager,
) -> FeimaoBackend:
    """飞猫 disabled shim — mirror-only 空 token backend，禁止 tier 写路径。"""
    feimao_cfg = providers.get("feimao") or {}
    return FeimaoBackend(
        resolve_cloud_root(home, "feimao", feimao_cfg),
        session_token=None,
        force_mirror=True,
        live=False,
        api_base=feimao_cfg.get("api_base"),
        credential_manager=cred_mgr,
        remote_root=resolve_remote_root(config, feimao_cfg),
        **feimao_connectivity_options(config, feimao_cfg=feimao_cfg),
    )


def build_cloud_backend(
    home: Path,
    *,
    config: dict[str, Any] | None = None,
    providers: dict[str, Any] | None = None,
    credential_manager: CloudCredentialManager | None = None,
) -> CloudBackendUnion:
    config = config or {}
    providers = providers or {}
    storage_cfg = config.get("storage") or {}
    primary_cfg = storage_cfg.get("primary") or {}
    tier_cfg = storage_cfg.get("tier") or {}
    mode = _resolve_primary_mode(primary_cfg)

    cred_mgr = credential_manager or CloudCredentialManager(home, config=config)
    cred_mgr.ensure_legacy_import(providers)

    quark_cfg = providers.get("quark") or {}
    baidu_cfg = providers.get("baidu") or {}
    onedrive_cfg = providers.get("onedrive") or {}

    cloud_cfg = storage_cfg.get("cloud") or {}
    baidu_cloud_cfg = cloud_cfg.get("baidu") or {}
    onedrive_cloud_cfg = cloud_cfg.get("onedrive") or {}
    quark_cloud_cfg = cloud_cfg.get("quark") or {}
    onedrive_tier = tier_cfg.get("onedrive") or {}

    quark = QuarkBackend(
        resolve_cloud_root(home, "quark", quark_cfg),
        refresh_token=quark_cfg.get("refresh_token") or cred_mgr.get_refresh_token("quark"),
        cookie=quark_cfg.get("cookie") or cred_mgr.get_cookie("quark"),
        api_base=quark_cfg.get("api_base"),
        force_mirror=bool(quark_cfg.get("force_mirror")),
        credential_manager=cred_mgr,
        remote_root=resolve_remote_root(config, quark_cfg),
        chunk_size_bytes=quark_cloud_cfg.get("chunk_size_bytes"),
        max_upload_bytes=quark_cloud_cfg.get("max_upload_bytes"),
    )
    baidu = BaiduBackend(
        resolve_cloud_root(home, "baidu", baidu_cfg),
        access_token=baidu_cfg.get("access_token") or baidu_cfg.get("refresh_token"),
        refresh_token=baidu_cfg.get("refresh_token") or cred_mgr.get_refresh_token("baidu"),
        credential_manager=cred_mgr,
        remote_root=resolve_remote_root(config, baidu_cfg),
        pcs_api_base=baidu_cloud_cfg.get("pcs_api_base"),
        pcs_superfile_base=baidu_cloud_cfg.get("pcs_superfile_base"),
        upload_max_bytes=baidu_cloud_cfg.get("upload_max_bytes"),
        chunk_size_bytes=baidu_cloud_cfg.get("chunk_size_bytes"),
        max_upload_bytes=baidu_cloud_cfg.get("max_upload_bytes"),
    )
    onedrive_live = bool(onedrive_tier.get("live", True))
    onedrive = OneDriveBackend(
        resolve_cloud_root(home, "onedrive", onedrive_cfg),
        access_token=onedrive_cfg.get("access_token") or cred_mgr.get_access_token("onedrive"),
        refresh_token=onedrive_cfg.get("refresh_token") or cred_mgr.get_refresh_token("onedrive"),
        force_mirror=not onedrive_live,
        graph_base=onedrive_cloud_cfg.get("graph_base"),
        upload_max_bytes=onedrive_cloud_cfg.get("upload_max_bytes"),
        chunk_size_bytes=onedrive_cloud_cfg.get("chunk_size_bytes"),
        max_upload_bytes=onedrive_cloud_cfg.get("max_upload_bytes"),
        credential_manager=cred_mgr,
        remote_root=resolve_remote_root(config, onedrive_cfg),
    )

    if is_feimao_disabled(tier_cfg):
        build_feimao_shim(home, config=config, providers=providers, tier_cfg=tier_cfg, cred_mgr=cred_mgr)

    notify_cfg = (config.get("notifications") or {}).get("tier") or {}
    if mode == "dual_cloud":
        cred_mgr.end_boot_phase()
        return CloudDualBackend(quark, baidu)
    if mode == "primary_backup":
        cred_mgr.end_boot_phase()
        return PrimaryBackupBackend(quark, baidu, backup_cfg=primary_cfg.get("backup") or {})
    router = CloudTierRouter(
        home,
        quark,
        baidu,
        onedrive,
        tier_cfg=tier_cfg,
        notify_cfg=notify_cfg,
        credential_manager=cred_mgr,
    )
    cred_mgr.end_boot_phase()
    return router
