package cn.sikey.selenium.api;

import cn.sikey.framework.common.exception.ServiceException;
import cn.sikey.framework.common.pojo.CommonResult;
import cn.sikey.selenium.api.selenium.SmsApi;
import cn.sikey.selenium.api.selenium.dto.AuthRespVO;
import cn.sikey.selenium.api.selenium.dto.TriggerSmsReqDTO;
import cn.sikey.selenium.api.selenium.dto.VerifyCodeReqDTO;
import cn.sikey.selenium.util.AppIdGeneratorUtil;
import cn.sikey.selenium.util.WebDriverContextManagerUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Objects;

/**
 * @Author: nelson
 * @Date: 2025/6/26
 * @Description: 验证码
 */
@Slf4j
@RestController // 提供 RESTful API 接口，给 Feign 调用
@Validated
public class SmsServiceImpl implements SmsApi {

    @Value("${selenium.remote.url}")
    private String url;

    @Value("${selenium.remote.loginUrl}")
    private String loginUrl;

    @Value("${selenium.remote.redirectUrl}")
    private String redirectUrl;

    public static final String ACCESS_TOKEN1 = "/app-api/mcdisk/wristwatch/authorize/accessToken1";

    @Value("${selenium.remote.appid}")
    private String appid;

    @Value("${selenium.remote.appkey}")
    private String appkey;

    public static final String APP_TITLE = "移动云盘";

    public static final int GET_VERIFICATION_CODE_AGAIN = 10001;

    public static final int UUID_EXPIRES_MINUTE = 2;

    public static final String SMS_CODE_KEY = "sms:code:phone:";

    public static final String SMS_SESSION_ID_KEY = "sms:session:id:";

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Qualifier("myTaskExecutor")
    @Autowired
    private ThreadPoolTaskExecutor myTaskExecutor;

