package org.dromara.resource.dubbo;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.common.core.enums.SmsType;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.resource.api.RemoteFileService;
import org.dromara.resource.api.RemoteSmsService;
import org.dromara.resource.api.RemoteWeiXinService;
import org.dromara.resource.api.domain.RemoteFile;
import org.dromara.resource.api.domain.RemoteSms;
import org.dromara.resource.domain.SysSms;
import org.dromara.resource.mapper.SysSmsMapper;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.provider.enumerate.SupplierType;
import org.dromara.sms4j.tencent.config.TencentConfig;
import org.dromara.system.api.RemoteConfigService;
import org.dromara.system.api.domain.RemoteSysUnitDomainVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 微信服务
 *
 * @author Lion Li
 */
@Slf4j
//@RequiredArgsConstructor
@Service
@DubboService
public class RemoteWeiXinServiceImpl implements RemoteWeiXinService {

    @Resource(name="remoteFileServiceImpl")
    private  RemoteFileService remoteFileService;

    @DubboReference
    private RemoteConfigService remoteConfigService;

    @Override
    public String genPubAuthQrcode(String domain,String redirectUri) throws ServiceException {
        RemoteSysUnitDomainVo site = remoteConfigService.queryByDomainName(domain);
        if(site == null || StringUtils.isBlank(site.getWxPubConfig())){
            throw new ServiceException("不支持微信登录");
        }
        JSONObject weixinConfig = JSONObject.parseObject(site.getWxPubConfig());
        String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+weixinConfig.getString("appid")+"&redirect_uri="+ URLEncodeUtil.encodeAll(redirectUri) +"&response_type=code&scope=snsapi_base&state=123#wechat_redirect";
        byte[] data = null;
        String format = "png";
        try {
            Map<EncodeHintType, Object> hints = new HashMap<>(3);
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 0);

            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix bitMatrix = writer.encode(authUrl, BarcodeFormat.QR_CODE, 300, 300,hints);
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            MatrixToImageWriter.writeToStream(bitMatrix, format, outStream);
            data = outStream.toByteArray();
        } catch (WriterException e) {
            throw new ServiceException("二维码生成失败");
        } catch (IOException e) {
            throw new ServiceException("二维码生成失败");
        }
        String fileName = UUID.fastUUID().toString() + "." + format;
        RemoteFile oss = remoteFileService.upload(fileName, fileName, "image/png", data);
        return oss.getUrl();
    }

    @Override
    public String getOpenId(String domain, String code) {
        RemoteSysUnitDomainVo site = remoteConfigService.queryByDomainName(domain);
        if(site == null || StringUtils.isBlank(site.getWxPubConfig())){
            throw new ServiceException("不支持微信登录");
        }
        try {
            JSONObject weixinConfig = JSONObject.parseObject(site.getWxPubConfig());
            String json = HttpUtil.get("https://api.weixin.qq.com/sns/oauth2/access_token?appid="+weixinConfig.getString("appid")+"&secret="+weixinConfig.getString("appkey")+"&code="+code+"&grant_type=authorization_code", StandardCharsets.UTF_8);
            log.info("获取授权用户的微信openid：（"+weixinConfig.getString("appid")+"）"+json);
            JSONObject rtn = JSONObject.parseObject(json);
            if(rtn.containsKey("openid")){
                return rtn.getString("openid");
            }
        } catch (Exception e) {
            log.error("获取授权用户的微信openid出错：（"+domain+","+code+"）",e);
        }
        return null;
    }
}
