# =============================================================================
# 企微IT智能服务台 — Mock适配器（开发期使用）
# =============================================================================
# 说明：
#   1. 在 Mock 模式下（EXT_MOCK_MODE=True），所有外部系统查询
#      返回预置的 Mock 数据，不调用任何真实 API
#   2. Mock 数据覆盖 P0 场景（终端查询、安全状态、VPN在线）
#   3. 凭证未配置时自动降级到 MockAdapter，保证开发期无外部依赖
#
# 使用方式：
#   EXT_MOCK_MODE=True  → 所有系统走 Mock
#   某系统凭证未配置          → 单个系统自动降级到 Mock（在 service.py 中处理）
# =============================================================================

import logging
from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional

from app.services.external.base import (
    ExternalSystemAdapter,
    TerminalInfo,
    SecurityStatus,
    VpnSession,
)

logger = logging.getLogger(__name__)


# =============================================================================
# Mock 数据工厂
# =============================================================================

def _make_mock_terminal(username: str) -> TerminalInfo:
    """生成 Mock 终端信息

    做什么：为指定用户生成一个逼真的模拟终端数据
    为什么：开发期没有真实凭证时需要终端数据支撑会话排查流程
    """
    return TerminalInfo(
        source_system="mock",
        terminal_id=f"mock-terminal-{username}",
        computer_name=f"{username.upper()}-PC01",
        ip_addresses=[f"192.168.{hash(username) % 255}.{100 + hash(username) % 155}"],
        mac_addresses=[f"00:16:3E:{hash(username) % 256:02X}:{hash(username + 'a') % 256:02X}:{hash(username + 'b') % 256:02X}"],
        os_version="Windows 11 专业版 23H2",
        is_online=True,
        logged_in_user=username,
        logged_in_user_name=_username_to_display_name(username),
        department=_guess_department(username),
        hardware_summary={
            "cpu": "Intel Core i7-12700",
            "memory_total_gb": 16,
            "memory_used_gb": 8,
            "disk_total_gb": 512,
            "disk_free_gb": 128,
            "disk_usage_pct": 75,  # 模拟磁盘使用率较高
        },
        last_seen=datetime.now() - timedelta(minutes=5),
        raw_data=None,  # Mock 数据不保留原始响应
    )


def _make_mock_security_status(terminal_id: str) -> SecurityStatus:
    """生成 Mock 安全状态

    做什么：生成一个模拟的安全状态数据
    为什么：开发期需要验证安全状态卡片、漏洞警告等UI渲染
    """
    return SecurityStatus(
        source_system="mock",
        terminal_id=terminal_id,
        computer_name=f"MOCK-PC01",
        virus_total=2,
        virus_uncleaned=1,
        vulnerabilities=[
            {
                "name": "Microsoft Windows 安全更新 (CVE-2025-12345)",
                "level": "high",
                "description": "远程代码执行漏洞，需立即修补",
                "publish_time": (datetime.now() - timedelta(days=7)).isoformat(),
            },
            {
                "name": "火绒安全漏洞扫描：弱密码检测",
                "level": "medium",
                "description": "账户密码强度不足，建议修改",
                "publish_time": (datetime.now() - timedelta(days=3)).isoformat(),
            },
        ],
        high_vuln_count=1,
        is_isolated=False,
        isolation_source=None,
        checked_at=datetime.now(),
    )


def _make_mock_vpn_session(username: str) -> VpnSession:
    """生成 Mock VPN 会话"""
    return VpnSession(
        source_system="mock",
        session_id=f"mock-session-{username}",
        username=username,
        display_name=_username_to_display_name(username),
        remote_ip=f"1{hash(username) % 100}.{hash(username + 'r') % 256}.{hash(username + 's') % 256}.{hash(username + 't') % 256}",
        vpn_ip=f"10.200.{hash(username) % 255}.{100 + hash(username) % 155}",
        is_trusted=True,
        os="Windows 11",
        last_login=datetime.now() - timedelta(minutes=30),
        domain="servyou.local",
    )


