"""
Drive Service HTTP Client
呼叫 drive-api.ease.taipei 的 RESTful API 管理 Nextcloud 雲端硬碟帳號

架構說明:
- Drive Service 是獨立的微服務 (尚未部署)
- 本 Client 以非致命方式處理失敗 (失敗只記錄 warning,不影響其他流程)
- Drive Service 上線後自動生效,無需修改 HR Portal 核心邏輯
"""
import logging
from typing import Dict, Any, Optional

import requests
from requests.exceptions import ConnectionError, Timeout, RequestException

logger = logging.getLogger(__name__)

# Drive Service API 配額配置 (GB)，與 NAS 配額相同
DRIVE_QUOTA_BY_JOB_LEVEL = {
    "Junior": 50,
    "Mid": 100,
    "Senior": 200,
    "Manager": 500,
}


class DriveServiceClient:
    """
    Drive Service HTTP Client

    透過 REST API 管理 Nextcloud 雲端硬碟帳號:
    - 創建帳號 (POST /api/v1/drive/users)
    - 查詢配額 (GET /api/v1/drive/users/{id}/quota)
    - 更新配額 (PUT /api/v1/drive/users/{id}/quota)
    - 停用帳號 (DELETE /api/v1/drive/users/{id})

    失敗處理原則:
    - Drive Service 未上線時，連線失敗以 warning 記錄
    - 不拋出例外，回傳包含 error 的結果字典
    - 不影響 Keycloak、郵件等其他 onboarding 流程
    """

    def __init__(self, base_url: str, timeout: int = 10):
        self.base_url = base_url.rstrip("/")
        self.timeout = timeout
        self.session = requests.Session()
        self.session.headers.update({
            "Content-Type": "application/json",
            "Accept": "application/json",
        })

    def _is_available(self) -> bool:
        """快速檢查 Drive Service 是否可用"""
        try:
            resp = self.session.get(
                f"{self.base_url}/health",
                timeout=3,
            )
            return resp.status_code == 200
        except (ConnectionError, Timeout):
            return False
        except RequestException:
            return False

    def create_user(
        self,
        tenant_id: int,
        keycloak_user_id: str,
        username: str,
        email: str,
        display_name: str,
        quota_gb: int,
    ) -> Dict[str, Any]:
        """
        創建 Nextcloud 帳號

        POST /api/v1/drive/users

        Args:
            tenant_id: 租戶 ID
            keycloak_user_id: Keycloak UUID
            username: Nextcloud 使用者名稱 (username_base)
            email: 電子郵件
            display_name: 顯示名稱
            quota_gb: 配額 (GB)

        Returns:
            {
                "created": True/False,
                "user_id": int or None,
                "username": str,
                "quota_gb": int,
                "drive_url": str,
                "message": str,
                "error": str or None,
            }
        """
        try:
            resp = self.session.post(
                f"{self.base_url}/api/v1/drive/users",
                json={
                    "tenant_id": tenant_id,
                    "keycloak_user_id": keycloak_user_id,
                    "nextcloud_username": username,
                    "email": email,
                    "display_name": display_name,
                    "quota_gb": quota_gb,
                },
                timeout=self.timeout,
            )

            if resp.status_code == 201:
                data = resp.json()
                logger.info(f"Drive Service: 帳號建立成功 {username} ({quota_gb}GB)")
                return {
                    "created": True,
                    "user_id": data.get("id"),
                    "username": username,
                    "quota_gb": quota_gb,
                    "drive_url": f"https://drive.ease.taipei",
                    "message": f"雲端硬碟帳號建立成功 ({quota_gb}GB)",
                    "error": None,
                }
            elif resp.status_code == 409:
                logger.warning(f"Drive Service: 帳號已存在 {username}")
                return {
                    "created": False,
                    "user_id": None,
                    "username": username,
                    "quota_gb": quota_gb,
                    "drive_url": f"https://drive.ease.taipei",
                    "message": "雲端硬碟帳號已存在",
                    "error": "帳號已存在",
                }
            else:
                logger.warning(f"Drive Service: 建立帳號失敗 {username} - HTTP {resp.status_code}")
                return {
                    "created": False,
                    "user_id": None,
                    "username": username,
                    "quota_gb": quota_gb,
                    "drive_url": None,
                    "message": f"雲端硬碟帳號建立失敗 (HTTP {resp.status_code})",
                    "error": resp.text[:200],
                }

        except (ConnectionError, Timeout):
            logger.warning(f"Drive Service 未上線或無法連線，跳過帳號建立: {username}")
            return {
                "created": False,
                "user_id": None,
                "username": username,
                "quota_gb": quota_gb,
                "drive_url": None,
                "message": "Drive Service 尚未上線，跳過雲端硬碟帳號建立",
                "error": "Drive Service 無法連線",
            }
        except RequestException as e:
            logger.warning(f"Drive Service 請求失敗: {e}")
            return {
                "created": False,
                "user_id": None,
                "username": username,
                "quota_gb": quota_gb,
                "drive_url": None,
                "message": "Drive Service 請求失敗",
                "error": str(e),
            }

    def get_quota(self, drive_user_id: int) -> Optional[Dict[str, Any]]:
        """
        查詢配額使用量

        GET /api/v1/drive/users/{id}/quota

        Returns:
            {
                "quota_gb": float,
                "used_gb": float,
                "usage_percentage": float,
                "warning_threshold": bool,  # >= 80%
                "alert_threshold": bool,    # >= 95%
            }
            or None if Drive Service unavailable
        """
        try:
            resp = self.session.get(
                f"{self.base_url}/api/v1/drive/users/{drive_user_id}/quota",
                timeout=self.timeout,
            )

            if resp.status_code == 200:
                return resp.json()
            else:
                logger.warning(f"Drive Service: 查詢配額失敗 user_id={drive_user_id} - HTTP {resp.status_code}")
                return None

        except (ConnectionError, Timeout, RequestException):
            logger.warning(f"Drive Service 無法連線，無法查詢配額 user_id={drive_user_id}")
            return None

    def update_quota(self, drive_user_id: int, quota_gb: int) -> Dict[str, Any]:
        """
        更新配額

        PUT /api/v1/drive/users/{id}/quota

        Returns:
            {"updated": True/False, "quota_gb": int, "error": str or None}
        """
        try:
            resp = self.session.put(
                f"{self.base_url}/api/v1/drive/users/{drive_user_id}/quota",
                json={"quota_gb": quota_gb},
                timeout=self.timeout,
            )

            if resp.status_code == 200:
                logger.info(f"Drive Service: 配額更新成功 user_id={drive_user_id} -> {quota_gb}GB")
                return {"updated": True, "quota_gb": quota_gb, "error": None}
            else:
                logger.warning(f"Drive Service: 配額更新失敗 user_id={drive_user_id} - HTTP {resp.status_code}")
                return {
                    "updated": False,
                    "quota_gb": quota_gb,
                    "error": f"HTTP {resp.status_code}",
                }

        except (ConnectionError, Timeout, RequestException) as e:
            logger.warning(f"Drive Service 無法連線，無法更新配額: {e}")
            return {"updated": False, "quota_gb": quota_gb, "error": "Drive Service 無法連線"}

    def disable_user(self, drive_user_id: int) -> Dict[str, Any]:
        """
        停用帳號 (軟刪除)

        DELETE /api/v1/drive/users/{id}

        Returns:
            {"disabled": True/False, "error": str or None}
        """
        try:
            resp = self.session.delete(
                f"{self.base_url}/api/v1/drive/users/{drive_user_id}",
                timeout=self.timeout,
            )

            if resp.status_code in (200, 204):
                logger.info(f"Drive Service: 帳號停用成功 user_id={drive_user_id}")
                return {"disabled": True, "error": None}
            else:
                logger.warning(f"Drive Service: 帳號停用失敗 user_id={drive_user_id} - HTTP {resp.status_code}")
                return {
                    "disabled": False,
                    "error": f"HTTP {resp.status_code}",
                }

        except (ConnectionError, Timeout, RequestException) as e:
            logger.warning(f"Drive Service 無法連線，無法停用帳號: {e}")
            return {"disabled": False, "error": "Drive Service 無法連線"}


def get_drive_quota_by_job_level(job_level: str) -> int:
    """根據職級取得雲端硬碟配額 (GB)"""
    return DRIVE_QUOTA_BY_JOB_LEVEL.get(job_level, DRIVE_QUOTA_BY_JOB_LEVEL["Junior"])


# 延遲初始化單例
_drive_service_client: Optional[DriveServiceClient] = None


def get_drive_service_client() -> DriveServiceClient:
    """取得 DriveServiceClient 單例 (延遲初始化)"""
    global _drive_service_client
    if _drive_service_client is None:
        from app.core.config import settings
        _drive_service_client = DriveServiceClient(
            base_url=settings.DRIVE_SERVICE_URL,
            timeout=settings.DRIVE_SERVICE_TIMEOUT,
        )
    return _drive_service_client
