#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
完全自动化版本：从 Excel 读取 → 查询 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
from datetime import datetime
import csv

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_full_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_full_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

    # Excel 格式：
    # | Domain | EmployeeID | SamAccountName | TerminationDay | status | Backup |
    # |--------|------------|----------------|----------------|--------|--------|
    # | ...    | 172034     | ...            | ...            | ...    | ...    |

    employee_data = []  # 存储完整数据

    # 从第2行开始读取（第1行是标题）
    for row in ws.iter_rows(min_row=2, values_only=True):
        if len(row) >= 2 and row[1]:  # 确保至少有2列，且 EmployeeID 列有值
            emp_id = str(row[1]).strip()  # row[1] 是第二列（EmployeeID）
            domain = str(row[0]).strip() if row[0] else ""  # row[0] 是第一列（Domain）
            sam_account = str(row[2]).strip() if len(row) > 2 and row[2] else ""  # row[2] 是第三列（SamAccountName）

            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

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}")
        print(f"  URL 包含 'main.aspx': {'main.aspx' in current_url}")
        print(f"  URL 包含 'errorhandler.aspx': {'errorhandler.aspx' in current_url}")

        # 检测登录状态
        # 更灵活的检测：只要没有错误页面，就认为可能已登录
        if 'errorhandler.aspx' in current_url:
            print()
            print("  [WARNING] 检测到错误页面")
            print("  >> 请在浏览器中手动登录 CRM")
            print("  >> 登录成功后脚本将自动继续...")
            print()
            print("  提示：如果已经登录但仍看到此消息，请按 Ctrl+C 继续")
            print()

            # 等待登录
            try:
                for i in range(120):  # 等待最多 2 分钟
                    time.sleep(1)
                    current_url = page.url
                    # 检查 URL 是否变化（不再包含 errorhandler）
                    if 'errorhandler.aspx' not in current_url:
                        print(f"  [OK] 检测到登录成功！（{i+1}秒）")
                        print(f"  新 URL: {current_url}")
                        break
                    if i % 10 == 0 and i > 0:
                        print(f"  等待登录... {i}/120 秒")
                else:
                    print("  [ERROR] 120 秒内未检测到登录")
                    browser.close()
                    sys.exit(1)
            except KeyboardInterrupt:
                print()
                print("  [INFO] 用户选择继续")
        else:
            print("  [OK] 检测到已登录状态（或无需登录）")

        print("  [3/3] 浏览器已就绪")

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

        # 生成报告
        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 search_user_in_crm(display_name):
    """在 CRM 中搜索用户"""
    try:
        print(f"  [1/3] 在 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"  等待搜索结果加载...")

        max_retries = 5
        card_clicked = False

        for retry in range(max_retries):
            if retry > 0:
                print(f"  [重试 {retry}/{max_retries-1}] 等待页面加载...")

            # 每次重试等待时间递增
            wait_time = 3 + retry * 2  # 第一次 3 秒，然后 5, 7, 9, 11 秒
            print(f"  等待 {wait_time} 秒...")
            time.sleep(wait_time)

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

            # 检查是否有搜索结果
            page_content = page.content()

            # 检查是否找到用户
            if display_name.lower() not in page_content.lower():
                print(f"  [INFO] 未在页面中找到用户名，继续等待...")
                continue

            print(f"  [OK] 找到用户: {display_name}")

            # 尝试查找用户卡片并点击
            print(f"  尝试点击用户卡片...")

            # 方法 1: 查找 id="attribone" 的元素
            try:
                elements = page.query_selector_all('span#attribone')
                print(f"  找到 {len(elements)} 个 attribone 元素")

                for elem in elements:
                    text = elem.inner_text() or ""
                    print(f"  检查元素: '{text}'")

                    if display_name.lower() in text.lower():
                        print(f"  匹配！点击用户卡片...")
                        elem.click(timeout=5000)
                        time.sleep(2)
                        card_clicked = True
                        print(f"  [OK] 已点击用户卡片")
                        break

                if card_clicked:
                    break
            except Exception as e:
                print(f"  方法1失败: {e}")

            # 方法 2: 尝试其他选择器
            if not card_clicked:
                print(f"  尝试其他选择器...")
                try:
                    # 尝试通过文本查找
                    element = page.get_by_text(display_name, exact=False).first
                    if element:
                        print(f"  通过文本找到元素，点击...")
                        element.click(timeout=5000)
                        time.sleep(2)
                        card_clicked = True
                        print(f"  [OK] 已点击用户卡片")
                        break
                except Exception as e:
                    print(f"  方法2失败: {e}")

            if card_clicked:
                break

        if card_clicked:
            return True, "找到用户并点击"
        else:
            print(f"  [WARNING] 无法自动点击卡片")
            print(f"  [INFO] 请在浏览器中手动点击用户: {display_name}")
            print(f"  等待 10 秒供你手动操作...")
            time.sleep(10)
            return True, "找到用户（手动点击）"

    except Exception as e:
        import traceback
        return False, f"搜索失败: {str(e)}"

        # 检查是否找到用户
        if display_name.lower() in page_content.lower():
            print(f"  [OK] 找到用户: {display_name}")

            # 尝试查找用户卡片并点击
            # 用户卡片的可能选择器
            card_selectors = [
                'span#attribone',  # 用户提供的特定选择器
                f'#attribone:has-text("{display_name}")',
                f'[data-name="{display_name}"]',
                f'title="{display_name}"]',
                f'alt="{display_name}"]',
                '.ms-crm-List-DataRow',  # CRM 列表行
                '[onclick*="' + display_name + '"]',
            ]

            card_clicked = False
            for selector in card_selectors:
                try:
                    if selector == 'span#attribone':
                        # 特殊处理：查找所有 id="attribone" 的元素
                        elements = page.query_selector_all('span#attribone')
                        print(f"  找到 {len(elements)} 个 attribone 元素")

                        for elem in elements:
                            text = elem.inner_text() or ""
                            print(f"  检查元素: '{text}'")

                            if display_name.lower() in text.lower():
                                print(f"  匹配！点击用户卡片...")
                                elem.click(timeout=5000)
                                time.sleep(2)
                                card_clicked = True
                                break

                        if card_clicked:
                            break
                    else:
                        elements = page.query_selector_all(selector)
                        for elem in elements:
                            text = elem.inner_text() or elem.get_attribute('title') or elem.get_attribute('alt') or ""
                            if display_name.lower() in text.lower():
                                print(f"  点击用户卡片...")
                                elem.click(timeout=5000)
                                time.sleep(2)
                                card_clicked = True
                                break
                        if card_clicked:
                            break
                except Exception as e:
                    print(f"  选择器 '{selector}' 失败: {e}")
                    continue
                    continue

            if card_clicked:
                print(f"  [OK] 已点击用户卡片")
            else:
                print(f"  [INFO] 无法自动点击卡片，请手动选择用户")
                time.sleep(2)

            return True, "找到用户"
        else:
            return False, f"未找到用户: {display_name}"

    except Exception as e:
        import traceback
        return False, f"搜索失败: {str(e)}"

def disable_user_in_crm():
    """在 CRM 中禁用当前用户"""
    try:
        print(f"  [2/3] 执行 Disable 操作...")

        # 等待页面加载（点击用户卡片后）
        print(f"  等待用户详情页面加载...")
        print(f"  等待 5 秒...")
        time.sleep(5)  # 增加到 5 秒

        print(f"  开始查找 Disable 按钮...")

        # 重试机制：查找 Disable 按钮
        max_retries = 5
        button_clicked = False

        for retry in range(max_retries):
            if retry > 0:
                print(f"  [重试 {retry}/{max_retries-1}] 查找 Disable 按钮...")

            # 每次重试等待时间更长
            wait_time = 3 + retry * 3  # 3, 6, 9, 12, 15 秒
            print(f"  等待 {wait_time} 秒...")
            time.sleep(wait_time)

            # 方法 1: 使用完整的 command 属性（最准确）
            try:
                selector = 'span[command="systemuser|NoRelationship|Form|Mscrm.Form.systemuser.Disable"]'
                if page.is_visible(selector, timeout=2000):
                    print(f"  找到 Disable 按钮 (方法1: command属性)")
                    page.click(selector, timeout=5000)
                    time.sleep(2)
                    button_clicked = True
                    print(f"  [OK] 已点击 Disable 按钮")
                    break
            except:
                pass

            # 方法 2: 使用部分 command 属性
            if not button_clicked:
                try:
                    selector = 'span[command*="Disable"]'
                    elements = page.query_selector_all(selector)
                    print(f"  找到 {len(elements)} 个包含 'Disable' 的 command 元素")

                    for elem in elements:
                        command = elem.get_attribute('command') or ""
                        if 'systemuser' in command and 'Disable' in command:
                            print(f"  找到 Disable 按钮 (方法2: 部分command属性)")
                            elem.click(timeout=5000)
                            time.sleep(2)
                            button_clicked = True
                            print(f"  [OK] 已点击 Disable 按钮")
                            break

                    if button_clicked:
                        break
                except Exception as e:
                    print(f"  方法2失败: {e}")

            # 方法 3: 使用文本内容
            if not button_clicked:
                try:
                    element = page.get_by_text("Disable", exact=True).first
                    if element and element.is_visible():
                        print(f"  找到 Disable 按钮 (方法3: 文本内容)")
                        element.click(timeout=5000)
                        time.sleep(2)
                        button_clicked = True
                        print(f"  [OK] 已点击 Disable 按钮")
                        break
                except Exception as e:
                    print(f"  方法3失败: {e}")

            # 方法 4: 使用 aria-label
            if not button_clicked:
                try:
                    selector = '[aria-label*="Disable"]'
                    if page.is_visible(selector, timeout=2000):
                        print(f"  找到 Disable 按钮 (方法4: aria-label)")
                        page.click(selector, timeout=5000)
                        time.sleep(2)
                        button_clicked = True
                        print(f"  [OK] 已点击 Disable 按钮")
                        break
                except Exception as e:
                    print(f"  方法4失败: {e}")

            if button_clicked:
                break

        if not button_clicked:
            print(f"  [WARNING] 未找到 Disable 按钮")
            print(f"  [INFO] 请在浏览器中手动点击 Disable 按钮")
            print(f"  等待 15 秒...")
            time.sleep(15)
            return False, "未找到 Disable 按钮（需手动操作）"

        # 检查是否有确认对话框
        print(f"  [3/3] 确认 Disable 操作...")

        # 等待可能的确认对话框
        time.sleep(2)

        # 尝试查找确认按钮（重试机制）
        confirm_clicked = False

        for retry in range(3):
            if retry > 0:
                print(f"  重试查找确认对话框 {retry}/2...")
                time.sleep(2)

            # 检查是否有确认对话框
            confirm_selectors = [
                'button:has-text("OK")',
                'button:has-text("Yes")',
                'button:has-text("Confirm")',
                'input[type="button"][value="OK"]',
                'input[type="button"][value="Yes"]',
                '[role="button"][aria-label*="OK"]',
                '[role="button"][aria-label*="Yes"]',
            ]

            for selector in confirm_selectors:
                try:
                    if page.is_visible(selector, timeout=1000):
                        print(f"  找到确认按钮: {selector}")
                        page.click(selector, timeout=5000)
                        time.sleep(2)
                        confirm_clicked = True
                        print(f"  [OK] 已确认 Disable")
                        break
                except:
                    continue

            if confirm_clicked:
                break

        if not confirm_clicked:
            print(f"  [INFO] 未检测到确认对话框，可能已直接完成")

        # 等待操作完成
        time.sleep(2)

        return True, "Disable 成功"

    except Exception as e:
        import traceback
        print(f"  [ERROR] Disable 失败: {e}")
        import traceback
        traceback.print_exc()
        return False, f"Disable 失败: {str(e)}"
            'input[type="button"][value="OK"]',
            'input[type="button"][value="Yes"]',
        ]

        confirm_clicked = False
        for selector in confirm_selectors:
            try:
                if page.is_visible(selector, timeout=2000):
                    print(f"  找到确认按钮: {selector}")
                    page.click(selector, timeout=5000)
                    time.sleep(2)
                    confirm_clicked = True
                    print(f"  [OK] 已确认 Disable")
                    break
            except:
                continue

        if not confirm_clicked:
            print(f"  [INFO] 未检测到确认对话框，可能已直接完成")

        # 等待操作完成
        time.sleep(2)

        return True, "Disable 成功"

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

def process_employee(employee_id):
    """处理单个用户"""
    result = {
        'employee_id': employee_id,
        'display_name': '',
        'ad_account': '',
        '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 中搜索用户
        print(f"  步骤 2: 在 CRM 中搜索用户")
        found, message = search_user_in_crm(display_name)

        if not found:
            print(f"  [ERROR] {message}")
            result['status'] = 'failed'
            result['message'] = message
            return result

        # 3. Disable 用户
        print(f"  步骤 3: Disable 用户")
        success, message = disable_user_in_crm()

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

    except Exception as e:
        import traceback
        print(f"  [ERROR] 处理失败: {e}")
        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_{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')
    partial = sum(1 for r in results if r['status'] == 'partial')
    failed = sum(1 for r in results if r['status'] == 'failed')

    print()
    print("统计:")
    print(f"  总数: {total}")
    print(f"  成功: {success}")
    print(f"  部分: {partial}")
    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 partial > 0:
        print()
        print("部分成功的用户（需手动检查）:")
        for r in results:
            if r['status'] == 'partial':
                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()
