package cn.sikey.mcdisk.service;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.sikey.framework.common.exception.ServiceException;
import cn.sikey.framework.common.pojo.CommonResult;
import cn.sikey.mcdisk.config.McdiskConfig;
import cn.sikey.mcdisk.controller.app.authorizephoto.vo.QueryOauthPhotoByDeviceIdRespVO;
import cn.sikey.mcdisk.controller.app.wristwatch.vo.*;
import cn.sikey.mcdisk.convert.OauthConvert;
import cn.sikey.mcdisk.dal.dataobject.AuthorizeDO;
import cn.sikey.mcdisk.dal.mysql.AuthorizeMapper;
import cn.sikey.mcdisk.entity.NotifyParentsSuccessfulActivationMessage;
import cn.sikey.mcdisk.enums.*;
import cn.sikey.mcdisk.feign.ApiMessageFeignService;
import cn.sikey.mcdisk.pojo.McdiskResult;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Objects;

/**
 * @Author: nelson
 * @Date: 2025/5/30
 * @Description: 授权
 */
@Service
@Slf4j
public class AuthorizeServiceImpl extends AbstractMcdiskService implements AuthorizeService {

    @Resource
    private FamilyCloudService familyCloudService;

    @Resource
    private AuthorizeMapper authorizeMapper;

    @Resource
    private McdiskConfig mcdiskConfig;

    @Resource
    private AuthorizePhotoService authorizePhotoService;

    private static final String MY_FAMILY_CLOUD = "我的家庭云";

    @Resource
    private MessageIdIncrementingService<Long> messageIdIncrementingService;

    @Resource
    private ApiMessageFeignService apiMessageFeignService;

    /**
     * 设备授权
     *
     * @param oauthReqVO  授权
     * @param accessToken accessToken
     * @return
     */
    private CommonResult oauth(OauthReqVO oauthReqVO, String accessToken) {
        // ticket
        String ticket = oauthReqVO.getTicket();

        // 创建家庭云
        String cloudName = oauthReqVO.getCloudName();
        McdiskResult mcdiskResult = familyCloudService.createFamilyCloud(cloudName, oauthReqVO.getAccountType(), ticket, accessToken);

        // 创建家庭云相册
        String cloudID = JSONUtil.parseObj(JSONUtil.toJsonStr(mcdiskResult.getData())).getStr("cloudID");
        Integer theme = 0;
        String photoName = oauthReqVO.getPhotoName();
        mcdiskResult = familyCloudService.createCloudPhoto(cloudID, theme, photoName, ticket, accessToken);
        String photoID = JSONUtil.parseObj(JSONUtil.toJsonStr(mcdiskResult.getData())).getStr("photoID");
        // 更新设备授权
        AuthorizeDO authorizeDO = new AuthorizeDO();
        authorizeDO.setDeviceId(ticket);
        authorizeDO.setCloudId(cloudID);
        authorizeDO.setPhotoId(photoID);
        authorizeDO.setUpdater(ticket);
        authorizeDO.setAuthorizeStatus(IsAuthorizeEnum.AUTHORIZED.getValue());
        authorizeDO.setUpdateTime(LocalDateTime.now());
        authorizeDO.setAccessToken(accessToken);
        authorizeMapper.updateAuthorizeByDeviceId(authorizeDO);

        QueryOauthPhotoByDeviceIdRespVO queryOauthPhotoByDeviceIdRespVO = authorizePhotoService.queryOauthPhotoByDeviceId(ticket);
        String userId = "";
        if (Objects.nonNull(queryOauthPhotoByDeviceIdRespVO)) {
            userId = queryOauthPhotoByDeviceIdRespVO.getUserId();
        }
        // 推送
        NotifyParentsSuccessfulActivationMessage request = new NotifyParentsSuccessfulActivationMessage();
        request.setMsgId(messageIdIncrementingService.incr());
        request.setMsgType(MessageType.NOTIFY_PARENTS_SUCCESSFUL_ACTIVATION);
        request.setSendId(ticket);
        request.setRecvId(userId);
        request.setSendTime(Instant.now().toEpochMilli());
        NotifyParentsSuccessfulActivationMessage.Content content = new NotifyParentsSuccessfulActivationMessage.Content();
        content.setTicket(ticket);
        request.setContent(content);
        apiMessageFeignService.notifyParentsSuccessfulActivation(request);

        log.info("[授权]更新设备授权数据成功");

        return CommonResult.success();
    }

