package org.jeecg.modules.adweb.site.controller;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.adweb.common.service.DomainService;
import org.jeecg.modules.adweb.common.util.AdwebRedisUtil;
import org.jeecg.modules.adweb.quota.service.IResourceQuotaService;
import org.jeecg.modules.adweb.site.entity.AdwebSite;
import org.jeecg.modules.adweb.site.service.SelfWebSiteService;
import org.jeecg.modules.adweb.site.service.SiteManageService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * @autor jerry
 * @date: 2022/1/11 20:45
 */
@Slf4j
@RestController
@RequestMapping("/wpWebSite")
public class WPSiteController {

    @Resource private SelfWebSiteService selfWebSiteService;

    @Resource private AdwebRedisUtil adwebRedisUtil;

    @Resource private SiteManageService siteManageService;

    @Resource private DomainService domainService;

    @Resource private IResourceQuotaService resourceQuotaService;

    /**
     * 创建站点
     *
     * @param templateId 模板id
     * @param planId 域名
     * @param name 站点名称
     * @param uid 站点所属用户名称
     * @param request 请求信息
     * @return 创建的站点信息
     */
    @RequestMapping("addWebsite")
    public Result<?> createWebSiteByTempId(
            HttpServletRequest request,
            Long templateId,
            String planId,
            String name,
            String uid,
            Integer giveDay,
            Integer compensateDay) {
        log.info("新建站点模板：" + templateId + "; 站点名称：" + name + "; 套餐id：" + planId);

        // 校验用户网站资源额度
        Pair<Integer, Integer> websiteQuota = resourceQuotaService.getWebsiteQuota(uid);
        if (websiteQuota.getLeft() <= websiteQuota.getRight()) {
            log.warn("用户 {} 网站资源额度不足", uid);
            return Result.error(
                    String.format(
                            "网站创建失败。用户资源额度为%d，已使用%d",
                            websiteQuota.getLeft(), websiteQuota.getRight()),
                    null);
        }

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 如果2分钟内有创建过站点，则不允许再次创建站点
        String flag = adwebRedisUtil.getString(templateId + "_" + uid);
        if (StringUtils.isNotBlank(flag)) {
            log.info("2分钟内重复拉站点");
            try {
                Thread.sleep(5 * 60 * 1000);
            } catch (InterruptedException e) {
                log.info("重复拉站点的睡眠出现异常");
            }
            return Result.OK("ignore");
        }
        adwebRedisUtil.set(templateId + "_" + uid, "flag", 2 * 60);

        LoginUser user = SecureUtil.currentUser();
        // 建站服务
        selfWebSiteService.createSite(
                user, templateId, uid, name, planId, sysUser, giveDay, compensateDay);

        return Result.OK("申请创建站点成功，请等待通知，或者去站点管理查看结果！");
    }

    /**
     * 发布网站接口
     *
     * <p>该方法通过接收服务器ID、域名和站点代码来申请发布一个网站 用户通过该接口提交发布申请，实际的发布操作由后台异步处理
     *
     * @param request HttpServletRequest对象，用于获取请求相关信息
     * @param serverId 服务器ID，标识要发布的服务器
     * @param domain 域名，标识要发布的网站域名
     * @param siteCode 站点代码，用于识别和验证要发布的站点
     * @return 返回一个Result对象，包含发布申请的结果信息
     */
    @RequestMapping("releaseWebsite")
    public Result<?> releaseWebsite(
            HttpServletRequest request, String serverId, String domain, String siteCode) {

        LoginUser user = SecureUtil.currentUser();

        // 站点发布
        selfWebSiteService.releaseSite(user, serverId, domain, siteCode);

        return Result.OK("申请发布站点成功，请等待发布通知，或者去站点管理查看结果！");
    }

    /**
     * 重新发布站点
     *
     * @param domain 域名
     * @param siteId 站点ID
     * @return
     */
    @RequestMapping("delReleaseWebsite")
    public Result<?> delReleaseWebsite(String domain, Integer siteId) {
        return selfWebSiteService.delReleaseWebsite(domain, siteId);
    }

    /**
     * 站点 启动/停止
     *
     * @param siteId 站点Id
     * @param status 站点启动（local）：1；停止：2; 站点启动（prod）：3；停止：4;
     * @return
     */
    @RequestMapping("siteStartOrStop")
    public Result<?> siteStartOrStop(Integer siteId, Integer status) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        boolean flag = selfWebSiteService.siteStartOrStop(sysUser, siteId, status);
        String result = "";
        if (flag) {
            if (status.equals(1) || status.equals(3)) {
                result = "站点启动成功！";
            }
            if (status.equals(2) || status.equals(4)) {
                result = "站点停止成功！";
            }
        } else {
            if (status.equals(1) || status.equals(3)) {
                result = "站点启动失败！";
            }
            if (status.equals(2) || status.equals(4)) {
                result = "站点停止失败！";
            }
        }
        return Result.OK(result);
    }

    /**
     * 检查域名是否有效
     *
     * <p>此方法用于验证提交的域名是否符合特定条件它首先检查域名是否与CNAME或IP地址相同， 然后检查域名是否已被使用接下来，它验证域名是否以http开头，
     * 最后检查域名是否指向CNAME或IP地址如果所有条件都满足，则域名被视为有效
     *
     * @param request HttpServletRequest对象，用于获取请求信息
     * @param cname 用户的CNAME
     * @param ip 用户的IP地址
     * @param domain 用户提交的域名
     * @return 返回一个Result对象，包含验证结果和相关信息
     */
    @RequestMapping(value = "/check/domain", method = RequestMethod.POST)
    @ResponseBody
    public Result<?> checkDomain(
            HttpServletRequest request, String cname, String ip, String domain) {

        log.info("====== checkDomain cname:{},ip:{},domain:{} ======", cname, ip, domain);
        if (cname.equalsIgnoreCase(domain) || ip.equalsIgnoreCase(domain)) {

            return new Result<>(100, "请勿提交我们的CNAME或IP");
        }

        // 提交的域名已发布或被他人使用
        List<AdwebSite> siteList = siteManageService.checkSiteDomainIsExists(domain);
        log.info("siteList:{}", siteList);
        if (!siteList.isEmpty()) {
            return new Result<>(102, "您填写的域名已发布或被他人使用，请勿重复提交！");
        }
        // 检验域名是否以http开头
        List<String> headStrs = new ArrayList<>();
        headStrs.add("http://");
        headStrs.add("https://");
        boolean isHttp = domainService.checkDomainBegin(domain, headStrs);
        // isHttp == true 是以http或https开头 直接返回
        if (isHttp) {
            return new Result<>(101, "域名请勿以http://或https://开头");
        }
        // 检验域名是否指向cname或ip
        boolean isToCnameOrIp = domainService.checkDomainIsCnameOrIp(cname, domain, ip);
        if (isToCnameOrIp) {
            // 满足不以http等开头 并且域名指向cname或ip中的一个
            return Result.ok();
        } else {
            // 未指向cname或ip任意一个
            return new Result<>(103, "请确认您的域名已指向CNAME或IP");
        }
    }
}