    /**
     * 发送验证码
     *
     * @param request 请求
     * @return
     */
    @Override
    public CommonResult<Void> triggerSmsVerification(TriggerSmsReqDTO request) {
        String uuid = AppIdGeneratorUtil.generateUuid(appid);
        String phoneNumber = request.getPhoneNumber();
        String deviceId = request.getTicket();

        myTaskExecutor.execute(() -> {
            WebDriver driver = null;
            try {
                String sessionId = WebDriverContextManagerUtil.createSession(url);
                driver = WebDriverContextManagerUtil.getDriver(sessionId);
                WebDriverWait wait = WebDriverContextManagerUtil.getWait(sessionId);

                String encodedUrl = URLEncoder.encode(redirectUrl + ACCESS_TOKEN1 + "?uuid=" + uuid + "&ticket=" + deviceId, StandardCharsets.UTF_8);
                String toLoginUrl = loginUrl + "?pageType=3&appId=" + appid + "&appKey=" + appkey + "&deviceId=" + deviceId + "&appTitle=" + APP_TITLE + "&uuid=" + uuid + "&redirectUrl=" + encodedUrl;

                driver.get(toLoginUrl);
                log.info("[发送验证码]获取移动云盘地址：{}", toLoginUrl);
                // 等待页面加载完成
                wait.until(ExpectedConditions.urlContains("middlePage"));

                // 手机号输入框定位
                WebElement phoneInput = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@type='number' and @maxlength='11']")));
                phoneInput.sendKeys(phoneNumber);

                // 验证码按钮定位
                WebElement codeBtn = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//button[.//span[contains(text(),'获取验证码')]]")));

                // 确保按钮可见
                ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView({block:'center'});", codeBtn);

                // 使用JavaScript点击确保不被拦截
                ((JavascriptExecutor) driver).executeScript("arguments[0].click();", codeBtn);

                redisTemplate.opsForValue().set(SMS_CODE_KEY + phoneNumber, uuid, Duration.ofMinutes(UUID_EXPIRES_MINUTE));
                redisTemplate.opsForValue().set(SMS_SESSION_ID_KEY + phoneNumber, sessionId, Duration.ofMinutes(UUID_EXPIRES_MINUTE));
                log.info("[发送验证码]短信验证码已发送，手机号：{}", phoneNumber);
            } catch (Exception e) {
                log.info("[发送验证码]异常，页面内容：", driver.findElement(By.tagName("body")).getAttribute("outerHTML"));
                throw new ServiceException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "触发短信验证码失败");
            }
        });


        return CommonResult.success();
    }

    /**
     * 验证码登录
     *
     * @param request 校验验证码登录
     * @return
     */
    @Override
    public CommonResult<AuthRespVO> verifyCodeAndLogin(VerifyCodeReqDTO request) {
        String phoneNumber = request.getPhoneNumber();
        Object uuid = redisTemplate.opsForValue().get(SMS_CODE_KEY + phoneNumber);
        if (Objects.isNull(uuid)) {
            throw new ServiceException(GET_VERIFICATION_CODE_AGAIN, "请重新获取验证码");
        }

        Object sessionId = redisTemplate.opsForValue().get(SMS_SESSION_ID_KEY + phoneNumber);
        if (Objects.isNull(sessionId)) {
            throw new ServiceException(GET_VERIFICATION_CODE_AGAIN, "无效的会话ID");
        }

        String deviceId = request.getTicket();
        String verificationCode = request.getVerificationCode();


        myTaskExecutor.execute(() -> {
            WebDriver driver;
            String sId = "";

            try {

                String encodedUrl = URLEncoder.encode(redirectUrl + ACCESS_TOKEN1 + "?uuid=" + uuid + "&ticket=" + deviceId, StandardCharsets.UTF_8);

                sId = String.valueOf(sessionId);
                driver = WebDriverContextManagerUtil.getDriver(sId);
                WebDriverWait wait = WebDriverContextManagerUtil.getWait(sId);

                String toLoginUrl = loginUrl + "?pageType=3&appId=" + appid + "&appKey=" + appkey + "&deviceId=" + deviceId + "&appTitle=" + APP_TITLE + "&uuid=" + uuid + "&redirectUrl=" + encodedUrl;

                log.info("[校验验证码登录]获取移动云盘地址：{}", toLoginUrl);

                // 验证码输入框定位
                WebElement codeInput = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@placeholder='输入验证码' and @maxlength='6']")));
                codeInput.sendKeys(verificationCode);

                Thread.sleep(3000);

                // 点击协议复选框（使用优化方案）
                WebElement agreementLabel = new WebDriverWait(driver, Duration.ofSeconds(30)).until(ExpectedConditions.elementToBeClickable(By.xpath("//div[contains(@class,'login_agreementGroup')]//input[@type='checkbox']/ancestor::label[1]")));

                // 使用Actions确保点击成功
                new Actions(driver).scrollToElement(agreementLabel).moveToElement(agreementLabel).click().perform();


                // 定位并点击第二个登录按钮
                By loginButtonSelector = By.xpath(
                        "//div[@id='login_mobile']/button[contains(@class, 'login_btn') " +
                                "and not(contains(@style, 'display: none')) " +
                                "and position()=2]"
                );

                WebElement loginButton = wait.until(d -> {
                    WebElement btn = d.findElement(loginButtonSelector);

                    // 确保按钮可见且未被禁用
                    if (btn.isDisplayed() && btn.getAttribute("disabled") == null) {
                        return btn;
                    }
                    return null;
                });

                // 添加可视化边框（调试用）
                ((JavascriptExecutor) driver).executeScript(
                        "arguments[0].style.border='3px solid green';", loginButton
                );

                // 点击前滚动到元素
                ((JavascriptExecutor) driver).executeScript(
                        "arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});",
                        loginButton
                );
                Thread.sleep(500); // 等待滚动完成

                // JavaScript点击
                ((JavascriptExecutor) driver).executeScript("arguments[0].click();", loginButton);
                System.out.println("已点击第二个登录按钮");

                new WebDriverWait(driver, Duration.ofSeconds(20))
                        .until(ExpectedConditions.invisibilityOf(loginButton));

                log.info("[校验验证码登录]登录成功，手机号：{}，验证码：{}", phoneNumber, verificationCode);
            } catch (Exception e) {
                log.error("[校验验证码登录]异常：{0}", e);
                throw new ServiceException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "触发校验验证码登录失败");
            } finally {
                WebDriverContextManagerUtil.destroySession(sId);
                redisTemplate.delete(SMS_CODE_KEY);
                redisTemplate.delete(SMS_SESSION_ID_KEY);
            }
        });

        return CommonResult.success();
    }

}