    /**
     * 查询设备认证
     *
     * @param deviceId 设备编码
     * @return
     */
    public AuthorizeRespVO queryOauth(String deviceId) {
        AuthorizeDO authorizeDO = authorizeMapper.queryAuthorize(deviceId);
        log.info("[查询设备认证]返回数据：{}", JSONUtil.toJsonStr(authorizeDO));
        if (Objects.isNull(authorizeDO)) {
            throw new ServiceException(CodeStatusEnum.NOT_ACTIVATED.getCode(), CodeStatusEnum.NOT_ACTIVATED.getDescription());
        }
        AuthorizeRespVO authorizeRespVO = OauthConvert.INSTANCE.convertOauthRespVO(authorizeDO);
        return authorizeRespVO;
    }

    /**
     * 中间页接入方式获取用户凭证oauth2/accessToken1
     *
     * @param accessToken1ReqVO accessToken
     * @return
     */
    @Override
    public CommonResult accessToken1(AccessToken1ReqVO accessToken1ReqVO) {
        // 准备请求参数
        String apiUrl = mcdiskConfig.getPath() + ApiEndpointsEnum.ACCESS_TOKEN1.getPath();

        String deviceId = accessToken1ReqVO.getTicket();
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("uuid", accessToken1ReqVO.getUuid());
        String jsonBody = jsonObject.toString();

        // 发送请求
        McdiskResult mcdiskResult = getMcdiskResult(apiUrl, jsonBody, null);
        log.info("[中间页接入方式获取用户凭证oauth2/accessToken1]返回数据：{}", mcdiskResult);

        JSONObject jo = JSONUtil.parseObj(JSONUtil.toJsonStr(mcdiskResult.getData()));
        String accessToken = jo.getStr("accessToken");
        int expiresIn = jo.getStr("expiresIn") == null ? 0 : jo.getInt("expiresIn");

        myTaskExecutor.execute(() -> {
            AuthorizeDO authorizeDO = authorizeMapper.queryAuthorize(deviceId);
            if (Objects.isNull(authorizeDO)) {
                // 保存设备授权
                authorizeDO = new AuthorizeDO();
                authorizeDO.setDeviceId(deviceId);
                authorizeDO.setAccessToken(accessToken);

                // 授权accessToken过期时间
                authorizeDO.setExpireTime(LocalDateTime.now().plusHours(expiresIn));
                authorizeDO.setAuthorizeStatus(IsAuthorizeEnum.AUTHORIZED.getValue());
                authorizeDO.setCreator(deviceId);
                authorizeDO.setUpdater(deviceId);
                authorizeMapper.insert(authorizeDO);
            } else {
                authorizeDO.setAccessToken(accessToken);
                // 授权accessToken过期时间
                authorizeDO.setExpireTime(LocalDateTime.now().plusHours(expiresIn));
                authorizeDO.setAuthorizeStatus(IsAuthorizeEnum.AUTHORIZED.getValue());
                authorizeDO.setUpdater(deviceId);
                authorizeDO.setUpdateTime(LocalDateTime.now());
                authorizeMapper.updateAuthorizeTokenByDeviceId(authorizeDO);
            }

            // 家庭云，相册云
            QueryOauthPhotoByDeviceIdRespVO queryOauthPhotoByDeviceIdRespVO = authorizePhotoService.queryOauthPhotoByDeviceId(deviceId);
            String photoName = "";
            if (Objects.nonNull(queryOauthPhotoByDeviceIdRespVO)) {
                photoName = queryOauthPhotoByDeviceIdRespVO.getNickName() + "-" + queryOauthPhotoByDeviceIdRespVO.getDeviceName();

            }

            // 手表授权获取云id，相册id
            OauthReqVO oauthReqVO = new OauthReqVO();
            oauthReqVO.setAccountType(AccountTypeEnum.PHONE_NUMBER.getValue());
            oauthReqVO.setTicket(accessToken1ReqVO.getTicket());
            oauthReqVO.setCloudName(photoName);
            oauthReqVO.setPhotoName(photoName);
            oauth(oauthReqVO, accessToken);

        });

        return CommonResult.success(mcdiskResult.getData());
    }

