#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
基于 API 的版本 - 直接调用 CRM SOAP API 禁用用户
不需要点击按钮，更可靠、更快速
"""

import os
import sys

# 强制立即输出
sys.stdout.reconfigure(line_buffering=True)
sys.stderr.reconfigure(line_buffering=True)

print("="*60)
print("  MDP Termination - API 版本")
print("="*60)
print()

# 导入
print(">>> 导入模块...")
from playwright.sync_api import sync_playwright
import json
import subprocess
import time
from openpyxl import load_workbook
from datetime import datetime
import csv
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

print("[OK] 所有模块已导入")
print()

# 加载配置
print(">>> 加载配置...")
config_file = "config.json"
with open(config_file, "r", encoding="utf-8") as f:
    config = json.load(f)

# 兼容不同的配置文件格式
crm_url = (
    config.get('crm', {}).get('url') or
    config.get('crm_url')
)

username = sys.argv[2] if len(sys.argv) > 2 else None
if not username:
    username = (
        config.get('crm', {}).get('username') or
        config.get('crm_username')
    )

if not username:
    print("请提供 CRM 用户名")
    print("用法: python mdp_termination_api.py <Excel文件> <CRM_Username>")
    sys.exit(1)

# 获取 Excel 文件
excel_file = sys.argv[1] if len(sys.argv) > 1 else None
if not excel_file:
    print("请提供 Excel 文件")
    print("用法: python mdp_termination_api.py <Excel文件> <CRM_Username>")
    sys.exit(1)

if not os.path.exists(excel_file):
    print(f"[ERROR] Excel 文件不存在: {excel_file}")
    sys.exit(1)

print(f"[OK] 配置已加载")
print(f"  CRM URL: {crm_url}")
print(f"  用户名: {username}")
print(f"  Excel 文件: {excel_file}")
print()

# 读取 Excel 文件
print(f">>> 读取 Excel 文件: {excel_file}")
try:
    wb = load_workbook(excel_file, read_only=True)
    ws = wb.active

    employee_data = []

    # 从第2行开始读取（第1行是标题）
    for row in ws.iter_rows(min_row=2, values_only=True):
        if len(row) >= 2 and row[1]:  # EmployeeID 在第2列
            emp_id = str(row[1]).strip()
            domain = str(row[0]).strip() if row[0] else ""
            sam_account = str(row[2]).strip() if len(row) > 2 and row[2] else ""

            if emp_id:
                employee_data.append({
                    'employee_id': emp_id,
                    'domain': domain,
                    'sam_account': sam_account
                })

    wb.close()

    employee_ids = [data['employee_id'] for data in employee_data]

    print(f"[OK] 找到 {len(employee_ids)} 个 EmployeeId")
    if len(employee_ids) <= 10:
        print(f"  列表: {', '.join(employee_ids)}")
    else:
        print(f"  前10个: {', '.join(employee_ids[:10])}...")

except Exception as e:
    print(f"[ERROR] 读取 Excel 失败: {e}")
    import traceback
    traceback.print_exc()
    sys.exit(1)

print()

# 全局变量
browser = None
context = None
page = None
req_client_id = None
org_id = None

def create_session():
    """创建带有重试机制的 requests session"""
    session = requests.Session()

    # 设置重试策略
    retry_strategy = Retry(
        total=3,
        backoff_factor=1,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["HEAD", "GET", "OPTIONS", "POST"]
    )

    adapter = HTTPAdapter(max_retries=retry_strategy)
    session.mount("http://", adapter)
    session.mount("https://", adapter)

    return session

def disable_user_via_api(systemuserid):
    """通过 CRM SOAP API 禁用用户（使用 Playwright）"""
    global page

    try:
        print(f"    调用 CRM API 禁用用户...")
        print(f"    SystemUserId: {systemuserid}")

        # 构造 SOAP 请求
        soap_url = f"{crm_url.rstrip('/')}/MDP/XRMServices/2011/Organization.svc/web"

        soap_headers = {
            "Accept": "application/xml, text/xml, */*; q=0.01",
            "Accept-Encoding": "gzip, deflate, br",
            "ClientAppName": "WebClient",
            "ClientAppVersion": "9.0",
            "Content-Type": "text/xml; charset=UTF-8",
            "SOAPAction": "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute",
            "X-Requested-With": "XMLHttpRequest",
        }

        # SOAP Body - SetStateRequest
        soap_body = f'''<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <SdkClientVersion xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">9.0</SdkClientVersion>
  </s:Header>
  <s:Body>
    <Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">
      <request i:type="b:SetStateRequest" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:b="http://schemas.microsoft.com/crm/2011/Contracts">
        <a:Parameters xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
          <a:KeyValuePairOfstringanyType>
            <b:key>EntityMoniker</b:key>
            <b:value i:type="a:EntityReference">
              <a:Id>{systemuserid}</a:Id>
              <a:LogicalName>systemuser</a:LogicalName>
            </b:value>
          </a:KeyValuePairOfstringanyType>
          <a:KeyValuePairOfstringanyType>
            <b:key>State</b:key>
            <b:value i:type="a:OptionSetValue">
              <a:Value>1</a:Value>
            </b:value>
          </a:KeyValuePairOfstringanyType>
          <a:KeyValuePairOfstringanyType>
            <b:key>Status</b:key>
            <b:value i:type="a:OptionSetValue">
              <a:Value>-1</a:Value>
            </b:value>
          </a:KeyValuePairOfstringanyType>
        </a:Parameters>
        <a:RequestId i:nil="true" />
        <a:RequestName>SetState</a:RequestName>
      </request>
    </Execute>
  </s:Body>
</s:Envelope>'''

        print(f"    发送 SOAP 请求...")

        # 使用 Playwright 的 page.request() API（会使用浏览器的 session 和 cookies）
        response = page.request(
            method="POST",
            url=soap_url,
            headers=soap_headers,
            data=soap_body.encode('utf-8'),
            timeout=30000  # 30 秒超时
        )

        print(f"    响应状态码: {response.status}")

        if response.status == 200:
            print(f"    [OK] API 调用成功")

            # 检查响应内容
            response_text = response.body().decode('utf-8')
            if 'ErrorResponse' in response_text:
                print(f"    [ERROR] API 返回错误")
                print(f"    响应: {response_text[:500]}")
                return False, "API 返回错误"

            return True, "用户已禁用"
        else:
            print(f"    [ERROR] HTTP 错误: {response.status}")
            print(f"    响应: {response.body()[:500].decode('utf-8')}")
            return False, f"HTTP 错误: {response.status}"

    except Exception as e:
        import traceback
        print(f"    [ERROR] API 调用失败: {e}")
        traceback.print_exc()
        return False, f"API 调用失败: {str(e)}"

def init_browser():
    """初始化浏览器并获取 cookies"""
    global browser, context, page, req_client_id, org_id

    print(">>> 初始化浏览器...")
    print()
    print("  [重要] 请确保浏览器已经登录 CRM！")
    print()

    with sync_playwright() as p:
        print("  [1/2] 启动浏览器...")
        browser = p.chromium.launch(
            headless=False,
            channel="msedge",
            slow_mo=100,
            args=[
                '--incognito',
                '--disable-blink-features=AutomationControlled',
            ]
        )

        print("  [OK] 浏览器已启动")

        context = browser.new_context(
            ignore_https_errors=True,
            accept_downloads=False,
            storage_state=None,
        )

        page = context.new_page()

        print("  [2/2] 访问 CRM...")

        login_url = f"{crm_url.rstrip('/')}/MDP/"
        page.goto(login_url, wait_until="domcontentloaded", timeout=30000)
        time.sleep(3)

        current_url = page.url
        print(f"  当前 URL: {current_url}")

        # 检查是否需要登录
        if 'errorhandler.aspx' in current_url:
            print()
            print("  [WARNING] 检测到错误页面（旧会话）")
            print("  >> 请在浏览器中手动刷新或重新登录")
            print("  >> 按 Ctrl+C 继续执行，或等待 30 秒自动继续...")
            print()

            try:
                time.sleep(30)
            except KeyboardInterrupt:
                print()
                print("  [INFO] 继续执行...")
        else:
            print("  [OK] 页面已加载")

        # 提取 cookies
        print()
        print("  提取 cookies...")
        cookies = context.cookies()

        for cookie in cookies:
            if cookie['name'] == 'ReqClientId':
                req_client_id = cookie['value']
            elif cookie['name'] == 'orgId':
                org_id = cookie['value']

        if req_client_id and org_id:
            print(f"  [OK] ReqClientId: {req_client_id[:20]}...")
            print(f"  [OK] orgId: {org_id[:20]}...")
        else:
            print("  [ERROR] 无法提取必要的 cookies")
            browser.close()
            sys.exit(1)

        print()
        print("="*60)
        print("  [OK] 浏览器已就绪，开始处理用户...")
        print("="*60)
        print()

        # 处理所有用户
        results = []

        for idx, employee_id in enumerate(employee_ids, 1):
            print(f"\n>>> [{idx}/{len(employee_ids)}] 处理 EmployeeId: {employee_id}")
            print("-"*60)

            result = process_employee(employee_id)

            # 保存结果
            results.append(result)

            # 每处理完一个用户，暂停一下
            if idx < len(employee_ids):
                print(f"\n  等待 2 秒后处理下一个...")
                time.sleep(2)

        # 生成报告
        print()
        print("="*60)
        print("  所有用户处理完成！生成报告...")
        print("="*60)
        print()

        generate_report(results)

        print()
        print("浏览器将在 30 秒后关闭...")
        time.sleep(30)

        context.close()
        browser.close()

def query_ad(employee_id):
    """查询 AD 获取 DisplayName"""
    try:
        ps_command = [
            "powershell",
            "-Command",
            f"Import-Module ActiveDirectory; Get-ADUser -Filter \"EmployeeId -eq '{employee_id}'\" -Properties DisplayName, SamAccountName | ConvertTo-Json"
        ]

        result = subprocess.run(
            ps_command,
            capture_output=True,
            text=True,
            timeout=30,
            encoding='utf-8'
        )

        if result.stderr and "Cannot find" in result.stderr:
            return None, "用户不存在"

        if not result.stdout.strip():
            return None, "用户不存在"

        user_data = json.loads(result.stdout)

        if not user_data or not isinstance(user_data, dict):
            return None, "用户不存在"

        display_name = user_data.get('DisplayName')
        sAMAccountName = user_data.get('SamAccountName')

        # 移除 -d 后缀（如果存在）
        if display_name and display_name.endswith('-d'):
            display_name_without_d = display_name[:-2].strip()
            print(f"  [INFO] AD DisplayName: {display_name}")
            print(f"  [INFO] 尝试使用不含 -d 的名称: {display_name_without_d}")
            return display_name_without_d, None

        return display_name, None

    except Exception as e:
        return None, f"AD 查询失败: {str(e)}"

def get_systemuserid_from_crm(display_name):
    """从 CRM 获取用户的 systemuserid"""
    global page, context

    try:
        print(f"  [1/2] 在 CRM 中搜索: {display_name}")

        # 构造搜索 URL
        search_url = f"{crm_url.rstrip('/')}/MDP/multientityquickfind/multientityquickfind.aspx"
        params = f"?text={display_name}&option=0&pagemode=iframe"

        full_url = search_url + params
        print(f"  URL: {full_url}")

        page.goto(full_url, wait_until="domcontentloaded", timeout=30000)

        # 等待搜索结果加载
        print(f"  等待搜索结果加载...")
        time.sleep(5)

        # 检查页面内容
        page_content = page.content()

        if display_name.lower() not in page_content.lower():
            print(f"  [ERROR] 未找到用户: {display_name}")
            return None, "用户未在搜索结果中找到"

        print(f"  [OK] 找到用户: {display_name}")

        # 设置新页面捕获
        new_page = None
        page_created = False

        def handle_new_page(new_p):
            nonlocal new_page, page_created
            new_page = new_p
            page_created = True
            print(f"  [INFO] 检测到新窗口/标签页打开")

        # 注册新页面监听器
        context.on('page', handle_new_page)

        # 点击用户卡片
        print(f"  点击用户卡片...")
        try:
            elements = page.query_selector_all('span#attribone')
            print(f"  找到 {len(elements)} 个 attribone 元素")

            clicked = False
            for elem in elements:
                text = elem.inner_text() or ""
                if display_name.lower() in text.lower():
                    print(f"  找到匹配的元素，点击...")
                    elem.click(timeout=5000)
                    clicked = True
                    break

            if not clicked:
                print(f"  [WARNING] 未找到匹配的元素")

        except Exception as e:
            print(f"  [ERROR] 点击失败: {e}")
            return None, f"点击失败: {str(e)}"

        # 等待新页面打开
        print(f"  等待新窗口/标签页打开...")

        if page_created and new_page:
            print(f"  [OK] 新窗口已打开")

            # 等待新页面加载
            time.sleep(3)

            new_url = new_page.url
            print(f"  新窗口 URL: {new_url}")

            # 从新窗口的 URL 提取 systemuserid
            # 优先从 extraqs 参数中提取（最可靠）
            import urllib.parse
            from urllib.parse import unquote
            import re

            systemuserid = None  # 先初始化变量

            parsed = urllib.parse.urlparse(new_url)
            query_params = urllib.parse.parse_qs(parsed.query)

            # 检查 extraqs 参数
            if 'extraqs' in query_params:
                print(f"  [INFO] 发现 extraqs 参数")
                extraqs = query_params['extraqs'][0]
                print(f"  extraqs: {extraqs[:100]}...")

                # 解码 extraqs
                decoded_extraqs = unquote(extraqs)
                print(f"  解码后: {decoded_extraqs[:100]}...")

                # 从解码的 extraqs 中提取 id 参数
                # 修复正则表达式
                id_patterns = [
                    r'[?&]id=([0-9a-f-]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})',  # ?id= 或 &id=
                    r'id=([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})',         # id= (不带前缀)
                ]

                for id_pattern in id_patterns:
                    match = re.search(id_pattern, decoded_extraqs, re.IGNORECASE)
                    if match:
                        systemuserid = match.group(1)
                        print(f"  [OK] 从 extraqs 提取 systemuserid: {systemuserid}")
                        break

                if systemuserid:
                    # 关闭新窗口
                    try:
                        new_page.close()
                        print(f"  [INFO] 已关闭新窗口")
                    except:
                        pass

                    return systemuserid, None

            # 备选：从 id 参数提取
            if not systemuserid and 'id=' in new_url:
                query_params = urllib.parse.parse_qs(parsed.query)
                if 'id' in query_params:
                    systemuserid = query_params['id'][0]
                    print(f"  [OK] 从 URL 提取 systemuserid: {systemuserid}")

                    # 关闭新窗口
                    try:
                        new_page.close()
                        print(f"  [INFO] 已关闭新窗口")
                    except:
                        pass

                    return systemuserid, None

            # 如果还没找到，从页面内容提取
            if not systemuserid:
                print(f"  [INFO] URL 中未找到，尝试从页面内容提取...")
                try:
                    page_content = new_page.content()
                    guids = re.findall(r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', page_content, re.IGNORECASE)

                    if guids:
                        systemuserid = guids[0]
                        print(f"  [OK] 从页面内容提取 systemuserid: {systemuserid}")
                        print(f"     找到 {len(guids)} 个 GUID")

                    # 关闭新窗口
                    try:
                        new_page.close()
                        print(f"  [INFO] 已关闭新窗口")
                    except:
                        pass

                    if systemuserid:
                        return systemuserid, None
                    else:
                        return None, "页面内容中未找到 systemuserid"

                except Exception as e:
                    print(f"  [ERROR] 从页面内容提取失败: {e}")
                    # 关闭新窗口
                    try:
                        new_page.close()
                    except:
                        pass

                    return None, f"提取失败: {str(e)}"

            # 如果 URL 中没有，尝试从新窗口页面内容提取
            print(f"  [INFO] URL 中未找到 systemuserid，尝试从页面内容提取...")
            try:
                new_page_content = new_page.content()

                import re
                guid_pattern = r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'

                # 查找所有 GUID
                guids = re.findall(guid_pattern, new_page_content, re.IGNORECASE)

                if guids:
                    # 通常第一个 GUID 就是 systemuserid
                    systemuserid = guids[0]
                    print(f"  [OK] 从新窗口页面提取 systemuserid: {systemuserid}")
                    print(f"     找到 {len(guids)} 个 GUID")

                    # 关闭新窗口
                    try:
                        new_page.close()
                        print(f"  [INFO] 已关闭新窗口")
                    except:
                        pass

                    return systemuserid, None
                else:
                    print(f"  [WARNING] 新窗口中未找到 GUID")

                    # 关闭新窗口
                    try:
                        new_page.close()
                    except:
                        pass

            except Exception as e:
                print(f"  [ERROR] 从新窗口提取失败: {e}")
                try:
                    new_page.close()
                except:
                    pass

        else:
            print(f"  [WARNING] 未检测到新窗口打开")
            print(f"  [INFO] 尝试从当前页面提取...")

            # 回退到原来的方法：从当前页面提取
            return get_systemuserid_from_current_page(display_name)

        return None, "无法获取 systemuserid"

    except Exception as e:
        import traceback
        return None, f"获取失败: {str(e)}"

def get_systemuserid_from_current_page(display_name):
    """从当前页面提取 systemuserid（备用方法）"""
    global page

    try:
        print(f"  [备用方法] 从当前页面搜索结果提取 systemuserid...")

        # 方法1: 从链接中提取
        try:
            print(f"  尝试从链接提取...")

            links = page.query_selector_all('a')
            print(f"  找到 {len(links)} 个链接")

            import re
            guid_pattern = r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'

            for link in links:
                href = link.get_attribute('href') or ""
                onclick = link.get_attribute('onclick') or ""
                link_text = link.inner_text() or ""

                # 查找 GUID
                href_guids = re.findall(guid_pattern, href, re.IGNORECASE)
                onclick_guids = re.findall(guid_pattern, onclick, re.IGNORECASE)

                if href_guids and display_name.lower() in link_text.lower():
                    systemuserid = href_guids[0]
                    print(f"  [OK] 从链接 href 找到 systemuserid: {systemuserid}")
                    return systemuserid, None

                if onclick_guids and display_name.lower() in link_text.lower():
                    systemuserid = onclick_guids[0]
                    print(f"  [OK] 从链接 onclick 找到 systemuserid: {systemuserid}")
                    return systemuserid, None

        except Exception as e:
            print(f"  从链接提取失败: {e}")

        # 方法2: 使用 JavaScript
        try:
            print(f"  尝试使用 JavaScript 提取...")

            js_code = f'''
            () => {{
                const guids = [];
                const links = document.querySelectorAll('a');
                const displayName = '{display_name}'.toLowerCase();

                links.forEach(link => {{
                    const href = link.href || '';
                    const onclick = link.getAttribute('onclick') || '';
                    const text = (link.textContent || '').toLowerCase();

                    const guidPattern = /[0-9a-f]{{8}}-[0-9a-f]{{4}}-[0-9a-f]{{4}}-[0-9a-f]{{4}}-[0-9a-f]{{12}}/gi;

                    const hrefMatches = href.match(guidPattern);
                    const onclickMatches = onclick.match(guidPattern);

                    if ((hrefMatches || onclickMatches) && text.includes(displayName)) {{
                        if (hrefMatches) guids.push(...hrefMatches);
                        if (onclickMatches) guids.push(...onclickMatches);
                    }}
                }});

                return [...new Set(guids)];
            }}
            '''

            guids = page.evaluate(js_code)

            if guids and len(guids) > 0:
                systemuserid = guids[0]
                print(f"  [OK] 通过 JavaScript 找到 systemuserid: {systemuserid}")
                return systemuserid, None

        except Exception as e:
            print(f"  JavaScript 提取失败: {e}")

        return None, "所有方法都失败"

    except Exception as e:
        return None, f"备用方法失败: {str(e)}"

def get_systemuserid_from_page_content(page, display_name):
    """从页面内容提取 systemuserid（备用方法2）"""
    try:
        print(f"  [备用方法2] 从页面内容提取 systemuserid...")

        # 等待页面完全加载
        time.sleep(3)

        page_content = page.content()

        import re
        guid_pattern = r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'

        # 查找所有 GUID
        guids = re.findall(guid_pattern, page_content, re.IGNORECASE)

        print(f"  找到 {len(guids)} 个 GUID")

        if guids:
            # 显示前几个 GUID，帮助调试
            print(f"  前 5 个 GUID:")
            for i, guid in enumerate(guids[:5]):
                print(f"    {i+1}. {guid}")

            # 通常用户详情页的第一个 GUID 就是 systemuserid
            systemuserid = guids[0]
            print(f"  [OK] 使用第一个 GUID: {systemuserid}")

            # 关闭页面
            try:
                page.close()
            except:
                pass

            return systemuserid, None
        else:
            return None, "页面内容中未找到 GUID"

    except Exception as e:
        return None, f"提取失败: {str(e)}"

def process_employee(employee_id):
    """处理单个用户"""
    result = {
        'employee_id': employee_id,
        'display_name': '',
        'systemuserid': '',
        'status': 'pending',
        'message': '',
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    }

    try:
        # 1. 查询 AD
        print(f"  步骤 1: 查询 AD")
        display_name, error = query_ad(employee_id)

        if error:
            print(f"  [ERROR] {error}")
            result['status'] = 'failed'
            result['message'] = error
            return result

        print(f"  [OK] DisplayName: {display_name}")
        result['display_name'] = display_name

        # 2. 从 CRM 获取 systemuserid
        print(f"  步骤 2: 从 CRM 获取 systemuserid")
        systemuserid, error = get_systemuserid_from_crm(display_name)

        if error:
            print(f"  [ERROR] {error}")
            result['status'] = 'failed'
            result['message'] = error
            return result

        print(f"  [OK] SystemUserId: {systemuserid}")
        result['systemuserid'] = systemuserid

        # 3. 通过 API 禁用用户
        print(f"  步骤 3: 通过 API 禁用用户")
        success, message = disable_user_via_api(systemuserid)

        if success:
            print(f"  [OK] {message}")
            result['status'] = 'success'
            result['message'] = message
        else:
            print(f"  [ERROR] {message}")
            result['status'] = 'failed'
            result['message'] = message

    except Exception as e:
        import traceback
        print(f"  [ERROR] 处理失败: {e}")
        traceback.print_exc()
        result['status'] = 'failed'
        result['message'] = f"异常: {str(e)}"

    return result

def generate_report(results):
    """生成 CSV 报告"""
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    report_file = f"Termination_Report_API_{timestamp}.csv"

    # 写入 CSV
    with open(report_file, 'w', newline='', encoding='utf-8-sig') as f:
        writer = csv.writer(f)

        # 写入标题
        writer.writerow(['EmployeeId', 'DisplayName', 'SystemUserId', 'Status', 'Message', 'Timestamp'])

        # 写入数据
        for result in results:
            writer.writerow([
                result['employee_id'],
                result['display_name'],
                result['systemuserid'],
                result['status'],
                result['message'],
                result['timestamp']
            ])

    print(f"[OK] 报告已生成: {report_file}")

    # 统计
    total = len(results)
    success = sum(1 for r in results if r['status'] == 'success')
    failed = sum(1 for r in results if r['status'] == 'failed')

    print()
    print("统计:")
    print(f"  总数: {total}")
    print(f"  成功: {success}")
    print(f"  失败: {failed}")

    # 显示失败的用户
    if failed > 0:
        print()
        print("失败的用户:")
        for r in results:
            if r['status'] == 'failed':
                print(f"  - {r['employee_id']} ({r.get('display_name', 'N/A')}): {r['message']}")

# 主程序
if __name__ == "__main__":
    try:
        init_browser()
    except KeyboardInterrupt:
        print("\n[INFO] 用户中断")
        if browser:
            try:
                browser.close()
            except:
                pass
    except Exception as e:
        print(f"\n[ERROR] 错误: {e}")
        import traceback
        traceback.print_exc()
        if browser:
            try:
                browser.close()
            except:
                pass

    print()
    print("="*60)
    print("  程序结束")
    print("="*60)
    print()
    print("按回车退出...")
    input()
