package com.gxwebsoft.cms.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.cms.entity.Domain;
import com.gxwebsoft.cms.entity.Website;
import com.gxwebsoft.cms.mapper.DomainMapper;
import com.gxwebsoft.cms.param.DomainParam;
import com.gxwebsoft.cms.service.DomainService;
import com.gxwebsoft.cms.service.WebsiteService;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.web.*;
import com.gxwebsoft.common.system.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;

import static com.gxwebsoft.common.core.utils.DomainUtils.DNSLookup;

/**
 * 网站域名记录表控制器
 *
 * @author 科技小王子
 * @since 2024-03-26 21:27:29
 */
@Api(tags = "网站域名")
@RestController
@RequestMapping("/api/cms/domain")
public class DomainController extends BaseController {
    @Resource
    private DomainService domainService;
    @Resource
    private DomainMapper domainMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private WebsiteService websiteService;

    @ApiOperation("根据域名查询授权")
    @GetMapping("/getByDomain")
    public ApiResult<Domain> get(DomainParam param) {
      System.out.println("param = " + param);
      final Domain one = domainService.getOne(new LambdaQueryWrapper<Domain>().eq(Domain::getDomain, param.getDomain()).eq(Domain::getDeleted, 0).last("limit 1"));
      if (ObjectUtil.isEmpty(one)) {
        return fail("域名未授权.",null);
      }
      if (one.getStatus().equals(0)) {
        return fail("域名审核中.",null);
      }
      return success(one);
    }

    @ApiOperation("分页查询网站域名记录表")
    @GetMapping("/page")
    public ApiResult<PageResult<Domain>> page(DomainParam param) {
        // 使用关联查询
        return success(domainService.pageRel(param));
    }

    @ApiOperation("查询全部网站域名记录表")
    @GetMapping()
    public ApiResult<List<Domain>> list(DomainParam param) {
        // 使用关联查询
        return success(domainService.listRel(param));
    }

    @ApiOperation("根据id查询网站域名记录表")
    @GetMapping("/{id}")
    public ApiResult<Domain> get(@PathVariable("id") Integer id) {
        // 使用关联查询
        return success(domainService.getByIdRel(id));
    }

    @PreAuthorize("hasAuthority('cms:domain:save')")
    @ApiOperation("添加网站域名记录表")
    @PostMapping()
    public ApiResult<?> save(@RequestBody Domain domain) {
        // 记录当前登录用户id
        User loginUser = getLoginUser();
        if (loginUser != null) {
          domain.setUserId(loginUser.getUserId());
          domain.setTenantId(loginUser.getTenantId());
          domain.setHostValue(UUID.randomUUID() + ".wsdns.cn");
        }
        // 检查缓存是否已存在
        String key = "Domain:" + domain.getDomain();
        final String string = redisUtil.get(key);
        if(string != null){
          return fail("您绑定的域名已存在");
        }
        // 是否有重复
        if(domainService.count(new LambdaQueryWrapper<Domain>().eq(Domain::getDomain, domain.getDomain())) > 0){
          return fail("您绑定的域名已存在");
        }
        // 是否超过最大绑定数量
        if(domainService.count() > 20){
          return fail("超过最大绑定限制");
        }

        if (domainService.save(domain)) {
          return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('cms:domain:update')")
    @ApiOperation("修改网站域名记录表")
    @PutMapping()
    public ApiResult<?> update(@RequestBody Domain domain) {
        if (domainService.updateById(domain)) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('cms:domain:remove')")
    @ApiOperation("删除网站域名记录表")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
      final Domain domain = domainService.getById(id);
        if (domainService.removeById(id)) {
            // 删除缓存
            String key = "Domain:" + domain.getDomain();
            redisUtil.delete(key);
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @PreAuthorize("hasAuthority('cms:domain:update')")
    @ApiOperation("批量添加网站域名记录表")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<Domain> list) {
        if (domainService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('cms:domain:update')")
    @ApiOperation("批量修改网站域名记录表")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<Domain> batchParam) {
        if (batchParam.update(domainService, "id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('cms:domain:remove')")
    @ApiOperation("批量删除网站域名记录表")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (domainService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @ApiOperation("检查域名是否存在")
    @GetMapping("/existence")
    public ApiResult<?> existence(ExistenceParam<Domain> param) {
      if (param.isExistence(domainService, Domain::getDomain)) {
        return success(param.getValue() + "已存在");
      }
      return fail(param.getValue() + "不存在");
    }

    @ApiOperation("验证DNS解析信息是否填写正确")
    @GetMapping("/resolvable/{id}")
    public ApiResult<?> resolvable(@PathVariable("id") Integer id){
      Domain domain = domainService.getByIdRel(id);
      if(DNSLookup(domain)){
        // 改变状态
        domain.setStatus(1);
        domainService.updateById(domain);
        // 重写缓存
        String key = "Domain:" + domain.getDomain();
        redisUtil.set(key,domain.getTenantId());
        return success("验证通过");
      };
      return fail("未检测到解析值");
    }

    @ApiOperation("根据id查询网站域名记录表")
    @GetMapping("/getByDomain/{domain}")
    public ApiResult<Domain> getByDomain(@PathVariable("domain") String domain) {
      final Domain one = domainMapper.getDomain(domain);
      return success(one);
    }

}