    /**
     * 刷新Token oauth2/refreshToken
     *
     * @param refreshTokenReqVO refreshTokenReqVO
     * @return
     */
    @Override
    public CommonResult refreshToken(RefreshTokenReqVO refreshTokenReqVO) {
        // 准备请求参数
        String apiUrl = mcdiskConfig.getPath() + ApiEndpointsEnum.REFRESH_TOKEN.getPath();

        JSONObject jsonObject = new JSONObject();
        jsonObject.set("appId", mcdiskConfig.getAppid());
        jsonObject.set("appSecret", mcdiskConfig.getSecretkey());
        jsonObject.set("refreshToken", refreshTokenReqVO.getRefreshToken());
        String jsonBody = jsonObject.toString();

        // 发送请求
        McdiskResult mcdiskResult = getMcdiskResult(apiUrl, jsonBody, null);
        log.info("[刷新Token oauth2/refreshToken]返回数据：{}", mcdiskResult);

        JSONObject jo = JSONUtil.parseObj(JSONUtil.toJsonStr(mcdiskResult.getData()));
        String accessToken = jo.getStr("accessToken");
        int expiresIn = jo.getStr("expiresIn") == null ? 0 : jo.getInt("expiresIn");

        myTaskExecutor.execute(() -> {
            String ticket = refreshTokenReqVO.getTicket();
            // 刷新Token
            AuthorizeDO authorizeDO = new AuthorizeDO();
            authorizeDO.setDeviceId(ticket);
            authorizeDO.setAccessToken(accessToken);
            authorizeDO.setExpireTime(LocalDateTime.now().plusHours(expiresIn));
            authorizeDO.setAuthorizeStatus(IsAuthorizeEnum.AUTHORIZED.getValue());
            authorizeDO.setUpdater(ticket);
            authorizeDO.setUpdateTime(LocalDateTime.now());
            authorizeMapper.updateAuthorizeTokenByDeviceId(authorizeDO);
        });

        return CommonResult.success(mcdiskResult.getData());
    }

    /**
     * 查询设备授权
     *
     * @param deviceId 设备编码
     * @return
     */
    @Override
    public AuthorizeRespVO queryAuthorize(String deviceId) {
        AuthorizeDO authorizeDO = authorizeMapper.queryAuthorize(deviceId);
        AuthorizeRespVO authorizeRespVO = OauthConvert.INSTANCE.convertOauthRespVO(authorizeDO);
        return authorizeRespVO;
    }

    /**
     * 更新设备授权状态
     *
     * @param deviceId        设备id
     * @param authorizeStatus 手表状态
     * @return
     */
    @Override
    public void updateAuthorizeByDeviceId(String deviceId, Integer authorizeStatus) {
        AuthorizeDO authorizeDO = new AuthorizeDO();
        authorizeDO.setDeviceId(deviceId);
        authorizeDO.setAuthorizeStatus(authorizeStatus);
        authorizeDO.setUpdater(deviceId);
        authorizeDO.setUpdateTime(LocalDateTime.now());
        authorizeMapper.updateAuthorizeStatusByDeviceId(authorizeDO);
    }

    /**
     * 通知家长授权
     *
     * @param notifyParentsAuthorizationReqVO 通知家长授权
     * @return
     */
    @Override
    public void notifyParentsAuthorization(NotifyParentsAuthorizationReqVO notifyParentsAuthorizationReqVO) {
        String ticket = notifyParentsAuthorizationReqVO.getTicket();

        // 推送
        NotifyParentsSuccessfulActivationMessage request = new NotifyParentsSuccessfulActivationMessage();
        request.setMsgId(messageIdIncrementingService.incr());
        request.setMsgType(MessageType.NOTIFY_PARENTS_AUTHORIZATION);
        request.setSendId(ticket);
        request.setRecvId(notifyParentsAuthorizationReqVO.getUserId());
        request.setSendTime(Instant.now().toEpochMilli());
        NotifyParentsSuccessfulActivationMessage.Content content = new NotifyParentsSuccessfulActivationMessage.Content();
        content.setTicket(ticket);
        request.setContent(content);
        apiMessageFeignService.notifyParentsAuthorization(request);
    }

    /**
     * 更新设备授权accessToken
     *
     * @param deviceId 设备id
     * @return
     */
    @Override
    public void updateAuthorizeAccessTokenByDeviceId(String deviceId) {
        authorizeMapper.updateAuthorizeAccessTokenByDeviceId(deviceId);
    }
}
