"""
阿里云盘适配器 v1.0.0
AliyunAdapter — 继承 BaseCloudDriveAdapter，实现阿里云盘全部转存能力。

组件：
- AliyunCredentialManager: refresh_token 刷新 + 缓存
- AliyunTransfer: 4 步批量转存
- AliyunCleanup: 回收站清理

URL 匹配: aliyundrive.com/s/<share_id>
"""

import re
import logging
from typing import List, Dict, Tuple, Optional

from ..base import BaseCloudDriveAdapter, FileInfo, match_url
from ..config import PlatformConfig, TransferConfig
from ..errors import TransferError, TransferErrorCode

from .credential import AliyunCredentialManager
from .transfer import AliyunTransfer
from .cleanup import AliyunCleanup

logger = logging.getLogger(__name__)


class AliyunAdapter(BaseCloudDriveAdapter):
    """阿里云盘适配器"""

    PLATFORM_NAME = "阿里云盘"
    PLATFORM_KEY = "aliyun"

    URL_PATTERNS = [
        r'aliyundrive\.com/s/([a-zA-Z0-9]+)',
        r'alipan\.com/s/([a-zA-Z0-9]+)',
    ]

    DEFAULT_HEADERS = {
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/135.0.0.0 Safari/537.36"
        ),
        "Accept": "application/json, text/plain, */*",
        "Content-Type": "application/json",
        "Referer": "https://aliyundrive.com",
    }

    def __init__(self, config: PlatformConfig, transfer_config: TransferConfig):
        super().__init__(config, transfer_config)

        # 创建凭证管理器（AliyunCredentialManager）
        refresh_token = config.refresh_token or config.cookie or ""
        self._credential = AliyunCredentialManager(refresh_token=refresh_token)

        # 初始化 drive_id
        self._drive_id = ""

        # 创建子模块
        self._transfer: Optional[AliyunTransfer] = None
        self._cleanup: Optional[AliyunCleanup] = None

    def _setup_session(self):
        """初始化 session 和凭证"""
        if self._credential.refresh_token:
            # 验证 refresh_token 并获取 drive_id
            if self._credential.validate():
                self._drive_id = self._credential.get_drive_id()
                logger.info(
                    f"[AliyunAdapter] 凭证验证成功, drive_id={self._drive_id[:8]}..."
                )
            else:
                logger.warning("[AliyunAdapter] 凭证验证失败，转存功能可能不可用")
        else:
            logger.warning("[AliyunAdapter] 未配置 refresh_token")

    # ─── 核心抽象方法实现 ──────────────────────────────────

    def _get_share_detail(self, pwd_id: str, passcode: str = "") -> dict:
        """
        获取分享详情。
        步骤①②: 先获取匿名分享信息，再获取 share_token。

        Returns:
            {
                "title": "分享标题",
                "share_id": "...",
                "share_token": "...",
                "files": [{"file_id": "...", "name": "...", "size": 0, "type": "file"}, ...],
            }
        """
        try:
            transfer = self._get_transfer()

            # ① 获取分享信息（匿名）
            share_info = transfer._get_share_info(pwd_id)
            if not share_info:
                raise TransferError(
                    TransferErrorCode.SHARE_NOT_EXIST,
                    platform=self.PLATFORM_KEY,
                )

            # ② 获取分享令牌（Auth）
            share_token = transfer._get_share_token(pwd_id, passcode)
            if not share_token:
                raise TransferError(
                    TransferErrorCode.PASSCODE_WRONG if passcode else TransferErrorCode.SHARE_NOT_EXIST,
                    platform=self.PLATFORM_KEY,
                    message="获取分享令牌失败（可能需要提取码）",
                )

            return {
                "title": share_info.get("share_name", share_info.get("share_title", "")),
                "share_id": pwd_id,
                "share_token": share_token,
                "files": share_info.get("file_infos", []),
                "creator_name": share_info.get("creator_name", ""),
            }

        except TransferError:
            raise
        except Exception as e:
            logger.exception(f"[AliyunAdapter] 获取分享详情失败: {e}")
            raise TransferError(
                TransferErrorCode.NETWORK_ERROR,
                message=str(e),
                platform=self.PLATFORM_KEY,
            )

    def _save_files(self, pwd_id: str, detail: dict, save_dir: str) -> List[str]:
        """
        步骤③: 批量复制文件到自己的网盘。

        Args:
            pwd_id: 分享 ID
            detail: _get_share_detail 的返回值
            save_dir: 目标目录（根目录用 "root"）

        Returns:
            新文件 ID 列表
        """
        share_token = detail.get("share_token", "")
        files = detail.get("files", [])

        if not share_token:
            raise TransferError(
                TransferErrorCode.SHARE_NOT_EXIST,
                message="缺少 share_token",
                platform=self.PLATFORM_KEY,
            )

        if not files:
            raise TransferError(
                TransferErrorCode.RESOURCE_EMPTY,
                platform=self.PLATFORM_KEY,
            )

        file_ids = [f.get("file_id", "") for f in files if f.get("file_id")]
        if not file_ids:
            raise TransferError(
                TransferErrorCode.RESOURCE_EMPTY,
                message="无法提取文件 ID",
                platform=self.PLATFORM_KEY,
            )

        # 确定目标目录
        to_parent = save_dir if save_dir and save_dir != "/" else "root"

        transfer = self._get_transfer()
        new_ids = transfer._batch_copy(pwd_id, share_token, file_ids, to_parent)

        if not new_ids:
            raise TransferError(
                TransferErrorCode.NETWORK_ERROR,
                message="批量转存失败，所有文件复制均失败",
                platform=self.PLATFORM_KEY,
            )

        return new_ids

    def _create_share(
        self, file_ids: List[str], title: str, password: str = ""
    ) -> Tuple[str, str]:
        """
        步骤④: 创建新分享链接。

        Returns:
            (share_url, share_password)
        """
        if not file_ids:
            raise TransferError(
                TransferErrorCode.RESOURCE_EMPTY,
                platform=self.PLATFORM_KEY,
            )

        transfer = self._get_transfer()
        result = transfer._create_share(file_ids, password)

        share_url = result.get("share_url", "")
        share_pwd = result.get("share_pwd", password)

        if not share_url:
            raise TransferError(
                TransferErrorCode.SHARE_LINK_FAIL,
                message="创建分享链接失败",
                platform=self.PLATFORM_KEY,
            )

        return share_url, share_pwd

    def get_files(self, parent_fid: str = "0") -> List[FileInfo]:
        """
        列出网盘目录下的文件。

        NOTE: 当前实现为占位。如需完整功能，请调用阿里云盘 /adrive/v3/file/list API。
        """
        logger.warning("[AliyunAdapter] get_files() 未完整实现，返回空列表")
        return []

    def delete(self, file_ids: List[str]) -> bool:
        """
        删除文件（移入回收站）。

        Args:
            file_ids: 要删除的文件 ID 列表

        Returns:
            是否全部删除成功
        """
        if not file_ids:
            return True

        cleanup = self._get_cleanup()
        result = cleanup.delete_files(file_ids)
        return result.get("success", False)

    # ─── 扩展功能 ──────────────────────────────────────────

    def cleanup_files(self, file_ids: List[str]) -> Dict:
        """
        清理文件（移入回收站），返回详细结果。

        Returns:
            AliyunCleanup.delete_files() 的返回字典
        """
        cleanup = self._get_cleanup()
        return cleanup.delete_files(file_ids)

    def force_refresh_token(self) -> bool:
        """强制刷新 access_token"""
        return self._credential.refresh()

    def get_credential_status(self) -> Dict:
        """获取当前凭证状态"""
        return self._credential.to_dict()

    # ─── 文件列表提取 ──────────────────────────────────────

    def _extract_file_list(self, detail: dict) -> List[FileInfo]:
        """从分享详情中提取 FileInfo 列表"""
        files = detail.get("files", [])
        result = []
        for f in files:
            result.append(FileInfo(
                fid=f.get("file_id", ""),
                name=f.get("name", ""),
                size=int(f.get("size", 0)),
                is_dir=f.get("type", "") == "folder",
                ext=f.get("file_extension", ""),
            ))
        return result

    # ─── 内部辅助方法 ──────────────────────────────────────

    def _get_transfer(self) -> AliyunTransfer:
        """懒加载获取 AliyunTransfer 实例"""
        if self._transfer is None:
            drive_id = self._drive_id or self._credential.get_drive_id()
            self._transfer = AliyunTransfer(
                credential=self._credential,
                drive_id=drive_id,
                to_parent_file_id=self.config.save_dir or "root",
                request_timeout=self.transfer_config.request_timeout,
            )
        return self._transfer

    def _get_cleanup(self) -> AliyunCleanup:
        """懒加载获取 AliyunCleanup 实例"""
        if self._cleanup is None:
            drive_id = self._drive_id or self._credential.get_drive_id()
            self._cleanup = AliyunCleanup(
                credential=self._credential,
                drive_id=drive_id,
                request_timeout=self.transfer_config.request_timeout,
            )
        return self._cleanup
