package com.starry.admin.modules.weichat.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.starry.admin.common.aspect.ClerkUserLogin;
import com.starry.admin.common.aspect.CustomUserLogin;
import com.starry.admin.common.conf.ThreadLocalRequestDetail;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
import com.starry.admin.modules.weichat.entity.WxUserLoginVo;
import com.starry.admin.modules.weichat.entity.WxUserQueryAddressVo;
import com.starry.admin.modules.weichat.service.WxCustomMpService;
import com.starry.admin.modules.weichat.service.WxOauthService;
import com.starry.admin.modules.weichat.service.WxTokenService;
import com.starry.common.redis.RedisCache;
import com.starry.common.result.R;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Date;

import static com.starry.common.constant.Constants.*;

/**
 * 微信用户
 *
 * @author admin
 * @since 2019-03-25 15:39:39
 */
@Slf4j
@RestController
@RequestMapping("/wx/oauth2")
public class WxOauthController {


    @Resource
    private WxCustomMpService wxCustomMpService;
    @Resource
    private IPlayCustomUserInfoService customUserInfoService;
    @Resource
    private IPlayClerkUserInfoService clerkUserInfoService;
    @Resource
    private WxTokenService tokenService;
    @Resource
    private WxOauthService wxOauthService;
    @Resource
    private RedisCache redisCache;


    @PostMapping("/getConfigAddress")
    public R getConfigAddress(@RequestBody WxUserQueryAddressVo vo) throws WxErrorException {
        // 默认回调地址
        String defaultAddress = "http://july.hucs.top/api/wx/oauth2/clerkLoginCallback";
        if (!StrUtil.isBlankIfStr(vo.getUrl())) {
            defaultAddress = vo.getUrl();
        }
        WxJsapiSignature wxJsapiSignature = wxCustomMpService.proxyWxMpService().createJsapiSignature(defaultAddress);
        return R.ok(wxJsapiSignature);
    }

    @PostMapping("/getClerkLoginAddress")
    public R getClerkLoginAddress(@RequestBody WxUserQueryAddressVo vo) {
        // 默认回调地址
        String defaultAddress = "http://july.hucs.top/api/wx/oauth2/clerkLoginCallback";
        if (!StrUtil.isBlankIfStr(vo.getUrl())) {
            defaultAddress = vo.getUrl();
        }
        String url = wxCustomMpService.proxyWxMpService().getOAuth2Service().buildAuthorizationUrl(defaultAddress, "snsapi_userinfo", "STATE");
        return R.ok(url);
    }


    @GetMapping("/clerkLoginCallback")
    public void clerkLoginCallback(@RequestParam("code") String code) {
    }


