package com.gxwebsoft.oa.controller;

import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.net.url.UrlQuery;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.FileRecord;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.oa.entity.OaAppUrl;
import com.gxwebsoft.oa.entity.OaAppUser;
import com.gxwebsoft.oa.service.OaAppService;
import com.gxwebsoft.oa.entity.OaApp;
import com.gxwebsoft.oa.param.OaAppParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.oa.service.OaAppUrlService;
import com.gxwebsoft.oa.service.OaAppUserService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static com.gxwebsoft.common.core.constants.AppUserConstants.ADMINISTRATOR;

/**
 * 应用控制器
 *
 * @author 科技小王子
 * @since 2024-09-10 20:57:41
 */
@Tag(name = "应用管理")
@RestController
@RequestMapping("/api/oa/oa-app")
public class OaAppController extends BaseController {
    @Resource
    private OaAppService oaAppService;
    @Resource
    private OaAppUrlService oaAppUrlService;
    @Resource
    private OaAppUserService oaAppUserService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ConfigProperties configProperties;

    @PreAuthorize("hasAuthority('oa:app:list')")
    @Operation(summary = "分页查询应用")
    @GetMapping("/page")
    public ApiResult<PageResult<OaApp>> page(OaAppParam param, HttpServletRequest request) {
      final User loginUser = getLoginUser();
      // 未登录情况
      if(loginUser == null){
        String access_token = JwtUtil.getAccessToken(request);
        param.setToken(access_token);
        return success("案例列表",caseList(param));
      }
      final Integer userId = loginUser.getUserId();
      loginUser.getRoles().forEach(d -> {
        if(!StrUtil.equals(d.getRoleCode(),"superAdmin") && !StrUtil.equals(d.getRoleCode(),"admin")){
          // 非管理员按项目成员权限显示
          final List<OaAppUser> list = oaAppUserService.list(new LambdaQueryWrapper<OaAppUser>().eq(OaAppUser::getUserId, userId));
          final Set<Integer> collect = list.stream().map(OaAppUser::getAppId).collect(Collectors.toSet());
          param.setAppIds(collect);
        }
      });
      // 过滤续费提醒参数
      if (param.getAppStatus() != null && param.getAppStatus().equals("续费中")) {
        param.setAppStatus(null);
      }
      // 使用关联查询
      return success(oaAppService.pageRel(param));
    }

    @PreAuthorize("hasAuthority('oa:app:list')")
    @Operation(summary = "查询全部应用")
    @GetMapping()
    public ApiResult<List<OaApp>> list(OaAppParam param) {
        // 使用关联查询
        return success(oaAppService.listRel(param));
    }

    @PreAuthorize("hasAuthority('oa:app:list')")
    @Operation(summary = "根据id查询应用")
    @GetMapping("/{id}")
    public ApiResult<OaApp> get(@PathVariable("id") Integer id) {
      final User loginUser = getLoginUser();
      // 未登录情况
      if(loginUser == null){
        return success("案例详情",getDesensitizedApp(id));
      }
      if (!CommonUtil.hasRole(loginUser.getRoles(),"superAdmin") && !CommonUtil.hasRole(loginUser.getRoles(),"admin")) {
        // 查询权限
        if (oaAppUserService.count(new LambdaQueryWrapper<OaAppUser>().eq(OaAppUser::getUserId, getLoginUserId()).eq(OaAppUser::getAppId,id)) == 0) {
          return fail("无查看权限",null);
        }
      }
      // 使用关联查询
      return success(oaAppService.getByIdRel(id));
    }

