package com.test.test.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.test.common.config.TestConfig;
import com.test.common.utils.DateUtils;
import com.test.common.utils.SecurityUtils;
import com.test.common.utils.SeleniumUtils;
import com.test.common.utils.StringUtils;
import com.test.test.domain.*;
import com.test.test.domain.qo.OtherSettingsQO;
import com.test.test.domain.vo.UiHighSettingVO;
import com.test.test.mapper.UiAutomationMapper;
import com.test.test.mapper.UiSceneStepsMapper;
import com.test.test.mapper.UiSceneStepsReportMapper;
import com.test.test.service.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.C;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;


@Service
@Slf4j
public class UiSceneStepsServiceImpl implements IUiSceneStepsService {

    @Resource
    private UiSceneStepsMapper uiSceneStepsMapper;
    @Resource
    private IUiReportService uiReportService;
    @Resource
    private UiSceneStepsReportMapper uiSceneStepsReportMapper;
    @Resource
    private IUiAutomationService uiAutomationService;
    @Resource
    private IUiElementService uiElementService;
    @Resource
    private UiAutomationMapper uiAutomationMapper;




    /**
     * 执行场景步骤
     *
     * @param automationId
     * @return
     */
    public Map<String, Object> executeStep(Long automationId) {
        Map<String, Object> result = new HashMap<>();
        result.put("msg", "");
        result.put("id", 0L);
        // 1. 验证并获取步骤
        List<UiSceneSteps> steps = validateAndGetSteps(automationId);

        //修改ui_automation 状态为进行中 执行结果为running
        UiAutomation uiAutomation = new UiAutomation();
        uiAutomation.setStatus("2");
        uiAutomation.setExecutionResult("1");
        uiAutomation.setUpdateBy(DateUtils.getTime());
        uiAutomationMapper.updateUiAutomation(uiAutomation);


        Date startTime = DateUtils.getNowDate();
        // 2. 创建执行报告
        Long reportId =  uiReportService.insertUiReport(startTime, automationId, "1", steps.size());
        UiReport uiReport = new UiReport();
        result.put("id", reportId);
        uiReport.setId(reportId);
        Date endTime = null;
        Integer orderNumber = 0;
        for (UiSceneSteps step : steps) {
            orderNumber++;
            //创建报告步骤表
            createSceneStepsReport(orderNumber,step, reportId);
        }
        try {
            // 3. 执行所有步骤
            executeAllSteps(steps, reportId);
            log.info("场景执行成功: {}", automationId);
            uiReport.setConsoleStr("OK");
            uiReport.setStatus(3);
        } catch (IllegalArgumentException e) {
            result.put("msg", e.getMessage());
            log.error("场景执行失败: {}", e.getMessage());
            uiReport.setConsoleStr(e.toString());
            uiReport.setStatus(2);
            uiAutomation.setExecutionResult("2");
        } finally {
            endTime = DateUtils.getNowDate();
            uiReport.setTake(DateUtils.calculateTimeDifference(startTime, endTime));
            uiReport.setUpdateTime(endTime);
            //查询report
            UiSceneStepsReport uiStepsReport = new UiSceneStepsReport();
            uiStepsReport.setReportId(reportId);
            List<UiSceneStepsReport> uiSceneStepsReports = uiSceneStepsReportMapper.selectUiSceneStepsReportList(uiStepsReport);
            int scenesSucceedNumber = 0;
            int scenesErrorNumber = 0;
            int stepsSucceedNumber = 0;
            int stepsErrorNumber = 0;
            int stepsNotNumber = 0;
            if (uiSceneStepsReports != null && !uiSceneStepsReports.isEmpty()) {
                boolean allSuccess = true;
                for (UiSceneStepsReport report : uiSceneStepsReports) {
                    if (report.getExecutionFlag().equals("1")) {
                        stepsSucceedNumber++;
                    } else if (report.getExecutionFlag().equals("2")) {
                        stepsErrorNumber++;
                        allSuccess = false;
                    } else if (report.getExecutionFlag().equals("0")) {
                        stepsNotNumber++;
                    }
                }
                if (allSuccess) {
                    scenesSucceedNumber = 1;
                } else {
                    scenesErrorNumber = 1;
                }
            }
            uiReport.setScenesSucceedNumber(scenesSucceedNumber);
            uiReport.setScenesErrorNumber(scenesErrorNumber);
            uiReport.setScenesNotNumber(0);
            uiReport.setStepsSucceedNumber(stepsSucceedNumber);
            uiReport.setStepsErrorNumber(stepsErrorNumber);
            uiReport.setStepsNotNumber(stepsNotNumber);
            uiReport.setFaiiRate(
                    stepsErrorNumber == 0 ? "0%" :
                            String.format("%.2f%%", (double)stepsErrorNumber / steps.size() * 100)
            );
            uiReportService.updateUiReport(uiReport);

            //修改ui_automation
            uiAutomation = new UiAutomation();
            if (!uiAutomation.getExecutionResult().equals("2")){
                uiAutomation.setExecutionResult("3");
                uiAutomation.setStatus("3");
            }
            uiAutomation.setUpdateBy(DateUtils.getTime());
            uiAutomation.setPassRate(stepsSucceedNumber == 0 ? "0%" :
                    String.format("%.2f%%", (double)stepsSucceedNumber / steps.size() * 100));
            uiAutomationMapper.updateUiAutomation(uiAutomation);
        }
        return result;
    }