    @PostMapping("/clerk/login")
    public R clerkLogin(@Validated @RequestBody WxUserLoginVo vo) {
        try {
            String userId = wxOauthService.clerkUserLogin(vo.getCode());
            PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(userId);
            if (entity == null) {
                throw new CustomException("用户不存在");
            }
            // 缓存租户信息
            String redisKey = "TENANT_INFO:" + entity.getId();
            redisCache.setCacheObject(redisKey, entity.getTenantId());
            String tokenValue = tokenService.createWxUserToken(entity.getId());
            JSONObject jsonObject = JSONObject.from(clerkUserInfoService.getVo(entity));
            jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue);
            jsonObject.put("tokenName", CLERK_USER_LOGIN_TOKEN);
            jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            jsonObject.put("pcData", clerkUserInfoService.getPcData(entity));
            clerkUserInfoService.updateTokenById(entity.getId(), tokenValue);
            return R.ok(jsonObject);
        } catch (Exception e) {
            log.error("顾客登录失败，", e);
            return R.unauthorized();
        }
    }

    @PostMapping("/clerk/login/dev")
    public R clerkLoginDev(@Validated @RequestBody WxUserLoginVo vo) {
        try {
            String userId = "a4471ef596a1";
            PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(userId);
            if (entity == null) {
                throw new CustomException("用户不存在");
            }
            // 缓存租户信息
            String redisKey = "TENANT_INFO:" + entity.getId();
            redisCache.setCacheObject(redisKey, entity.getTenantId());
            String tokenValue = tokenService.createWxUserToken(entity.getId());
            JSONObject jsonObject = JSONObject.from(clerkUserInfoService.getVo(entity));
            jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue);
            jsonObject.put("tokenName", CLERK_USER_LOGIN_TOKEN);
            jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            jsonObject.put("pcData", clerkUserInfoService.getPcData(entity));
            clerkUserInfoService.updateTokenById(entity.getId(), tokenValue);
            return R.ok(jsonObject);
        } catch (Exception e) {
            log.error("顾客登录失败，", e);
            return R.unauthorized();
        }
    }

    @PostMapping("/clerk/loginById")
    public R loginById(@Validated @RequestBody WxUserLoginVo vo) {
        PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(vo.getCode());
        if (entity == null) {
            throw new CustomException("用户不存在");
        }
        // 缓存租户信息
        String redisKey = "TENANT_INFO:" + entity.getId();
        redisCache.setCacheObject(redisKey, entity.getTenantId());
        JSONObject jsonObject = JSONObject.from(clerkUserInfoService.getVo(entity));
        String tokenValue = tokenService.createWxUserToken(entity.getId());
        jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue);
        jsonObject.put("tokenName", CLERK_USER_LOGIN_TOKEN);
        jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        clerkUserInfoService.updateTokenById(entity.getId(), tokenValue);
        return R.ok(jsonObject);
    }

    @ClerkUserLogin
    @GetMapping("/clerk/logout")
    public R clerkLogout() {
        wxOauthService.clerkUserLogout(ThreadLocalRequestDetail.getClerkUserInfo());
        return R.ok("登出成功");
    }


    @PostMapping("/getCustomLoginAddress")
    public R getCustomLoginAddress(@RequestBody WxUserQueryAddressVo vo) {
        // 默认回调地址
        String defaultAddress = "http://july.hucs.top/api/wx/oauth2/customLoginCallback";
        if (!StrUtil.isBlankIfStr(vo.getUrl())) {
            defaultAddress = vo.getUrl();
        }
        String url = wxCustomMpService.proxyWxMpService().getOAuth2Service().buildAuthorizationUrl(defaultAddress, "snsapi_userinfo", "STATE");
        return R.ok(url);
    }

    @GetMapping("/customLoginCallback")
    public void customLoginCallback(@RequestParam("code") String code) {

    }


    @PostMapping("/custom/login")
    public R customLogin(@Validated @RequestBody WxUserLoginVo vo) {
        log.info("顾客登录接口调用，code = {}", vo.getCode());
        try {
            String userId = wxOauthService.customUserLogin(vo.getCode());
            PlayCustomUserInfoEntity entity = customUserInfoService.selectById(userId);
            if (entity == null) {
                throw new CustomException("用户不存在");
            }
            // 缓存租户信息
            String redisKey = "TENANT_INFO:" + entity.getId();
            redisCache.setCacheObject(redisKey, entity.getTenantId());
            JSONObject jsonObject = JSONObject.from(entity);
            String tokenValue = tokenService.createWxUserToken(entity.getId());
            jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue);
            jsonObject.put("tokenName", CUSTOM_USER_LOGIN_TOKEN);
            jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            customUserInfoService.updateTokenById(entity.getId(), tokenValue);
            return R.ok(jsonObject);
        } catch (Exception e) {
            log.error("登录失败", e);
            return R.unauthorized();
        }
    }

    @PostMapping("/custom/loginById")
    public R loginById1(@Validated @RequestBody WxUserLoginVo vo) {
        PlayCustomUserInfoEntity entity = customUserInfoService.selectById(vo.getCode());
        if (entity == null) {
            throw new CustomException("用户不存在");
        }
        // 缓存租户信息
        String redisKey = "TENANT_INFO:" + entity.getId();
        redisCache.setCacheObject(redisKey, entity.getTenantId());
        JSONObject jsonObject = JSONObject.from(entity);
        String tokenValue = tokenService.createWxUserToken(entity.getId());
        jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue);
        jsonObject.put("tokenName", CLERK_USER_LOGIN_TOKEN);
        jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        customUserInfoService.updateTokenById(entity.getId(), tokenValue);
        return R.ok(jsonObject);
    }


    @GetMapping("/custom/logout")
    @CustomUserLogin
    public R customLogout() {
        wxOauthService.customUserLogout(ThreadLocalRequestDetail.getCustomUserInfo());
        return R.ok("登出成功");
    }

}
