package cn.iocoder.yudao.module.system.controller.admin.dingding;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
import cn.iocoder.yudao.module.system.controller.admin.dingding.vo.AuthLoginRequest;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantJoinReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dingding.DingUserTenantRelateDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dingding.DingUserTenantRelateMapper;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dingding.DingAuthServiceInfo;
import cn.iocoder.yudao.module.system.service.dingding.DingThirdTokenService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dingtalkcontact_1_0.models.GetUserResponse;
import com.aliyun.dingtalkcontact_1_0.models.GetUserResponseBody;
import com.aliyun.dingtalkoauth2_1_0.models.GetSsoUserInfoResponse;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenResponse;
import com.dingtalk.api.response.*;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_NOT_EXISTS;

/**
 * <p>DingLoginController 此类用于：钉钉企业内部应用免登（H5微应用）</p>
 * <p>@remark：钉钉企业内部微应用DEMO, 实现了身份验证（免登）功能</p>
 */
@Tag(name = "管理后台 - 钉钉第三方企业应用免登")
@RestController
@RequestMapping(value = "/system/auth/ding")
@Slf4j
public class DingThirdAuthController {

    @Resource
    private DingThirdTokenService dingAuthTokenService;

    @Resource
    private DingAuthServiceInfo dingAuthServiceInfo;

    @Resource
    private AdminAuthService authService;
    @Resource
    private AdminUserService userService;
    @Resource
    private TenantService tenantService;
    @Resource
    private DeptService deptService;
    @Resource
    private DingUserTenantRelateMapper dingUserTenantRelateMapper;

    @PostMapping(value = "/callback")
    @PermitAll
    @ResponseBody
    public Map<String, String> callback(@RequestParam String signature,
                                        @RequestParam String timestamp,
                                        @RequestParam String nonce,
                                        @RequestBody JsonNode encryptNode) {
        String encryptMsg = encryptNode.get("encrypt").textValue();
        String plainText = dingAuthServiceInfo.decryptText(signature, timestamp, nonce, encryptMsg);
        JSONObject callBackContent = JSON.parseObject(plainText);

        //进入回调事件分支选择
        Map<String, String> resultMap = dingAuthServiceInfo.caseProcess(callBackContent);
        return resultMap;
    }