    /**
     * 判断步骤是否为空
     *
     * @param automationId
     * @return
     */
    private List<UiSceneSteps> validateAndGetSteps(Long automationId) {
        List<UiSceneSteps> steps = uiSceneStepsMapper.selectUiSceneStepsById(automationId);
        steps = steps.stream().filter(e->e.getIsDisabled() == 0).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(steps)) {
            throw new IllegalArgumentException("步骤不能为空");
        }
        //判断第一步是不是打开网页
        if (!"1".equals(steps.get(0).getOperateType()) || !"1".equals(steps.get(0).getStepType())) {
            throw new IllegalArgumentException("第一步必须是打开网页");
        }
        return steps;
    }

    /**
     * 创建报告步骤
     *
     * @param steps
     * @param reportId
     */
    private Long createSceneStepsReport(Integer orderNumber,UiSceneSteps steps, Long reportId) {
        UiSceneStepsReport uiSceneStepsReport = new UiSceneStepsReport();
        uiSceneStepsReport.setReportId(reportId);
        uiSceneStepsReport.setName(steps.getName());
        uiSceneStepsReport.setCreateBy(SecurityUtils.getUsername());
        uiSceneStepsReport.setExecutionFlag("0");//未执行
        uiSceneStepsReport.setOrderNumber(orderNumber);
        uiSceneStepsReportMapper.insertUiSceneStepsReport(uiSceneStepsReport);
        return uiSceneStepsReport.getId();
    }


    /**
     * 场景步骤执行
     *
     * @param steps
     */
    private void executeAllSteps(List<UiSceneSteps> steps, Long reportId) {
        System.setProperty("webdriver.chrome.driver", "D:/chromedriver-win64/chromedriver.exe");
        WebDriver driver = new ChromeDriver();
        SeleniumUtils seleniumUtils = new SeleniumUtils(driver);
        Integer orderNumber = 0;
        UiSceneStepsReport uiSceneStepsReport = new UiSceneStepsReport();
        uiSceneStepsReport.setReportId(reportId);
        for (UiSceneSteps step : steps) {
            orderNumber++;
            uiSceneStepsReport.setOrderNumber(orderNumber);
            List<UiSceneStepsReport> uiSceneStepsReports = uiSceneStepsReportMapper.selectUiSceneStepsReportList(uiSceneStepsReport);
            if (CollectionUtils.isEmpty(uiSceneStepsReports)) {
                continue;
            }
            //查看高级设置
            List<UiHighSettingVO> uiHighSettingVOList = uiAutomationService.getUiHighSettingVOList(step.getId());
            executeSingleStep(step, seleniumUtils, uiSceneStepsReports.get(0).getId(), uiHighSettingVOList);
        }
    }

    private void executeSingleStep(UiSceneSteps step, SeleniumUtils seleniumUtils,
                                   Long sceneStepsReportId, List<UiHighSettingVO> uiHighSettingVOList) {
        // 定义所有操作类型的执行方法映射
        Map<String, Map<String, StepExecution>> operationStrategies = Map.of(
                "1", Map.of( // 浏览器操作
                        "1", this::openWebPage,
                        "2", this::closeBrowser,
                        "3", this::switchWindow,
                        "4", this::resizeWindow,
                        "5", this::selectEmbeddedPage
                ),
                "2", Map.of( // 弹窗操作
                        "1", this::handlePopup
                ),
                "3", Map.of( // 元素操作
                        "1", this::submitForm,
                        "2", this::handleDropdown,
                        "3", this::setOption,
                        "4", this::waitForElement
                ),
                "4", Map.of( // 鼠标操作
                        "1", this::mouseClick,
                        "2", this::mouseMove
                ),
                "5", Map.of( // 输入操作
                        "1", this::inputText,
                        "2", this::uploadFile
                )
        );

        // 获取对应的操作类型映射
        Map<String, StepExecution> operationMap = operationStrategies.get(step.getOperateType());
        if (operationMap == null) {
            throw new IllegalArgumentException("不支持的操作类型: " + step.getOperateType());
        }

        // 获取具体的执行方法
        StepExecution execution = operationMap.get(step.getStepType());
        if (execution == null) {
            throw new IllegalArgumentException("不支持的步骤类型: " + step.getStepType() +
                    " 对于操作类型: " + step.getOperateType());
        }

        // 执行步骤并处理结果
        boolean shouldContinue = executeStepWithLog(step, seleniumUtils, sceneStepsReportId,
                execution, uiHighSettingVOList);
        if (!shouldContinue) {
            throw new IllegalArgumentException("步骤执行失败，根据设置终止场景执行");
        }
    }



    /**
     * 执行步骤并记录日志
     *
     * @param step               步骤对象
     * @param seleniumUtils      Selenium工具类
     * @param sceneStepsReportId 报告步骤ID
     * @param stepExecution      具体的步骤执行方法
     * @param uiHighSettingVOList 高级设置列表
     * @return boolean 是否继续执行后续步骤 (true=继续, false=终止)
     */
    private boolean executeStepWithLog(UiSceneSteps step, SeleniumUtils seleniumUtils,
                                       Long sceneStepsReportId, StepExecution stepExecution,
                                       List<UiHighSettingVO> uiHighSettingVOList) {
        // 1. 初始化设置对象
        UiHighSettingVO errorSetting = extractErrorSetting(uiHighSettingVOList);
        UiHighSettingVO otherSetting = extractOtherSetting(uiHighSettingVOList);
        OtherSettingsQO otherSettingsQO = otherSetting.getOtherSettingsQO();
        Integer screenshotConfiguration = otherSettingsQO.getScreenshotConfiguration(); //是否截图 1当前步骤截图 2异常截图 3 不截图
        //等待元素超时时间
        Integer waitElementTime = otherSettingsQO.getWaitElementTime()==null?0:otherSettingsQO.getWaitElementTime();
        //前置操作设置
        List<UiHighSettingVO> beforeSettingList = extractbeforeSetting(uiHighSettingVOList);
        //后置操作设置
        List<UiHighSettingVO> afterSettingList = extractafterSetting(uiHighSettingVOList);
        //前置等待时间
        int beforeAwaitTime = getAwaitTime(beforeSettingList);
        //后置等待时间
        int afterAwaitTime = getAwaitTime(afterSettingList);
        // 2. 准备报告对象
        UiSceneStepsReport report = new UiSceneStepsReport();
        report.setId(sceneStepsReportId);
        Date startTime = DateUtils.getNowDate();
        Date endTime = null;
        boolean continueExecution = true; // 默认继续执行
        try {
            // 执行前置等待
            if (beforeAwaitTime > 0) {
                log.info("执行前置等待: {}ms", beforeAwaitTime);
                Thread.sleep(beforeAwaitTime);
            }

            if (screenshotConfiguration == 1) {
                report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
                log.info("截图成功,路径:{}",seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
            }
            // 3. 执行具体步骤
            stepExecution.execute(step, seleniumUtils);

            // 执行后置等待
            if (afterAwaitTime > 0) {
                log.info("执行后置等待: {}ms", afterAwaitTime);
                Thread.sleep(afterAwaitTime);
            }

            report.setLogInfo("OK");
            report.setExecutionFlag("1");
        } catch (Exception e) {
            // 4. 错误处理
            report.setLogInfo(e.toString());
            report.setExecutionFlag("2");
            // 根据错误处理设置决定是否继续
            if ("1".equals(errorSetting.getErrorHandling())) {
                continueExecution = false; // 不继续执行后续步骤
            }
            if (screenshotConfiguration == 2) {
                report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
                log.info("截图成功,路径:{}",seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
            }
            log.error("步骤执行失败: {}", e.getMessage());
        } finally {
            endTime = DateUtils.getNowDate();
            // 更新报告
            report.setCreateTime(startTime);
            report.setUpdateTime(endTime);
            report.setTake(DateUtils.differenceInMilliseconds(startTime,endTime) + "ms");
            uiSceneStepsReportMapper.updateUiSceneStepsReport(report);
        }

        return continueExecution;
    }


    /**
     * 提取前置操作
     * @param settings
     * @return
     */
    private List<UiHighSettingVO> extractbeforeSetting(List<UiHighSettingVO> settings) {
        return settings.stream()
                .filter(e -> "1".equals(e.getSettingType()) && e.getIsDisabled() == 0)
                .collect(Collectors.toList()); // 返回默认设置
    }

    /**
     * 获取(前置//后置)等待时间
     * @param settingList
     * @return
     */
    private int getAwaitTime(List<UiHighSettingVO> settingList){
        //获取前置等待时间
        int totalWaitTime = settingList.stream()
                .map(UiHighSettingVO::getAwateTime)
                .filter(Objects::nonNull)
                .filter(s -> !s.isEmpty())
                .mapToInt(s -> {
                    try {
                        return Integer.parseInt(s);
                    } catch (NumberFormatException e) {
                        return 0;
                    }
                })
                .sum();
        return totalWaitTime;
    }


    /**
     * 提取后置操作
     * @param settings
     * @return
     */
    private List<UiHighSettingVO> extractafterSetting(List<UiHighSettingVO> settings) {
        return settings.stream()
                .filter(e -> "2".equals(e.getSettingType()) && e.getIsDisabled() == 0)
                .collect(Collectors.toList()); // 返回默认设置
    }

    /**
     * 提取错误处理设置
     * @param settings
     * @return
     */
    private UiHighSettingVO extractErrorSetting(List<UiHighSettingVO> settings) {
        return settings.stream()
                .filter(e -> "3".equals(e.getSettingType()) && e.getIsDisabled() == 0)
                .findFirst()
                .orElse(new UiHighSettingVO()); // 返回默认设置
    }




    /**
     * 提取错误处理设置
     * @param settings
     * @return
     */
    private UiHighSettingVO extractOtherSetting(List<UiHighSettingVO> settings) {
        return settings.stream()
                .filter(e -> "4".equals(e.getSettingType()) && e.getIsDisabled() == 0)
                .findFirst()
                .orElse(new UiHighSettingVO()); // 返回默认设置
    }







    //---------------------浏览器操作---------------------------

    /**
     * 打开网页
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void openWebPage(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        log.info("打开网页：{}",step.getUrl());
        seleniumUtils.openUrl(step.getUrl());
    }

    /**
     * 关闭网页
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void closeBrowser(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        log.info("关闭网页");
        seleniumUtils.quit();
    }

    /**
     * 切换窗口
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void switchWindow(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        if (step.getOperate()==1){
            log.info("根据句柄 ID 切换到指定窗口");
            //句柄id
            String handleId = step.getHandleId();
            seleniumUtils.switchToWindowByHandle(handleId);
        }else if (step.getOperate()==2){
            log.info("根据网页索引号切换到指定窗口");
            //网页索引号
            Integer frameIndex = step.getFrameIndex();
            seleniumUtils.switchToWindowByIndex(frameIndex);
        }else if (step.getOperate()==3){
            log.info("切换到初始窗口");
            seleniumUtils.switchToDefaultWindow();
        }else{
            log.info("无效的窗口切换操作类型");
            throw new IllegalArgumentException("无效的窗口切换操作类型");
        }
    }

    /**
     * 设置窗口大小
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void resizeWindow(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        if (step.getOperate()==1){
            log.info("窗口最大化");
            //窗口最大化
            seleniumUtils.maximizeWindow();
        }else if (step.getOperate()==2){
            log.info("设置窗口大小");
            String windowSize = step.getWindowSize();
            String[] dimensions = windowSize.split("\\*");
            int width = Integer.parseInt(dimensions[0]);
            int height = Integer.parseInt(dimensions[1]);
            seleniumUtils.setWindowSize(width, height);
        }else{
            log.info("无效的设置窗口大小");
            throw new IllegalArgumentException("无效的设置窗口大小");
        }
    }


    /**
     * 选择内嵌网页
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void selectEmbeddedPage(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        if (step.getOperate()==1){
            log.info("退出当前 frame(回到主页面)");
            seleniumUtils.switchToDefaultContent();
        }else if (step.getOperate()==2){
            log.info("根据 frame 索引号切换到指定 frame");
            //网页索引号
            seleniumUtils.switchToFrameByIndex(step.getFrameIndex());
        }else if (step.getOperate()==3){
            log.info("根据定位方式切换 frame");
            if ("2".equals(step.getOperateObject())) {
                //元素对象
                String operateLocType = step.getOperateLocType();   //属性
                String operateLocValue = step.getOperateLocValue(); //值
                seleniumUtils.switchToFrameByLocator(
                        operateLocType,
                        operateLocValue
                );
            }else{
                //元素定位
                UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
                if (uiElement == null) {
                    throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
                }
                String locType = uiElement.getLocType();    //属性
                String elementLoc = uiElement.getElementLoc();//值
                seleniumUtils.switchToFrameByLocator(
                        locType,
                        elementLoc
                );
            }
        } else{
            log.info("无效的选择内嵌网页");
            throw new IllegalArgumentException("无效的选择内嵌网页");
        }
    }


    //--------------------弹窗操作--------------------

    /**
     * 弹窗操作
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void handlePopup(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        if (step.getOperate()==1){
            log.info("弹窗操作");
            // 获取输入内容（如果需要）
            String inputValue = "1".equals(step.getIsEnter()) ? step.getInputValue() : null;
            String operateWay = step.getOperateWay();   //操作方式 1确定 2取消
            // 执行弹窗操作
            seleniumUtils.handleAlert(
                    Integer.parseInt(operateWay), // 操作方式 (1=确定, 2=取消)
                    inputValue                              // 输入内容
            );
        }else{
            log.info("无效的弹窗操作");
            throw new IllegalArgumentException("无效的弹窗操作");
        }
    }

    //---------------------------元素操作----------------------------------

    /**
     * 提交表单
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void submitForm(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        if ("2".equals(step.getOperateObject())) {
            //元素对象
            String operateLocType = step.getOperateLocType();   //属性
            String operateLocValue = step.getOperateLocValue(); //值
            // 根据属性和值定位元素并提交表单
            seleniumUtils.findElement(operateLocType, operateLocValue).submit();
            log.info("通过元素对象提交表单，定位方式：{}，定位值：{}", operateLocType, operateLocValue);
        }else{
            //元素定位
            UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
            if (uiElement == null) {
                throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
            }
            String locType = uiElement.getLocType();    //属性
            String elementLoc = uiElement.getElementLoc();//值
            seleniumUtils.findElement(locType, elementLoc).submit();
            log.info("通过元素定位提交表单，定位方式：{}，定位值：{}", locType, elementLoc);
        }
    }


    /**
     * 下拉框操作
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void handleDropdown(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        log.info("下拉框操作");
        Integer operate = step.getOperate();    //操作 1选择 2取消
        WebElement dropdownElement;
        if ("2".equals(step.getOperateObject())) {
            //元素对象
            String operateLocType = step.getOperateLocType();   //属性
            String operateLocValue = step.getOperateLocValue(); //值
            dropdownElement = seleniumUtils.findElement(operateLocType, operateLocValue);
            log.info("通过元素对象定位下拉框，定位方式：{}，定位值：{}", operateLocType, operateLocValue);
        }else{
            //元素定位
            UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
            if (uiElement == null) {
                throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
            }
            String locType = uiElement.getLocType();    //属性
            String elementLoc = uiElement.getElementLoc();//值
            dropdownElement = seleniumUtils.findElement(locType, elementLoc);
            log.info("通过元素定位定位下拉框，定位方式：{}，定位值：{}", locType, elementLoc);
        }
        //子选项
        String subOptions = step.getSubOptions();   //1 选项 2索引 3值
        String subOptionsValue = step.getSubOptionsValue(); //值

        if (operate == 1) {
            // 选择操作
            seleniumUtils.selectDropdownOption(dropdownElement, subOptions, subOptionsValue);
        } else if (operate == 2) {
            // 取消操作
            // 如果需要取消下拉框的选择，可以使用默认选项或其他逻辑
            log.info("取消下拉框选择");
            // 示例：取消选择（假设下拉框的第一个选项是默认选项）
            seleniumUtils.selectDropdownOption(dropdownElement, "2", "0");
        } else {
            throw new IllegalArgumentException("无效的操作类型: " + operate);
        }
    }

    /**
     * 设置选项
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void setOption(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        log.info("设置选项");
        Integer operate = step.getOperate();    // 操作 1选择 2取消
        WebElement element;

        if ("2".equals(step.getOperateObject())) {
            // 元素对象
            String operateLocType = step.getOperateLocType();   // 属性
            String operateLocValue = step.getOperateLocValue(); // 值
            element = seleniumUtils.findElement(operateLocType, operateLocValue);
            log.info("通过元素对象定位选项，定位方式：{}，定位值：{}", operateLocType, operateLocValue);
        } else {
            // 元素定位
            UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
            if (uiElement == null) {
                log.error("未找到指定的元素，元素ID：{}", step.getOperateElementId());
                throw new IllegalArgumentException("未找到指定的元素");
            }
            String locType = uiElement.getLocType();    // 属性
            String elementLoc = uiElement.getElementLoc(); // 值
            element = seleniumUtils.findElement(locType, elementLoc);
            log.info("通过元素定位定位选项，定位方式：{}，定位值：{}", locType, elementLoc);
        }

        if (operate == 1) {
            // 选择操作
            if (!element.isSelected()) {
                element.click();
                log.info("设置选项为选中状态");
            }
        } else if (operate == 2) {
            // 取消操作
            if (element.isSelected()) {
                element.click();
                log.info("设置选项为未选中状态");
            }
        } else {
            throw new IllegalArgumentException("无效的操作类型: " + operate);
        }
    }


    /**
     * 等待元素
     *
     * @param step        步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void waitForElement(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        log.info("等待元素");
        //操作 1等待元素等于给定的定值(Text) 2 等待元素存在 3等待元素显示 4等待元素不显示 5等待元素不存在 6等待元素可编辑 7等待元素不可编辑
        By locator;
        if ("2".equals(step.getOperateObject())) {
            //元素对象
            String operateLocType = step.getOperateLocType();   //属性
            String operateLocValue = step.getOperateLocValue(); //值
            // 使用直接指定的定位方式
            locator = seleniumUtils.getLocator(
                    operateLocType,
                    operateLocValue
            );
        }else{
            //元素定位
            UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
            String locType = uiElement.getLocType();    //属性
            String elementLoc = uiElement.getElementLoc();//值
            locator = seleniumUtils.getLocator(
                    locType,
                    elementLoc
            );
        }
        // 解析等待时间（默认15000ms）
        long timeout = 15000;
        if (step.getOperate() != 1 && step.getAwaitValue() != null) {
            try {
                timeout = Long.parseLong(step.getAwaitValue());
            } catch (NumberFormatException e) {
                log.warn("等待时间格式错误，使用默认值15000ms");
            }
        }
        // 执行等待操作
        seleniumUtils.waitForElement(
                locator,
                step.getOperate(),
                step.getOperate() == 1 ? step.getAwaitValue() : null,
                timeout
        );
    }


    //--------------------------鼠标操作------------------------------


    /**
     * 鼠标点击操作
     * @param step 步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void mouseClick(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        try {
            log.info("执行鼠标操作，方式: {}", step.getClickMethod());
            // 获取定位器
            By locator;
            if ("2".equals(step.getOperateObject())) {
                // 使用直接指定的定位方式
                locator = seleniumUtils.getLocator(
                        step.getOperateLocType(),
                        step.getOperateLocValue()
                );
            } else {
                // 使用元素ID从数据库获取定位信息
                UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
                if (uiElement == null) {
                    throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
                }
                locator = seleniumUtils.getLocator(
                        uiElement.getLocType(),
                        uiElement.getElementLoc()
                );
            }
            // 执行鼠标操作
            seleniumUtils.performMouseAction(
                    locator,
                    Integer.parseInt(step.getClickMethod())
            );
        } catch (NumberFormatException e) {
            log.error("鼠标操作类型格式错误: {}", step.getClickMethod());
            throw new RuntimeException("鼠标操作类型必须是数字(1-5)", e);
        } catch (Exception e) {
            log.error("鼠标操作执行失败", e);
            throw new RuntimeException("鼠标操作失败: " + e.getMessage(), e);
        }
    }

    /**
     * 鼠标移动操作
     * @param step 步骤对象
     * @param seleniumUtils Selenium工具类
     */
    private void mouseMove(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        try {
            log.info("执行鼠标移动操作，方式: {}", step.getClickMethod());
            // 获取定位器
            By locator;
            if ("2".equals(step.getOperateObject())) {
                // 使用直接指定的定位方式
                locator = seleniumUtils.getLocator(
                        step.getOperateLocType(),
                        step.getOperateLocValue()
                );
            } else {
                // 使用元素ID从数据库获取定位信息
                UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
                if (uiElement == null) {
                    throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
                }
                locator = seleniumUtils.getLocator(
                        uiElement.getLocType(),
                        uiElement.getElementLoc()
                );
            }
            // 执行鼠标移动操作
            seleniumUtils.performMouseMove(
                    locator,
                    Integer.parseInt(step.getClickMethod()) // 1=移出，2=移入
            );


        } catch (NumberFormatException e) {
            log.error("鼠标移动类型格式错误: {}", step.getClickMethod());
            throw new RuntimeException("鼠标移动类型必须是数字(1-2)", e);
        } catch (Exception e) {
            log.error("鼠标移动操作执行失败", e);
            throw new RuntimeException("鼠标移动操作失败: " + e.getMessage(), e);
        }
    }

    /**
     * 输入操作
     * @param step 步骤对象
     * @param seleniumUtils Selenium工具类
     */
    public void inputText(UiSceneSteps step, SeleniumUtils seleniumUtils) {
        try {
            log.info("执行输入操作，类型: {}", step.getOperate());

            // 获取定位器
            By locator;
            if ("2".equals(step.getOperateObject())) {
                // 使用直接指定的定位方式
                locator = seleniumUtils.getLocator(
                        step.getOperateLocType(),
                        step.getOperateLocValue()
                );
            } else {
                // 使用元素ID从数据库获取定位信息
                UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId());
                if (uiElement == null) {
                    throw new IllegalArgumentException("未找到ID为 " + step.getOperateElementId() + " 的元素");
                }
                locator = seleniumUtils.getLocator(
                        uiElement.getLocType(),
                        uiElement.getElementLoc()
                );
            }

            // 获取输入内容
            String inputValue = step.getInputValue();
            if (inputValue == null || inputValue.trim().isEmpty()) {
                log.warn("输入内容为空，将执行清空操作");
                seleniumUtils.clearInput(locator);
                return;
            }
            // 执行输入操作
            if (step.getOperate() == 1) { // 普通输入框
                seleniumUtils.inputText(
                        locator,
                        inputValue,
                        true, // 默认先清空
                        1    // 默认使用普通输入方式
                );
            } else if (step.getOperate() == 2) { // 可编辑段落
                seleniumUtils.inputToEditableDiv(
                        locator,
                        inputValue
                );
            } else {
                throw new IllegalArgumentException("不支持的输入操作类型: " + step.getOperate());
            }

        } catch (Exception e) {
            log.error("输入操作执行失败", e);
            throw new RuntimeException("输入操作失败: " + e.getMessage(), e);
        }
    }

    /**
     * 文件上传
     * @param step
     * @param seleniumUtils
     */
    public void uploadFile(UiSceneSteps step, SeleniumUtils seleniumUtils){

    }

}