package cn.hanghui.outapi.platform.xinghuo.service.impl;

import cn.hanghui.outapi.platform.common.config.CacheConfig;
import cn.hanghui.outapi.platform.xinghuo.constant.XinghuoRespCode;
import cn.hanghui.outapi.platform.xinghuo.entity.dto.GetProofByQrCodeDto;
import cn.hanghui.outapi.platform.xinghuo.service.XinghuoApiService;
import cn.hanghui.outapi.platform.common.exception.CommonException;
import cn.hanghui.outapi.platform.xinghuo.api.XinghuoQrCodeApi;
import cn.hanghui.outapi.platform.xinghuo.entity.dto.ApplyProofDto;
import cn.hanghui.outapi.platform.xinghuo.entity.dto.GetQrCodeDto;
import cn.hanghui.outapi.platform.xinghuo.entity.param.*;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.qrcode.BufferedImageLuminanceSource;
import com.alibaba.fastjson.JSONObject;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Base64;
import java.util.Hashtable;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@AllArgsConstructor(onConstructor_ = @Autowired)
public class XinghuoApiServiceImpl implements XinghuoApiService {

    private final XinghuoQrCodeApi xinghuoQrcodeApi;

    private final RedisTemplate<Object, Object> redisTemplate;

    /**
     * 申请凭证
     *
     * @param applyProofDto ApplyProofDto
     * @return ApplyProofApiResult
     */
    @Override
    public ApplyProofApiResult applyProof(ApplyProofDto applyProofDto) {
        ApplyProofApiParam applyProofApiParam = new ApplyProofApiParam();
        applyProofApiParam.setIdCardNo(applyProofDto.getSfzh());
        StringBuilder addr = new StringBuilder();
        if (ObjectUtil.isNotEmpty(applyProofDto.getProvince())) {
            addr.append(applyProofDto.getAddr());
        }
        if (ObjectUtil.isNotEmpty(applyProofDto.getCity())) {
            addr.append(applyProofDto.getCity());
        }
        if (ObjectUtil.isNotEmpty(applyProofDto.getCounty_area())) {
            addr.append(applyProofDto.getCounty_area());
        }
        if (ObjectUtil.isNotEmpty(applyProofDto.getAddr())) {
            addr.append(applyProofDto.getAddr());
        }
        applyProofApiParam.setAddress(addr.toString());
        applyProofApiParam.setName(applyProofDto.getXm());
        applyProofApiParam.setNation(applyProofDto.getNation());
        applyProofApiParam.setPhone(applyProofDto.getPhone());
        applyProofApiParam.setPhoto(applyProofDto.getScene_xp());
        // 优先从缓存中获取凭证
        ApplyProofApiResult applyProofApiResult = (ApplyProofApiResult) redisTemplate.opsForValue().get(CacheConfig.APPLY_PROOF_CACHE_PREFIX + applyProofApiParam.getIdCardNo());
        if (ObjectUtil.isNotNull(applyProofApiResult)) {
            log.info("-->redis中获取数据:{}", JSONObject.toJSONString(applyProofApiResult));
            // 若缓存中的凭证有二维码信息则直接返回
            if (ObjectUtil.isNotEmpty(applyProofApiResult.getQrcode())) {
                //不做处理直接返回
            } else {
                //二维码不存在 获取二维码
                applyProofApiResult = handleQrCode(applyProofApiParam.getIdCardNo());
            }
        } else {
            // 缓存中没数据则调用申请凭证
            // 调用申请凭证
            XinghuoApiResp<ApplyProofApiResult> result = xinghuoQrcodeApi.applyProof(applyProofApiParam);
            log.info("-->申请凭证接口返回:{}", JSONObject.toJSONString(result));
            if (!XinghuoRespCode.SUCCESS.code.equals(result.getStatus()) && !XinghuoRespCode.EXIST.code.equals(result.getStatus())) {
                throw new CommonException(result.getMsg());
            }
            applyProofApiResult = result.getRows();
            //成功/已存在或二维码为空时 调用获取二维码
            if (XinghuoRespCode.SUCCESS.code.equals(result.getStatus()) || XinghuoRespCode.EXIST.code.equals(result.getStatus())) {
                applyProofApiResult = handleQrCode(applyProofApiParam.getIdCardNo());
            }
        }
        log.info("--->申请凭证接口最终响应数据:{}", JSONObject.toJSONString(applyProofApiResult));
        return applyProofApiResult;
    }

    private ApplyProofApiResult handleQrCode(String idCard) {
        ApplyProofApiResult applyProofApiResult = new ApplyProofApiResult();
        GetQrCodeDto getQrCodeDto = new GetQrCodeDto();
        getQrCodeDto.setIdCardNo(idCard);
        GetQrCodeApiResult qrCodeApiResult = getQrCode(getQrCodeDto);
        if (qrCodeApiResult == null || qrCodeApiResult.getQrCode() == null) {
            throw new CommonException("二维码获取失败");
        }
        applyProofApiResult.setQrcode(qrCodeApiResult.getQrCode());
        applyProofApiResult.setIsFocusOnPeople(qrCodeApiResult.getIsFocusOnPeople());
        applyProofApiResult.setValidTime(qrCodeApiResult.getValidTime());
        return applyProofApiResult;
    }