    @Operation(summary = "第三方企业应用用户登录")
    @PostMapping("/authLogin")
    public CommonResult<AuthLoginRespVO> authLogin(@RequestBody AuthLoginRequest authLoginRequest) {
        String code = authLoginRequest.getCode();
        String corpId =  authLoginRequest.getCorpId();
        log.info("钉钉用户登录第三方企业应用code:{},corpId:{}", authLoginRequest.getCode(), authLoginRequest.getCorpId());
        //调用接口获取第三方企业应用的access_token，详情请参考获取第三方应用授权企业的accessToken。
//        String corpAccessToken = dingAuthTokenService.getCorpAccessToken(authLoginRequest.getCorpId());

        GetUserTokenResponse userTokenResponse = dingAuthTokenService.getUserAccessToken(authLoginRequest.getCode());
        log.info("用户登录信息corpAccessToken" + JSONObject.toJSONString(userTokenResponse));
        String userAccessToken = userTokenResponse.getBody().getAccessToken();
        GetUserResponse addressBookUserInfo = dingAuthTokenService.getAddressBookUserInfo(userAccessToken, "me");
        log.info("用户通讯录信息" + JSONObject.toJSONString(addressBookUserInfo));

        //查询租户
        TenantDO tenant = tenantService.getTenantByCorpId(corpId);
        if (tenant == null || tenant.getId() == null) {
            throw exception(TENANT_NOT_EXISTS);
        }
        //todo 查询租户管理员信息
        DingUserTenantRelateDO dingUserTenantRelateDO = dingUserTenantRelateMapper.selectOne(DingUserTenantRelateDO::getTenantId,tenant.getId());
        //获取企业token。
        String corpAccessToken = dingAuthTokenService.getThirdCorpAccessToken(corpId,tenant.getSuiteTicket());
        // System.out.println("企业" + JSONObject.toJSONString(corpAccessToken));
        log.info("企业" + JSONObject.toJSONString(corpAccessToken));
        //根据管理员用户userid查询管理员信息
        OapiV2UserGetResponse userUnfo = dingAuthTokenService.getUser(dingUserTenantRelateDO.getUserId(), corpAccessToken);
        // System.out.println("用户管理员信息" + JSONObject.toJSONString(userUnfo));
        log.info("用户管理员信息" + JSONObject.toJSONString(userUnfo));

        //todo 初始化用户
        GetUserResponseBody result= addressBookUserInfo.getBody();
        Boolean adminType = false;
        //todo 判断是否是管理员用户
        if(userUnfo.getResult().getUnionid().equals(result.getUnionId())){
            adminType = true;

            //-权限需开通
            OapiV2DepartmentListsubResponse departmentListsubResponse = dingAuthTokenService.getDept(corpAccessToken);
            System.out.println("部门组" + JSONObject.toJSONString(departmentListsubResponse.getResult()));
            //todo 是管理员后执行
            //todo 管理员登录时同步部门信息
            deptService.updateDDingDept(departmentListsubResponse.getResult(),tenant.getId());

        }
        //todo 根据授权登录人的UnionId获取用户详细- ——X——获取的内容不需要
//        OapiUserGetbyunionidResponse authUserInfo = dingAuthTokenService.getUserUnionId(result.getUnionId(), corpAccessToken);
//        System.out.println("登录用户信息详情" + JSONObject.toJSONString(authUserInfo));

        //todo 获取用户详情。查询是否存在
        AdminUserDO adminUserDO = userService.getUserByMobile(addressBookUserInfo.getBody().getMobile());
        if (Objects.isNull(adminUserDO)) {
            //创建用户信息
            UserSaveReqVO userSaveReqVO = new UserSaveReqVO();
            userSaveReqVO.setUsername(result.getMobile());
            userSaveReqVO.setNickname(result.getNick());
            userSaveReqVO.setEmail(result.getEmail());
            userSaveReqVO.setMobile(result.getMobile());
            userSaveReqVO.setAvatar(result.getAvatarUrl());
            userSaveReqVO.setPassword(result.getMobile() + ".1@2");

            adminUserDO = dingAuthServiceInfo.initUser(userSaveReqVO, corpId, adminType);
        }
        if(!adminUserDO.getTenantId().equals(tenant.getId())){
            userService.updateUserTenantId(adminUserDO.getId(),tenant.getId());
            //todo 更新用户租户操作
            TenantJoinReqVO createReqVO = new TenantJoinReqVO();
            createReqVO.setTenantId(tenant.getId());
            createReqVO.setCorpId(corpId);
            createReqVO.setUserId(adminUserDO.getId());
            tenantService.joinDDingTenant(createReqVO);
        }
        TenantContextHolder.setTenantId(tenant.getId());
        adminUserDO.setTenantId(tenant.getId());
        return success(authService.DDinglogin(adminUserDO),tenant.getId().toString());
    }

    @Operation(summary = "第三方企业应用授权")
    @PostMapping("/cropLogin")
    @PermitAll
    public CommonResult<AuthLoginRespVO> cropLogin(@RequestBody AuthLoginRequest authLoginRequest) {

        //todo 功能不完善，可参考[第三方企业应用用户登录]应用授权

        System.out.println("钉钉用户登录第三方企业应用code:{},corpId:{}" + authLoginRequest);
        String code = authLoginRequest.getCode();
        String corpId =  authLoginRequest.getCorpId();
        System.out.println("钉钉用户登录第三方企业应用code:{},corpId:{}" + code + corpId);
        //调用接口获取第三方企业应用的access_token，详情请参考获取第三方应用授权企业的accessToken。
        String corpAccessToken = dingAuthTokenService.getCorpAccessToken(corpId);
        GetUserTokenResponse userTokenResponse = dingAuthTokenService.getUserAccessToken(code);
        System.out.println("用户登录信息corpAccessToken" + corpAccessToken);
        //获取用户userid。
        OapiV2UserGetuserinfoResponse userUnfo = dingAuthTokenService.getUserUnfo(code, corpAccessToken);
        System.out.println("用户登录信息" + JSONObject.toJSONString(userUnfo));
        //调用接口获取用户的userid，详情请参考通过免登码获取用户信息。
        OapiV2UserGetResponse authUser = dingAuthTokenService.getAuthUser(corpAccessToken, userUnfo.getResult().getUserid());
        System.out.println("用户登录详细信息" + JSONObject.toJSONString(authUser.getResult()));

//        GetUserResponse addressBookUserInfo = dingAuthTokenService.getAddressBookUserInfo(corpAccessToken, "me");
//        log.info("用户通讯录信息" + JSONObject.toJSONString(addressBookUserInfo));

        //查询租户
        TenantDO tenant = tenantService.getTenantByCorpId(corpId);
        if (tenant == null || tenant.getId() == null) {
            throw exception(TENANT_NOT_EXISTS);
        }
        //todo 获取用户详情。查询是否存在
        AdminUserDO adminUserDO = userService.getUserByUserIdAndCorpId(userUnfo.getResult().getUserid(), tenant.getId());
        if (Objects.isNull(adminUserDO)) {
            // todo 初始化用户

            OapiV2UserGetResponse.UserGetResponse result = authUser.getResult();
            //创建用户信息
            UserSaveReqVO userSaveReqVO = new UserSaveReqVO();
            userSaveReqVO.setUsername(authUser.getResult().getUserid());
            userSaveReqVO.setNickname(result.getName());
            userSaveReqVO.setEmail(result.getEmail());
            userSaveReqVO.setMobile(result.getMobile());
            userSaveReqVO.setRemark(result.getRemark());
            userSaveReqVO.setAvatar(result.getAvatar());
            userSaveReqVO.setPassword(result.getMobile());

            adminUserDO = dingAuthServiceInfo.initUser(userSaveReqVO, corpId,true);
        }
        TenantContextHolder.setTenantId(tenant.getId());
        adminUserDO.setTenantId(tenant.getId());
        return success(authService.DDinglogin(adminUserDO),tenant.getId().toString());
    }

