#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
完整自动化版本：从 Excel 读取 EmployeeId → 查询 AD → 在 CRM 中搜索并 Disable
"""

import os
import sys

# 强制立即输出
sys.stdout.reconfigure(line_buffering=True)
sys.stderr.reconfigure(line_buffering=True)

print("="*60)
print("  MDP Termination - 完整自动化")
print("="*60)
print()

# 导入
print(">>> 导入模块...")
from playwright.sync_api import sync_playwright
import json
import subprocess
import time
from openpyxl import load_workbook

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_auto.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_auto.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

    # 假设 EmployeeId 在第一列，从第2行开始（第1行是标题）
    employee_ids = []
    for row in ws.iter_rows(min_row=2, max_col=1, values_only=True):
        if row[0]:
            emp_id = str(row[0]).strip()
            if emp_id:
                employee_ids.append(emp_id)

    wb.close()

    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

# 初始化浏览器和登录
def init_browser():
    """初始化浏览器并等待登录"""
    global browser, context, page

    print(">>> 初始化浏览器...")

    with sync_playwright() as p:
        print("  [1/3] 启动浏览器...")
        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/3] 访问 CRM...")

        login_url = f"{crm_url.rstrip('/')}/MDP/"
        page.goto(login_url, wait_until="domcontentloaded", timeout=30000)
        time.sleep(2)

        current_url = page.url
        print(f"  当前 URL: {current_url}")

        # 检测登录状态
        if 'main.aspx' not in current_url or 'errorhandler.aspx' in current_url:
            print()
            print("  [WARNING] 未检测到登录状态")
            print("  >> 请在浏览器中手动登录 CRM")
            print("  >> 登录成功后脚本将自动继续...")
            print()

            # 等待登录
            for i in range(120):  # 等待最多 2 分钟
                time.sleep(1)
                if 'main.aspx' in page.url and 'errorhandler.aspx' not in page.url:
                    print(f"  [OK] 检测到登录成功！（{i+1}秒）")
                    break
                if i % 10 == 0 and i > 0:
                    print(f"  等待登录... {i}/120 秒")
            else:
                print("  [ERROR] 120 秒内未检测到登录")
                browser.close()
                sys.exit(1)
        else:
            print("  [OK] 检测到已登录状态")

        print("  [3/3] 提取 cookies...")
        time.sleep(1)

        cookies = context.cookies()

        req_client_id = None
        org_id = None

        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("  [WARNING] 未提取到必要的 cookies")

        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"  等待 2 秒后处理下一个...")
                time.sleep(2)

        # 生成报告
        print()
        print("="*60)
        print("  处理完成！生成报告...")
        print("="*60)
        print()

        generate_report(results)

        print()
        print("浏览器将在 10 秒后关闭...")
        time.sleep(10)

        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')

        return display_name, None

    except Exception as e:
        return None, f"AD 查询失败: {str(e)}"

def search_and_disable_user_in_crm(display_name, employee_id):
    """在 CRM 中搜索用户并禁用"""
    try:
        # 等待页面加载完成
        time.sleep(1)

        # 方案1: 尝试在全局搜索框中搜索
        # CRM 通常有一个全局搜索框，可以搜索任何实体
        print(f"  在 CRM 中搜索: {display_name}")

        # 尝试多种搜索框选择器
        search_selectors = [
            'input[placeholder*="Search" i]',
            'input[type="search"]',
            'input[id*="search" i]',
            '#search',
            '.search-input',
        ]

        search_found = False
        for selector in search_selectors:
            try:
                if page.is_visible(selector, timeout=2000):
                    print(f"  找到搜索框: {selector}")

                    # 清空搜索框
                    page.fill(selector, "", timeout=5000)
                    time.sleep(0.5)

                    # 输入 DisplayName
                    page.fill(selector, display_name, timeout=5000)
                    time.sleep(0.5)

                    # 按 Enter 搜索
                    page.keyboard.press("Enter")
                    time.sleep(2)

                    search_found = True
                    print(f"  [OK] 已执行搜索")
                    break
            except:
                continue

        if not search_found:
            # 方案2: 尝试导航到用户列表页面
            print(f"  [INFO] 未找到搜索框，尝试导航到用户列表...")

            # CRM 用户列表通常在特定 URL
            user_list_url = f"{crm_url.rstrip('/')}/MDP/main.aspx?etc=8&pagetype=entitylist"
            print(f"  访问: {user_list_url}")

            page.goto(user_list_url, wait_until="domcontentloaded", timeout=30000)
            time.sleep(2)

            # 尝试在列表页面的搜索框中搜索
            for selector in search_selectors:
                try:
                    if page.is_visible(selector, timeout=2000):
                        page.fill(selector, display_name, timeout=5000)
                        time.sleep(0.5)
                        page.keyboard.press("Enter")
                        time.sleep(2)
                        search_found = True
                        print(f"  [OK] 已在用户列表中搜索")
                        break
                except:
                    continue

        # 等待搜索结果加载
        time.sleep(3)

        # 检查是否找到用户
        current_url = page.url
        print(f"  当前 URL: {current_url}")

        # 尝试查找包含 DisplayName 的结果
        page_content = page.content()
        if display_name.lower() in page_content.lower():
            print(f"  [OK] 找到用户: {display_name}")

            # 这里需要根据实际的 CRM 页面结构来定位用户记录并点击 disable
            # 这通常需要：
            # 1. 找到用户记录的行
            # 2. 点击该行或勾选复选框
            # 3. 点击 "Disable" 或 "Deactivate" 按钮
            # 4. 确认操作

            print(f"  [INFO] 需要手动完成 disable 操作")
            print(f"  >> 请在浏览器中找到用户 '{display_name}'")
            print(f"  >> 点击 Disable 按钮")
            print(f"  >> 确认操作")
            print()
            print(f"  按 Ctrl+C 继续，或等待 30 秒自动继续...")

            # 等待用户手动操作
            try:
                time.sleep(30)
            except KeyboardInterrupt:
                print(f"  继续处理...")

            return True, "已找到用户（需手动 disable）"
        else:
            return False, f"在 CRM 中未找到用户: {display_name}"

    except Exception as e:
        import traceback
        return False, f"CRM 操作失败: {str(e)}"

def process_employee(employee_id):
    """处理单个用户"""
    result = {
        'employee_id': employee_id,
        'display_name': '',
        'status': 'pending',
        'message': '',
        'timestamp': time.strftime('%Y-%m-%d %H:%M:%S')
    }

    # 1. 查询 AD
    print(f"  [1/3] 查询 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 中搜索并禁用
    print(f"  [2/3] 在 CRM 中搜索并禁用...")
    success, message = search_and_disable_user_in_crm(display_name, employee_id)

    if success:
        print(f"  [OK] {message}")
        result['status'] = 'success'
        result['message'] = message
    else:
        print(f"  [ERROR] {message}")
        result['status'] = 'failed'
        result['message'] = message

    # 3. 完成
    print(f"  [3/3] 完成")
    print(f"  状态: {result['status']}")

    return result

def generate_report(results):
    """生成报告"""
    import csv
    from datetime import datetime

    # 生成报告文件名
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    report_file = f"Termination_Report_{timestamp}.csv"

    # 写入 CSV
    with open(report_file, 'w', newline='', encoding='utf-8-sig') as f:
        writer = csv.writer(f)

        # 写入标题
        writer.writerow(['EmployeeId', 'DisplayName', 'Status', 'Message', 'Timestamp'])

        # 写入数据
        for result in results:
            writer.writerow([
                result['employee_id'],
                result['display_name'],
                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['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()