    /**
     * 获取凭证二维码
     *
     * @param getQrCodeDto GetQrCodeDto
     * @return GetQrCodeApiResult
     */
    @Override
    public GetQrCodeApiResult getQrCode(GetQrCodeDto getQrCodeDto) {
        GetQrCodeApiParam getQrCodeApiParam = BeanUtil.copyProperties(getQrCodeDto, GetQrCodeApiParam.class);
        GetQrCodeApiResult result = xinghuoQrcodeApi.getQrCode(getQrCodeApiParam);
        try {
            InputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(result.getQrCode()));
            BufferedImage image = ImageIO.read(inputStream);
            BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(
                    image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            Result imgResult;
            Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
            //精度
            hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
            //复杂模式
            hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
            hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
            imgResult = new MultiFormatReader().decode(bitmap, hints);
            String qrcodeText = imgResult.getText();
            result.setQrCode(qrcodeText);
            ApplyProofApiResult applyProofApiResult = new ApplyProofApiResult();
            applyProofApiResult.setQrcode(result.getQrCode());
            applyProofApiResult.setIsFocusOnPeople(result.getIsFocusOnPeople());
            applyProofApiResult.setValidTime(result.getValidTime());
            DateTime validTime = DateUtil.parse(applyProofApiResult.getValidTime());
            redisTemplate.opsForValue()
                    .set(CacheConfig.APPLY_PROOF_CACHE_PREFIX + getQrCodeDto.getIdCardNo(),
                            applyProofApiResult,
                            validTime.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            throw new CommonException("二维码解析失败", e);
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
//        String qrcode = " ";
//        String qrcode = "iVBORw0KGgoAAAANSUhEUgAAAMgAAADIAQAAAACFI5MzAAABIElEQVR42u2YQbKEIAxEw4pjcFOFm3IMVvA7HbXGKWf7k4UUWspjEZN0SCnr15CXvOSfSRWM0kaZUtbQlxSGNFyj1IyHvo9yrAQhQxLJzEoqviAYwX23LfEInAqrwxFGG5n4Iw88yaUSzkf9uBEbEyvIxIe640mgj6p1hXP17eN73AkXMLroFtnyFW1/Al+mIRvv++pp0a8xiGZfhiOLaWXetO1MFoXbLAGp4xSGaOVjPsK1G6O9whA9ZkXjbPqotxz1JizDZjV5WWGIlRYSNT+N0sKQT8Pbt0ediZ1m0+yl+SsMObtOrXnpFE0UMo4I81hDFbxpOwK50pDmByNUsFDEexxydp3q0dzloSN2I0fXqdGGvehTegpD3v8HL/Enf4/zCA9y/AqQAAAAAElFTkSuQmCC";
        String qrcode = "iVBORw0KGgoAAAANSUhEUgAAAMgAAADIAQAAAACFI5MzAAABIElEQVR42u2YOxLDIAxEodIxuCmfm3IMKhNphR0nnrSRCjTEQ/xSrAUrFIf5K8Imm/yZ1MCRjpDmCHHIl+iGNP6MxNdKPY607jghIpZVQ+xINSRvpGFSXJJztZ2RM5GVZPLYB5ZEXdKGjqd/LInGQcsrj7pjSVg1iko6qAfqmXrxQ0gG347yq1O4D9JmzyxaMsoOXm52Qg7SAdXM55VRe8JTFp0BofrmEmtSZev1AL243vaBNeHVXsUYpYWjOCIow5Asy/7RoVgTFONMa9njvUOxJhpN7Xs9hA9ynWaSSyktPboh2gXAvtp73lxiTrQSXy0AmhRXpEpnl1Ck3xl1QlZetY3yQ85/ObwTceT24oYsl6A841j79o8h2e8PNrEnL5SoG606fWD4AAAAAElFTkSuQmCC";
        InputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(qrcode));
        BufferedImage image = ImageIO.read(inputStream);
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(
                image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Result imgResult;
        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
        //精度
        hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
        //复杂模式
        hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
        hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
        imgResult = new MultiFormatReader().decode(bitmap, hints);
        String qrcodeText = imgResult.getText();
        System.out.println(qrcodeText);
    }

    /**
     * 根据二维码获取凭证信息
     *
     * @param getProofByQrCodeDto GetProofByQrCodeDto
     * @return GetProofByQrCodeApiResult
     */
    @Override
    public GetProofByQrCodeApiResult getProofByQrCode(GetProofByQrCodeDto getProofByQrCodeDto) {
        GetProofByQrCodeApiParam getProofByQrCodeApiParam = BeanUtil.copyProperties(getProofByQrCodeDto, GetProofByQrCodeApiParam.class);
        GetProofByQrCodeApiResult result;
        try {
            result = xinghuoQrcodeApi.getProofByQrCode(getProofByQrCodeApiParam);
            return result;
        } catch (Exception e) {
            result = xinghuoQrcodeApi.getProofByMiniAppletQrCode(getProofByQrCodeApiParam);
        }
        return result;
    }
}