    @Operation(summary = "用户向企业管理员提交授权申请")
    @PostMapping("/cropAuth/apply")
    @ResponseBody
    public CommonResult<String> cropAuthApply() {
//        LoginUser loginUser = SecurityUtils.getLoginUser();
//        String roles = "tentant_admin,hr";
//        boolean hasAnyRoles = permissionService.hasAnyRoles(roles);
//        if (hasAnyRoles) {
//            AjaxResult.error("您已具备该企业权限，无需再次申请");
//        }
//        authApplyService.applyAuth(loginUser.getUser());
        return success("申请成功，请等待管理员审核");
    }

//    @Operation(summary = "用户向企业管理员提交授权申请列表")
//    @GetMapping("/cropAuth/apply/page")
//    @ResponseBody
//    public TableDataInfo cropAuthApplyPage() {
//        startPage();
//        LoginUser loginUser = SecurityUtils.getLoginUser();
//        List<AuthApply> list = authApplyService.applyAuthList(0, loginUser.getUser().getCorpId());
//        return getDataTable(list);
//    }

    @Operation(summary = "管理员审批用户授权申请")
    @PostMapping("/cropAuth/complete")
    @ResponseBody
    public CommonResult<String> cropAuthComplete(Long id, Boolean flag) {
//        LoginUser loginUser = SecurityUtils.getLoginUser();
//        authApplyService.applyComplete(id, flag, loginUser.getUserId());
        return success("成功");
    }

    @Operation(summary = "管理员给用户开通企业权限")
    @PostMapping("/cropAuth/liberal")
    @ResponseBody
    public CommonResult<String> cropAuthLiberal(String[] empIds) {
//        LoginUser loginUser = SecurityUtils.getLoginUser();
//        SysRole role = sysRoleService.selectRoleByKey("hr");
//        Long[] roleIds = new Long[1];
//        roleIds[0] = role.getRoleId();
//        for (String empId : empIds) {
//            SysUser sysUser = userMapper.selectByEmployNoAndCorpId(empId, loginUser.getCorpid());
//            if (sysUser == null) {
//                //查询不到用户证明 该员工还未登录，先由管理员赋予hr角色
//                sysUser = new SysUser();
//                sysUser.setEmployNo(empId);
//                sysUser.setCorpId(loginUser.getCorpid());
//                sysUser.setCreateBy(loginUser.getUser().getUserId().toString());
//                sysUser.setCreateTime(new Date());
//                userMapper.insertUser(sysUser);
//
//                SysUserRole userRole = new SysUserRole();
//                userRole.setUserId(sysUser.getUserId());
//                userRole.setRoleId(role.getRoleId());
//                sysUserService.insertUserAuth(sysUser.getUserId(), roleIds);
//            } else {
//                //有用户信息 设置他的角色为hr
//                SysUserRole userRole = new SysUserRole();
//                userRole.setUserId(sysUser.getUserId());
//                userRole.setRoleId(role.getRoleId());
//                sysUserService.insertUserAuth(sysUser.getUserId(), roleIds);
//            }
//        }
//        return AjaxResult.success();
        return success("成功");
    }

}