    @PreAuthorize("hasAuthority('oa:app:save')")
    @Operation(summary = "添加应用")
    @PostMapping()
    public ApiResult<?> save(@RequestBody OaApp app) {
      // 记录当前登录用户id、租户id、商户编号
      User loginUser = getLoginUser();
      OaAppUser appUser = new OaAppUser();
      if (loginUser != null) {
        app.setUserId(loginUser.getUserId());
        app.setTenantId(loginUser.getTenantId());
      }
      if (oaAppService.count(new LambdaQueryWrapper<OaApp>()
        .eq(OaApp::getAppCode, app.getAppCode())) > 0) {
        return fail("应用标识已存在");
      }
      if (oaAppService.save(app)) {
        // 添加应用管理员
        if (loginUser != null) {
          appUser.setUserId(loginUser.getUserId());
          appUser.setNickname(loginUser.getNickname());
          appUser.setAppId(app.getAppId());
          appUser.setRole(ADMINISTRATOR);
          oaAppUserService.save(appUser);
        }
        return success("添加成功");
      }
      return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('oa:app:update')")
    @Operation(summary = "修改应用")
    @PutMapping()
    public ApiResult<?> update(@RequestBody OaApp oaApp) {
        if (oaAppService.updateById(oaApp)) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('oa:app:remove')")
    @Operation(summary = "删除应用")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (oaAppService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @PreAuthorize("hasAuthority('oa:app:save')")
    @Operation(summary = "批量添加应用")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<OaApp> list) {
        if (oaAppService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('oa:app:update')")
    @Operation(summary = "批量修改应用")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<OaApp> batchParam) {
        if (batchParam.update(oaAppService, "app_id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('oa:app:remove')")
    @Operation(summary = "批量删除应用")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (oaAppService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @Operation(summary = "统计信息")
    @GetMapping("/data")
    public ApiResult<Map<String, Integer>> data() {
      Map<String, Integer> data = new HashMap<>();
      long totalNum = oaAppService.count(
        new LambdaQueryWrapper<>()
      );
      long totalNum2 = oaAppService.count(
        new LambdaQueryWrapper<OaApp>()
          .eq(OaApp::getAppStatus, "开发中")
      );
      long totalNum3 = oaAppService.count(
        new LambdaQueryWrapper<OaApp>()
          .eq(OaApp::getAppStatus, "已上架")
      );
      long totalNum4 = oaAppService.count(
        new LambdaQueryWrapper<OaApp>()
          .eq(OaApp::getAppStatus, "已上架")
          .eq(OaApp::getShowExpiration,false)
      );
      long totalNum5 = oaAppService.count(
        new LambdaQueryWrapper<OaApp>()
          .eq(OaApp::getAppStatus, "已下架")
      );
      long totalNum6 = oaAppService.count(
        new LambdaQueryWrapper<OaApp>()
          .eq(OaApp::getShowCase,true)
      );
      long totalNum7 = oaAppService.count(
        new LambdaQueryWrapper<OaApp>()
          .eq(OaApp::getShowIndex, true)
      );

      data.put("totalNum", Math.toIntExact(totalNum));
      data.put("totalNum2", Math.toIntExact(totalNum2));
      data.put("totalNum3", Math.toIntExact(totalNum3));
      data.put("totalNum4", Math.toIntExact(totalNum4));
      data.put("totalNum5", Math.toIntExact(totalNum5));
      data.put("totalNum6", Math.toIntExact(totalNum6));
      data.put("totalNum7", Math.toIntExact(totalNum7));
      return success(data);
    }


  // 读取案例列表
  private PageResult<OaApp> caseList(OaAppParam param){
    param.setShowCase(true);
    final PageResult<OaApp> appPageResult = oaAppService.pageRel(param);
    appPageResult.getList().forEach(d -> {
      d.setContent(null);
      // 读取账号列表
      d.setAppUrlList(oaAppUrlService.list(new LambdaQueryWrapper<OaAppUrl>().eq(OaAppUrl::getAppId,d.getAppId())));
      // 读取项目附件（链式构建GET请求）
      HashMap<String, Object> map = new HashMap<>();
      map.put("appId", d.getAppId());
      final String build = UrlBuilder.of(configProperties.getServerUrl() + "/file/page").setQuery(new UrlQuery(map)).build();
      String response = HttpRequest.get(build)
        .header("Authorization", param.getToken())
        .header("Tenantid", d.getTenantId().toString())
        .body(JSONObject.toJSONString(map))//表单内容
        .timeout(20000)//超时，毫秒
        .execute().body();

      final ApiResult<PageResult<FileRecord>> userResult = JSONObject.parseObject(response, new TypeReference<ApiResult<PageResult<FileRecord>>>() {
      });
      d.setAppFiles(userResult.getData().getList());
    });
    return appPageResult;
  }

  private OaApp getDesensitizedApp(Integer id) {
    final OaApp app = oaAppService.getByIdRel(id);
    app.setPhone(DesensitizedUtil.mobilePhone(app.getPhone()));
    app.setCompanyName(
      StrUtil.hide(app.getCompanyName(), 2, app.getCompanyName().length() - 2));
    app.setRequirement(DesensitizedUtil.chineseName(app.getCompanyName()));
    return app;
  }

  @PreAuthorize("hasAuthority('oa:app:update')")
  @Operation(summary = "重置秘钥")
  @PostMapping("/updateAppSecret")
  public ApiResult<?> updateAppSecret(@RequestBody OaApp app) {
    String key = "code:" + app.getPhone();
    final String code = redisUtil.get(key);
    if (app.getAppId() == null) {
      return fail("appId不合法");
    }
    if(app.getAppSecret() == null){
      return fail("appSecret不合法");
    }
    if(app.getAppCode() == null){
      return fail("短信验证码不正确");
    }
//         && !app.getAppCode().equals("170083")
    if(!app.getAppCode().equals(code)){
      return fail("短信验证码不正确");
    }
    oaAppService.updateById(app);
    // 保存到redis
    redisUtil.set("AppSecret:" + app.getAppId(),app.getAppSecret());
    redisUtil.delete(key);
    return success("重置成功",app.getAppSecret());
  }

  @PreAuthorize("hasAuthority('oa:app:list')")
  @Operation(summary = "APP应用授权身份效验")
  @GetMapping("/authentication/{appid}")
  public ApiResult<?> authentication(@PathVariable("appid") String appid) {
    final OaApp appInfo = oaAppService.getById(appid);
    if(appInfo == null){
      return fail("应用不存在:".concat(appid));
    }
    return success("应用信息",appInfo);
  }

  @Operation(summary = "查询我的项目信息")
  @GetMapping("/getMyApp")
  public ApiResult<OaApp> getMyApp() {
    final User loginUser = getLoginUser();
    // 未登录情况
    if(loginUser == null){
      return fail("请先登录",null);
    }
    oaAppService.list();

    // 使用关联查询
    return success("查询成功",null);
  }

}
