package com.test.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.*;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.time.Duration;
import java.util.List;
import java.util.Set;

/**
 * Selenium 工具类
 */
@Slf4j
public class SeleniumUtils {

    private WebDriver driver;
    private WebDriverWait wait;
    private Actions actions;

    // 构造函数
    public SeleniumUtils(WebDriver driver) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        this.actions = new Actions(driver);
    }
    // 设置显式等待超时时间
    public void setWaitTimeout(long seconds) {
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(seconds));
    }

    // 打开URL
    public void openUrl(String url) {
        driver.get(url);
    }

    // 获取当前URL
    public String getCurrentUrl() {
        return driver.getCurrentUrl();
    }

    // 获取页面标题
    public String getPageTitle() {
        return driver.getTitle();
    }

    // 通过ID查找元素
    public WebElement findElementById(String id) {
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.id(id)));
    }

    // 通过name查找元素
    public WebElement findElementByName(String name) {
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.name(name)));
    }

    // 通过className查找元素
    public WebElement findElementByClassName(String className) {
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.className(className)));
    }

    // 通过xpath查找元素
    public WebElement findElementByXpath(String xpath) {
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
    }

    // 通过cssSelector查找元素
    public WebElement findElementByCssSelector(String cssSelector) {
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(cssSelector)));
    }

    // 通过linkText查找元素
    public WebElement findElementByLinkText(String linkText) {
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.linkText(linkText)));
    }

    // 通过partialLinkText查找元素
    public WebElement findElementByPartialLinkText(String partialLinkText) {
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.partialLinkText(partialLinkText)));
    }

    // 通过tagName查找元素
    public WebElement findElementByTagName(String tagName) {
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.tagName(tagName)));
    }

    // 查找多个元素
    public List<WebElement> findElements(By by) {
        return wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(by));
    }

    // 输入文本
    public void sendKeys(WebElement element, String text) {
        wait.until(ExpectedConditions.visibilityOf(element)).clear();
        element.sendKeys(text);
    }

    // 点击元素
    public void click(WebElement element) {
        wait.until(ExpectedConditions.elementToBeClickable(element)).click();
    }

    // 获取元素文本
    public String getText(WebElement element) {
        return wait.until(ExpectedConditions.visibilityOf(element)).getText();
    }

    // 获取元素属性值
    public String getAttribute(WebElement element, String attribute) {
        return wait.until(ExpectedConditions.visibilityOf(element)).getAttribute(attribute);
    }

    // 判断元素是否显示
    public boolean isDisplayed(WebElement element) {
        try {
            return element.isDisplayed();
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    // 判断元素是否启用
    public boolean isEnabled(WebElement element) {
        try {
            return element.isEnabled();
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    // 判断元素是否被选中
    public boolean isSelected(WebElement element) {
        try {
            return element.isSelected();
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    // 选择下拉框选项(通过value)
    public void selectByValue(WebElement element, String value) {
        new Select(wait.until(ExpectedConditions.visibilityOf(element))).selectByValue(value);
    }

    // 选择下拉框选项(通过visible text)
    public void selectByVisibleText(WebElement element, String text) {
        new Select(wait.until(ExpectedConditions.visibilityOf(element))).selectByVisibleText(text);
    }

    // 选择下拉框选项(通过index)
    public void selectByIndex(WebElement element, int index) {
        new Select(wait.until(ExpectedConditions.visibilityOf(element))).selectByIndex(index);
    }

    // 获取下拉框所有选项
    public List<WebElement> getSelectOptions(WebElement element) {
        return new Select(element).getOptions();
    }

    // 获取选中的下拉框选项
    public WebElement getFirstSelectedOption(WebElement element) {
        return new Select(element).getFirstSelectedOption();
    }

    // 鼠标悬停
    public void mouseHover(WebElement element) {
        actions.moveToElement(wait.until(ExpectedConditions.visibilityOf(element))).perform();
    }

    // 鼠标双击
    public void doubleClick(WebElement element) {
        actions.doubleClick(wait.until(ExpectedConditions.visibilityOf(element))).perform();
    }

    // 鼠标右键点击
    public void contextClick(WebElement element) {
        actions.contextClick(wait.until(ExpectedConditions.visibilityOf(element))).perform();
    }

    // 拖拽元素
    public void dragAndDrop(WebElement source, WebElement target) {
        actions.dragAndDrop(
                wait.until(ExpectedConditions.visibilityOf(source)),
                wait.until(ExpectedConditions.visibilityOf(target))
        ).perform();
    }

    // 执行JavaScript
    public Object executeScript(String script, Object... args) {
        JavascriptExecutor js = (JavascriptExecutor) driver;
        return js.executeScript(script, args);
    }

    // 滚动到元素可见
    public void scrollToElement(WebElement element) {
        executeScript("arguments[0].scrollIntoView(true);", element);
    }

    // 滚动到页面底部
    public void scrollToBottom() {
        executeScript("window.scrollTo(0, document.body.scrollHeight)");
    }

    // 滚动到页面顶部
    public void scrollToTop() {
        executeScript("window.scrollTo(0, 0)");
    }

    // 切换到frame
    public void switchToFrame(WebElement frameElement) {
        driver.switchTo().frame(frameElement);
    }

    // 切换到主窗口
    public void switchToDefaultContent() {
        driver.switchTo().defaultContent();
    }

    // 切换到父frame
    public void switchToParentFrame() {
        driver.switchTo().parentFrame();
    }

    // 切换到alert
    public Alert switchToAlert() {
        return wait.until(ExpectedConditions.alertIsPresent());
    }

    // 接受alert
    public void acceptAlert() {
        switchToAlert().accept();
    }

    // 取消alert
    public void dismissAlert() {
        switchToAlert().dismiss();
    }

    // 获取alert文本
//    public String getAlertText() {
//        return switchToAlert().getText();
//    }

    // 在alert中输入文本
    public void sendKeysToAlert(String text) {
        switchToAlert().sendKeys(text);
    }

    // 切换到窗口
    public void switchToWindow(String windowHandle) {
        driver.switchTo().window(windowHandle);
    }

    // 获取当前窗口句柄
    public String getCurrentWindowHandle() {
        return driver.getWindowHandle();
    }

    // 获取所有窗口句柄
    public Set<String> getAllWindowHandles() {
        return driver.getWindowHandles();
    }

    // 关闭当前窗口
    public void closeCurrentWindow() {
        driver.close();
    }

    // 刷新页面
    public void refreshPage() {
        driver.navigate().refresh();
    }

    // 前进
    public void navigateForward() {
        driver.navigate().forward();
    }

    // 后退
    public void navigateBack() {
        driver.navigate().back();
    }

    // 获取页面源码
    public String getPageSource() {
        return driver.getPageSource();
    }

    // 设置窗口大小
    public void setWindowSize(int width, int height) {
        driver.manage().window().setSize(new Dimension(width, height));
    }

    // 最大化窗口
    public void maximizeWindow() {
        driver.manage().window().maximize();
    }

    // 全屏窗口
    public void fullscreenWindow() {
        driver.manage().window().fullscreen();
    }

    // 获取cookie
    public Set<Cookie> getCookies() {
        return driver.manage().getCookies();
    }

    // 获取指定cookie
    public Cookie getCookieNamed(String name) {
        return driver.manage().getCookieNamed(name);
    }

    // 添加cookie
    public void addCookie(Cookie cookie) {
        driver.manage().addCookie(cookie);
    }

    // 删除cookie
    public void deleteCookie(Cookie cookie) {
        driver.manage().deleteCookie(cookie);
    }

    // 删除指定cookie
    public void deleteCookieNamed(String name) {
        driver.manage().deleteCookieNamed(name);
    }

    // 删除所有cookie
    public void deleteAllCookies() {
        driver.manage().deleteAllCookies();
    }

    // 等待元素可见
    public void waitForElementVisible(By by, long timeoutInSeconds) {
        new WebDriverWait(driver, Duration.ofSeconds(timeoutInSeconds))
                .until(ExpectedConditions.visibilityOfElementLocated(by));
    }

    // 等待元素可点击
    public void waitForElementClickable(By by, long timeoutInSeconds) {
        new WebDriverWait(driver, Duration.ofSeconds(timeoutInSeconds))
                .until(ExpectedConditions.elementToBeClickable(by));
    }

    // 等待元素消失
    public void waitForElementInvisible(By by, long timeoutInSeconds) {
        new WebDriverWait(driver, Duration.ofSeconds(timeoutInSeconds))
                .until(ExpectedConditions.invisibilityOfElementLocated(by));
    }

    // 等待文本出现在元素中
    public void waitForTextPresentInElement(By by, String text, long timeoutInSeconds) {
        new WebDriverWait(driver, Duration.ofSeconds(timeoutInSeconds))
                .until(ExpectedConditions.textToBePresentInElementLocated(by, text));
    }

    // 截屏并保存为Base64
    public String takeScreenshotAsBase64() {
        return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);
    }

    // 截屏并保存为字节数组
    public byte[] takeScreenshotAsBytes() {
        return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
    }

    // 截屏并保存为文件
    public String takeScreenshotAsFile(String filePath) {
        return ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE).getAbsolutePath();
    }

    // 关闭浏览器
    public void quit() {
        if (driver != null) {
            driver.quit();
        }
    }



    //Add SeleniumUtils -----


    /**
     * 根据句柄ID切换到指定窗口
     * @param handleId 窗口句柄ID
     */
    public void switchToWindowByHandle(String handleId) {
        driver.switchTo().window(handleId);
        log.info("已切换到句柄ID为 {} 的窗口", handleId);
    }

    /**
     * 根据网页索引号切换到指定窗口
     * @param index 窗口索引（从0开始）
     */
    public void switchToWindowByIndex(int index) {
        Set<String> handles = driver.getWindowHandles();
        if (index >= 0 && index < handles.size()) {
            String handle = handles.toArray(new String[0])[index];
            driver.switchTo().window(handle);
            log.info("已切换到索引为 {} 的窗口", index);
        } else {
            throw new NoSuchWindowException("无效的窗口索引: " + index);
        }
    }

    /**
     * 切换到初始窗口（第一个打开的窗口）
     */
    public void switchToDefaultWindow() {
        Set<String> handles = driver.getWindowHandles();
        if (!handles.isEmpty()) {
            String firstHandle = handles.iterator().next();
            driver.switchTo().window(firstHandle);
            log.info("已切换回初始窗口");
        }
    }


    /**
     * 根据索引切换到指定frame
     * @param index frame索引(从0开始)
     */
    public void switchToFrameByIndex(int index) {
        try {
            driver.switchTo().frame(index);
            log.info("已切换到索引为 {} 的frame", index);
        } catch (NoSuchFrameException e) {
            log.error("按索引切换frame失败: {}", e.getMessage());
            throw new RuntimeException("找不到索引为 " + index + " 的frame", e);
        }
    }

    /**
     * 根据定位方式切换到frame
     * @param locatorType 定位类型(id/name/xpath/css等)
     * @param locatorValue 定位值
     */
    public void switchToFrameByLocator(String locatorType, String locatorValue) {
        By locator = getLocator(locatorType, locatorValue);
        try {
            WebElement frameElement = wait.until(ExpectedConditions.presenceOfElementLocated(locator));
            driver.switchTo().frame(frameElement);
            log.info("已切换到 {} = '{}' 的frame", locatorType, locatorValue);
        } catch (TimeoutException e) {
            log.error("等待frame元素超时: {} = '{}'", locatorType, locatorValue);
            throw new RuntimeException("找不到 " + locatorType + " = '" + locatorValue + "' 的frame元素", e);
        }
    }


    /**
     * 根据定位类型和值获取Selenium定位器
     * @param locatorType 定位类型(不区分大小写):
     *        id/name/className/tagName/linkText/partialLinkText/css/xpath/label/value/index
     * @param locatorValue 定位值
     * @return By 定位器对象
     * @throws IllegalArgumentException 如果定位类型不支持
     */
    public By getLocator(String locatorType, String locatorValue) {
        if (locatorValue == null || locatorValue.trim().isEmpty()) {
            throw new IllegalArgumentException("定位值不能为空");
        }

        switch (locatorType.toLowerCase()) {
            case "id":
                return By.id(locatorValue);
            case "name":
                return By.name(locatorValue);
            case "classname":
            case "class":
                return By.className(locatorValue);
            case "tagname":
            case "tag":
                return By.tagName(locatorValue);
            case "linktext":
            case "link":
                return By.linkText(locatorValue);
            case "partiallinktext":
            case "partiallink":
                return By.partialLinkText(locatorValue);
            case "css":
            case "cssselector":
                return By.cssSelector(locatorValue);
            case "xpath":
                return By.xpath(locatorValue);
            case "label":
                // 通过label文本定位对应的元素
                return By.xpath(String.format("//label[contains(text(), '%s')]", locatorValue));
            case "value":
                // 通过value属性定位
                return By.xpath(String.format("//*[@value='%s']", locatorValue));
            case "index":
                // 索引定位需要特殊处理，通常结合其他定位方式使用
                try {
                    int index = Integer.parseInt(locatorValue);
                    return By.xpath(String.format("(//*)[%d]", index + 1)); // XPath索引从1开始
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("索引必须是数字: " + locatorValue);
                }
            default:
                throw new IllegalArgumentException("不支持的定位类型: " + locatorType +
                        "。支持的定位类型: id,name,className,tagName,linkText," +
                        "partialLinkText,css,xpath,label,value,index");
        }
    }


    /**
     * 处理弹窗
     * @param operationType 操作类型 (1=确定, 2=取消)
     * @param inputText 需要输入的文本 (可为null表示不输入)
     */
    public void handleAlert(int operationType, String inputText) {
        try {
            Alert alert = wait.until(ExpectedConditions.alertIsPresent());

            // 如果有输入文本
            if (inputText != null && !inputText.isEmpty()) {
                alert.sendKeys(inputText);
                log.info("已在弹窗中输入文本: {}", inputText);
            }

            // 执行确认或取消操作
            if (operationType == 1) {
                alert.accept();
                log.info("已确认弹窗");
            } else if (operationType == 2) {
                alert.dismiss();
                log.info("已取消弹窗");
            } else {
                throw new IllegalArgumentException("无效的弹窗操作类型: " + operationType);
            }

        } catch (NoAlertPresentException e) {
            log.error("没有找到弹窗", e);
            throw new RuntimeException("当前没有可操作的弹窗", e);
        } catch (TimeoutException e) {
            log.error("等待弹窗超时", e);
            throw new RuntimeException("等待弹窗出现超时", e);
        }
    }

    /**
     * 获取弹窗文本
     * @return 弹窗显示的文本内容
     */
    public String getAlertText() {
        try {
            Alert alert = wait.until(ExpectedConditions.alertIsPresent());
            String text = alert.getText();
            log.info("获取到弹窗文本: {}", text);
            return text;
        } catch (Exception e) {
            log.error("获取弹窗文本失败", e);
            throw new RuntimeException("无法获取弹窗文本", e);
        }
    }

    /**
     * 根据定位方式和定位值查找元素
     * @param locType 定位方式 (如 "id", "xpath", "cssSelector" 等)
     * @param locValue 定位值
     * @return 找到的WebElement
     */
    public WebElement findElement(String locType, String locValue) {
        try {
            By by = getLocator(locType, locValue);
            WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(by));
            return element;
        } catch (Exception e) {
            throw new RuntimeException("无法定位元素，定位方式：" + locType + "，定位值：" + locValue, e);
        }
    }


    /**
     * 操作下拉框
     * @param element 下拉框元素
     * @param optionType 选项类型 (1=选项文本, 2=索引, 3=值)
     * @param optionValue 选项值
     */
    public void selectDropdownOption(WebElement element, String optionType, String optionValue) {
        Select select = new Select(element);
        try {
            switch (optionType) {
                case "1": // 选项文本
                    select.selectByVisibleText(optionValue);
                    log.info("通过选项文本选择下拉框选项: {}", optionValue);
                    break;
                case "2": // 索引
                    int index = Integer.parseInt(optionValue);
                    select.selectByIndex(index);
                    log.info("通过索引选择下拉框选项: {}", index);
                    break;
                case "3": // 值
                    select.selectByValue(optionValue);
                    log.info("通过值选择下拉框选项: {}", optionValue);
                    break;
                default:
                    throw new IllegalArgumentException("不支持的选项类型: " + optionType);
            }
        } catch (Exception e) {
            log.error("操作下拉框失败", e);
            throw new RuntimeException("操作下拉框失败", e);
        }
    }

    /**
     * 等待元素满足指定条件
     * @param locator 元素定位器
     * @param operate 操作类型：
     *        1=等待元素文本等于给定值
     *        2=等待元素存在
     *        3=等待元素显示
     *        4=等待元素不显示
     *        5=等待元素不存在
     *        6=等待元素可编辑
     *        7=等待元素不可编辑
     * @param awaitValue 等待的值（用于文本比较或自定义超时时间）
     * @param timeoutInMillis 默认超时时间（毫秒）
     */
    public void waitForElement(By locator, int operate, String awaitValue, long timeoutInMillis) {
        WebDriverWait customWait = new WebDriverWait(driver, Duration.ofMillis(timeoutInMillis));

        try {
            switch (operate) {
                case 1: // 等待元素文本等于给定值
                    customWait.until(ExpectedConditions.textToBe(locator, awaitValue));
                    log.info("元素文本已等于: {}", awaitValue);
                    break;
                case 2: // 等待元素存在
                    customWait.until(ExpectedConditions.presenceOfElementLocated(locator));
                    log.info("元素已存在");
                    break;
                case 3: // 等待元素显示
                    customWait.until(ExpectedConditions.visibilityOfElementLocated(locator));
                    log.info("元素已显示");
                    break;
                case 4: // 等待元素不显示
                    customWait.until(ExpectedConditions.invisibilityOfElementLocated(locator));
                    log.info("元素已不显示");
                    break;
                case 5: // 等待元素不存在
                    boolean isAbsent = customWait.until(ExpectedConditions.not(
                            ExpectedConditions.presenceOfElementLocated(locator)
                    ));
                    log.info("元素已不存在");
                    break;
                case 6: // 等待元素可编辑
                    customWait.until(driver -> {
                        WebElement element = driver.findElement(locator);
                        return element.isEnabled() && !element.getAttribute("readonly").equals("true");
                    });
                    log.info("元素已可编辑");
                    break;
                case 7: // 等待元素不可编辑
                    customWait.until(driver -> {
                        WebElement element = driver.findElement(locator);
                        return !element.isEnabled() || element.getAttribute("readonly").equals("true");
                    });
                    log.info("元素已不可编辑");
                    break;
                default:
                    throw new IllegalArgumentException("不支持的等待操作类型: " + operate);
            }
        } catch (TimeoutException e) {
            log.error("等待元素超时，操作类型: {}, 定位器: {}", operate, locator);
            throw new RuntimeException("等待元素条件未满足: " + getOperationDescription(operate), e);
        }
    }

    // 获取操作类型描述
    private String getOperationDescription(int operate) {
        switch (operate) {
            case 1: return "文本等于给定值";
            case 2: return "元素存在";
            case 3: return "元素显示";
            case 4: return "元素不显示";
            case 5: return "元素不存在";
            case 6: return "元素可编辑";
            case 7: return "元素不可编辑";
            default: return "未知操作";
        }
    }

    /**
     * 执行鼠标操作
     * @param locator 元素定位器
     * @param clickMethod 点击方式：
     *        1=单击(左键)
     *        2=单击(右键)
     *        3=双击
     *        4=按下
     *        5=弹起
     */
    public void performMouseAction(By locator, int clickMethod) {
        try {
            WebElement element = wait.until(ExpectedConditions.elementToBeClickable(locator));

            switch (clickMethod) {
                case 1: // 左键单击
                    actions.click(element).perform();
                    log.info("已执行左键单击操作");
                    break;
                case 2: // 右键单击
                    actions.contextClick(element).perform();
                    log.info("已执行右键单击操作");
                    break;
                case 3: // 双击
                    actions.doubleClick(element).perform();
                    log.info("已执行双击操作");
                    break;
                case 4: // 按下
                    actions.clickAndHold(element).perform();
                    log.info("已执行鼠标按下操作");
                    break;
                case 5: // 弹起
                    actions.release(element).perform();
                    log.info("已执行鼠标弹起操作");
                    break;
                default:
                    throw new IllegalArgumentException("不支持的鼠标操作类型: " + clickMethod);
            }
        } catch (TimeoutException e) {
            log.error("等待元素可点击超时，定位器: {}", locator);
            throw new RuntimeException("元素不可点击或未找到: " + locator, e);
        } catch (Exception e) {
            log.error("鼠标操作执行失败", e);
            throw new RuntimeException("鼠标操作失败: " + e.getMessage(), e);
        }
    }

    /**
     * 执行鼠标移动操作
     * @param locator 元素定位器
     * @param moveType 移动类型：
     *        1=鼠标移出元素
     *        2=鼠标移入元素
     */
    public void performMouseMove(By locator, int moveType) {
        try {
            WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));

            switch (moveType) {
                case 1: // 鼠标移出元素
                    // 先移动到元素上，再移动到页面左上角
                    actions.moveToElement(element)
                            .moveByOffset(-element.getSize().getWidth(), -element.getSize().getHeight())
                            .perform();
                    log.info("已将鼠标从元素移出");
                    break;
                case 2: // 鼠标移入元素（悬停）
                    actions.moveToElement(element).perform();
                    log.info("已将鼠标悬停在元素上");
                    break;
                default:
                    throw new IllegalArgumentException("不支持的鼠标移动类型: " + moveType);
            }
        } catch (TimeoutException e) {
            log.error("等待元素可见超时，定位器: {}", locator);
            throw new RuntimeException("元素不可见或未找到: " + locator, e);
        } catch (Exception e) {
            log.error("鼠标移动操作执行失败", e);
            throw new RuntimeException("鼠标移动操作失败: " + e.getMessage(), e);
        }
    }
    /**
     * 在指定元素中输入文本
     * @param locator 元素定位器
     * @param text 要输入的文本
     * @param clearFirst 是否先清空原有内容
     * @param inputMethod 输入方式：
     *        1=普通输入（sendKeys）
     *        2=通过JavaScript设置值
     *        3=模拟人工输入（带延迟）
     */
    public void inputText(By locator, String text, boolean clearFirst, int inputMethod) {
        try {
            WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));

            // 先清空内容（如果需要）
            if (clearFirst) {
                element.clear();
                log.info("已清空输入框内容");
            }

            switch (inputMethod) {
                case 1: // 普通输入
                    element.sendKeys(text);
                    log.info("已通过sendKeys输入文本: {}", text);
                    break;
                case 2: // JavaScript输入
                    JavascriptExecutor js = (JavascriptExecutor) driver;
                    js.executeScript("arguments[0].value = arguments[1]", element, text);
                    log.info("已通过JavaScript设置文本: {}", text);
                    break;
                case 3: // 模拟人工输入
                    for (char c : text.toCharArray()) {
                        element.sendKeys(String.valueOf(c));
                        Thread.sleep(50); // 每个字符间隔50ms
                    }
                    log.info("已模拟人工输入文本: {}", text);
                    break;
                default:
                    throw new IllegalArgumentException("不支持的输入方式: " + inputMethod);
            }
        } catch (TimeoutException e) {
            log.error("等待输入元素可见超时，定位器: {}", locator);
            throw new RuntimeException("输入元素不可见或未找到: " + locator, e);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("模拟人工输入被中断");
            throw new RuntimeException("输入操作被中断", e);
        } catch (Exception e) {
            log.error("输入操作执行失败", e);
            throw new RuntimeException("输入操作失败: " + e.getMessage(), e);
        }
    }

    /**
     * 在可编辑段落中输入文本（如富文本编辑器）
     * @param locator 元素定位器
     * @param text 要输入的文本
     */
    public void inputToEditableDiv(By locator, String text) {
        try {
            WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
            element.click(); // 先点击激活
            element.sendKeys(text);
            log.info("已在可编辑段落中输入文本: {}", text);
        } catch (Exception e) {
            log.error("可编辑段落输入失败", e);
            throw new RuntimeException("可编辑段落输入失败: " + e.getMessage(), e);
        }
    }

    /**
     * 清空输入框内容
     * @param locator 元素定位器
     */
    public void clearInput(By locator) {
        try {
            WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
            element.clear();
            log.info("已清空输入框内容");
        } catch (Exception e) {
            log.error("清空输入框失败", e);
            throw new RuntimeException("清空输入框失败: " + e.getMessage(), e);
        }
    }

}