def _username_to_display_name(username: str) -> str:
    """Mock 用户名转换（简单映射）"""
    name_map = {
        "songxian": "宋献",
        "zhangsan": "张三",
        "lisi": "李四",
        "wangwu": "王五",
    }
    return name_map.get(username, username)


def _guess_department(username: str) -> str:
    """Mock 部门推断"""
    dept_map = {
        "songxian": "IT支持组",
        "zhangsan": "财务部",
        "lisi": "人力资源部",
        "wangwu": "研发部",
    }
    return dept_map.get(username, "未知部门")


# =============================================================================
# MockAdapter 实现
# =============================================================================

class MockAdapter(ExternalSystemAdapter):
    """Mock 适配器 — 开发期替代所有外部系统

    做什么：提供逼真的模拟数据，让开发期可以不依赖任何外部系统
    为什么：阶段一MVP验证、前端开发、单元测试都需要稳定的数据来源

    降级规则：
    - 所有方法均返回 Mock 数据
    - 支持常用测试用户：songxian / zhangsan / lisi / wangwu
    - is_available 固定返回 True（Mock 永远可用）
    """

    @property
    def system_name(self) -> str:
        return "mock"

    @property
    def is_available(self) -> bool:
        """Mock 永远可用"""
        return True

    async def health_check(self) -> bool:
        """Mock 健康检查永远通过"""
        logger.debug("[MockAdapter] 健康检查 → OK（Mock模式）")
        return True

    # ── 终端查询能力 ──

    async def get_terminal_by_user(self, username: str) -> Optional[TerminalInfo]:
        """Mock：通过账号查询终端

        做什么：返回预置的 Mock 终端信息
        为什么：开发期坐席打开会话时需要看到终端画像
        """
        logger.info(f"[MockAdapter] get_terminal_by_user({username}) → Mock数据")
        return _make_mock_terminal(username)

    async def get_terminal_by_computer(self, computer_name: str) -> Optional[TerminalInfo]:
        """Mock：通过计算机名查询终端"""
        logger.info(f"[MockAdapter] get_terminal_by_computer({computer_name}) → Mock数据")
        # 从计算机名反推用户名（简单逻辑）
        username = computer_name.split("-")[0].lower() if "-" in computer_name else "songxian"
        return _make_mock_terminal(username)

    async def get_terminal_detail(self, terminal_id: str) -> Optional[TerminalInfo]:
        """Mock：查询终端详细信息"""
        logger.info(f"[MockAdapter] get_terminal_detail({terminal_id}) → Mock数据")
        return _make_mock_terminal("songxian")

    # ── 安全能力 ──

    async def get_security_status(self, terminal_id: str) -> Optional[SecurityStatus]:
        """Mock：获取安全状态"""
        logger.info(f"[MockAdapter] get_security_status({terminal_id}) → Mock数据")
        return _make_mock_security_status(terminal_id)

    async def isolate_terminal(self, terminal_id: str, reason: str) -> bool:
        """Mock：隔离终端（Mock 模式仅记录日志）"""
        logger.warning(
            f"[MockAdapter] 隔离终端（Mock，不真实执行）: "
            f"terminal={terminal_id}, reason={reason}"
        )
        return True  # Mock 永远返回成功

    async def unisolate_terminal(self, terminal_id: str) -> bool:
        """Mock：解除隔离"""
        logger.warning(
            f"[MockAdapter] 解除隔离（Mock，不真实执行）: terminal={terminal_id}"
        )
        return True

    # ── VPN/在线状态 ──

    async def get_vpn_sessions(self, username: Optional[str] = None) -> List[VpnSession]:
        """Mock：查询VPN在线会话"""
        if username:
            return [_make_mock_vpn_session(username)]
        # 返回多个 Mock 会话
        return [
            _make_mock_vpn_session("songxian"),
            _make_mock_vpn_session("zhangsan"),
        ]

    async def get_online_status(self, username: str) -> bool:
        """Mock：查询在线状态（Mock 永远返回 True）"""
        return True
