package cn.wisenergy.service.app.impl;

import cn.wisenergy.common.constant.CommonAttributes;
import cn.wisenergy.common.utils.DateUtil;
import cn.wisenergy.common.utils.R;
import cn.wisenergy.common.utils.StringUtil;
import cn.wisenergy.mapper.AntiFakeMapper;
import cn.wisenergy.mapper.ProductMapper;
import cn.wisenergy.model.app.AntiFake;
import cn.wisenergy.model.app.ProductInfo;
import cn.wisenergy.model.dto.AntiFakeQuery;
import cn.wisenergy.model.dto.CreateCodeVo;
import cn.wisenergy.model.dto.ProductDto;
import cn.wisenergy.model.vo.ReportCodeVo;
import cn.wisenergy.service.Manager.AntiFakeManger;
import cn.wisenergy.service.app.AntiFakeService;
import cn.wisenergy.service.util.CodeUtils;
import cn.wisenergy.service.util.QRCodeUtils;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.util.*;

/**
 * @author 86187
 */
@Service
@Slf4j
public class AntiFakeServiceImpl extends ServiceImpl<AntiFakeMapper, AntiFake> implements AntiFakeService {

    private static final String DEST_PATH = "/opt/upload/video";

    private static final String REQUEST_URL = "http://localhost:81/shop-mall/admin/scanCode?shaValue=";
    @Autowired
    private AntiFakeMapper antiFakeMapper;

    @Autowired
    private AntiFakeManger antiFakeManger;

    @Autowired
    private ProductMapper productMapper;

    @Override
    public R<Boolean> createCode(CreateCodeVo codeVo) throws ParseException {
        log.info("AntiFakeServiceImpl[]createCode[]input.param.codeVo:" + codeVo);
        if (null == codeVo || StringUtils.isBlank(codeVo.getProduceTime())) {
            return R.error("入参不能为空!");
        }

        int number;
        if (null == codeVo.getNumber()) {
            number = 1000;
        } else {
            number = codeVo.getNumber();
        }

        //获取最大批次号
        String batch = antiFakeMapper.getByBestBigNumber();
        String batchNumber = "";
        if (StringUtils.isBlank(batch)) {
            batchNumber = "10000001";
        } else {
            Integer sum = Integer.parseInt(batch) + 1;
            batchNumber = String.valueOf(sum);
        }

        int initBatchNo = 10000000;
        String realTime = DateUtil.getTime(new Date(), "yyyy-MM-dd");
        List<AntiFake> list = new ArrayList<>();

        for (int i = 0; i < number; i++) {
            int batchNo = initBatchNo + i + 1;
            AntiFake antiFake = new AntiFake();
            antiFake.setBatchNumber(batchNumber);
            antiFake.setProduceTime(realTime);

            //生成产品编码
            String productNo = CodeUtils.createProductNo(batchNumber, String.valueOf(batchNo), codeVo.getProduceTime());
            antiFake.setProductNo(productNo);
            antiFake.setStatus(0);
            antiFake.setUseStatus(0);

            //生成防伪码
            String sha = DigestUtils.sha1Hex(productNo).substring(0, 16);
            antiFake.setShaValue(sha);

            //生成六位随机数作为安全码
            int code = (int) ((Math.random() * 9 + 1) * 100000);
            antiFake.setSecurityCode(String.valueOf(code));
            antiFake.setScanNumber(0);
            antiFake.setProduceTime(codeVo.getProduceTime());
            list.add(antiFake);
        }

        //初始化产品认证信息
        ProductInfo productInfo = new ProductInfo();
        productInfo.setBatchNumber(batchNumber);
        productInfo.setCompanyAddress("東京都千代田区東神田2丁目6番7号608");
        productInfo.setCompanyName("日本西田森製薬株式会社");
        productInfo.setCompanyUrl("www.nishidamori.co.jp");
        productInfo.setLogisticsUrl("中国国际货运航空 https://www.airchinacargo.com/en/search_order.php");
        productInfo.setBrand("西田森");
        productInfo.setProductCountry(codeVo.getProductCountry());
        productInfo.setRecordNumber(codeVo.getRecordNumber());
        productInfo.setTrackingNumber(codeVo.getTrackingNumber());
        productInfo.setValidTime(codeVo.getValidTime());
        productInfo.setSpecification(codeVo.getSpecification());
        productInfo.setBrandName(codeVo.getBrandName());

        //批量添加二维码 和产品认证信息
        boolean bool = antiFakeManger.addAntiFakeAndProductInfo(list, productInfo);
        if (!bool) {
            return R.ok(1, false);
        }
        return R.ok(0, true);
    }

    @Override
    public R<String> scanCode(String shaValue, String securityCode) {
        log.info("AntiFakeServiceImpl[]scanCode[]input.param.shaValue:" + shaValue);
        if (StringUtils.isBlank(shaValue) || StringUtils.isBlank(securityCode)) {
            return R.error("入参不能为空!");
        }

        //获取二维码信息
        AntiFake antiFake = antiFakeMapper.getByShaValue(shaValue);
        if (null == antiFake) {
            return R.ok("防伪码号" + shaValue + "的产品为非正品!");
        }

        if (!securityCode.equals(antiFake.getSecurityCode())) {
            return R.ok("溯源码不匹配,请重新输入!");
        }

        if (antiFake.getStatus() == 1) {
            antiFake.setScanNumber(antiFake.getScanNumber() + 1);
            int count = antiFakeMapper.edit(antiFake);
            if (count == 0) {
                return R.error("扫描失败!");
            }
            return R.ok("防伪码号" + antiFake.getShaValue() + "的产品为正品," +
                    "第一次扫描时间为:" + DateUtil.convertDateToStr(antiFake.getScanTime(), "yyyy-MM-dd HH:mm:ss")
                    + ",共扫描过" + antiFake.getScanNumber() + "次码");
        }

        antiFake.setStatus(1);
        antiFake.setScanTime(new Date());
        antiFake.setScanNumber(antiFake.getScanNumber() + 1);
        int count = antiFakeMapper.edit(antiFake);
        if (count == 0) {
            return R.error("扫描失败!");
        }
        return R.ok("防伪码号" + antiFake.getShaValue() + "的产品为正品," +
                "第一次扫描时间为:" + DateUtil.convertDateToStr(antiFake.getScanTime(), "yyyy-MM-dd HH:mm:ss")
                + ",共扫描过" + antiFake.getScanNumber() + "次码");
    }

    @Override
    public R<PageInfo<AntiFake>> getList(AntiFakeQuery query) {
        log.info("AntiFakeServiceImpl[]getList[]input.param.query:" + query);
        if (null == query) {
            return R.error("入参不能为空!");
        }

        pageHandle(query);

        Map<String, Object> map = new HashMap<>(8);
        if (null != query.getUseStatus()) {
            map.put("useStatus", query.getUseStatus());
        }
        int total = antiFakeMapper.count(map);

        map.put("startNum", query.getStartNum());
        map.put("endNum", query.getEndNum());
        List<AntiFake> list = antiFakeMapper.getList(map);
        PageInfo<AntiFake> info = new PageInfo<>();
        info.setPageSize(query.getPageSize());
        info.setPageNum(query.getPageNo());
        info.setTotal(total);
        info.setList(list);
        return R.ok(info);
    }

    @Override
    public R<Boolean> report(String batchNumber, HttpServletRequest request, HttpServletResponse response) {
        log.info("AntiFakeServiceImpl[]report[]input.param.batchNumber:" + batchNumber);
        if (StringUtils.isBlank(batchNumber)) {
            return R.error("入参不能为空!");
        }

        //获取防伪码
        List<AntiFake> result = antiFakeMapper.getBatchNumber(batchNumber);
        if (CollectionUtils.isEmpty(result)) {
            return R.ok(0, true);
        }

        String regFullUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
                + "/front/blockChain?shaValue=";
        List<ReportCodeVo> resultBo = new ArrayList<>();
        for (AntiFake anti : result) {
            String url = regFullUrl + anti.getShaValue();
            ReportCodeVo reportCodeVo = new ReportCodeVo();
            reportCodeVo.setShaValue(url);
            resultBo.add(reportCodeVo);
        }

        //生成Excel
        try {
            //  设置内容格式 以及 编码方式
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");

            //创建文件名称
            long lon = System.currentTimeMillis();

            response.setHeader("Content-disposition", "attachment;filename=" + lon + ".xlsx");

            //  sheet名称
            EasyExcel.write(response.getOutputStream(), AntiFake.class).sheet(Long.toString(lon)).doWrite(resultBo);

            //修改二维码使用状态
            boolean bool = antiFakeManger.updateAntiFake(batchNumber);
            if (!bool) {
                return R.error("更新二维码使用状态失败！");
            }
            return R.ok(0, true);
        } catch (Exception e) {
            return R.ok(1, false);
        }
    }

    @Override
    public R<ProductDto> getProductInfo(String shaValue) {
        log.info("AntiFakeServiceImpl[]getProductInfo[]input.param.shaValue:" + shaValue);
        if (StringUtils.isBlank(shaValue)) {
            return R.error("入参不能为空!");
        }

        //获取二维码信息
        ProductDto productDto = new ProductDto();
        AntiFake antiFake = antiFakeMapper.getByShaValue(shaValue);
        if (null != antiFake && StringUtils.isNotEmpty(antiFake.getBatchNumber())) {
            //获取产品信息
            ProductInfo productInfo = productMapper.getByBatchNumber(antiFake.getBatchNumber());
            if (null != productInfo) {
                productDto.setBrand(productInfo.getBrand());
                productDto.setBrandName(productInfo.getBrandName());
                productDto.setCompanyAddress(productInfo.getCompanyAddress());
                productDto.setCompanyName(productInfo.getCompanyName());
                productDto.setCompanyUrl(productInfo.getCompanyUrl());
                productDto.setLogisticsUrl(productInfo.getLogisticsUrl());
                productDto.setProduceTime(antiFake.getProduceTime());
                productDto.setProductCountry(productInfo.getProductCountry());
                productDto.setRecordNumber(productInfo.getRecordNumber());
                productDto.setSpecification(productInfo.getSpecification());
                productDto.setTrackingNumber(productInfo.getTrackingNumber());
                productDto.setValidTime(productInfo.getValidTime());
            }
        }

        return R.ok(productDto);
    }

    @Override
    public R<Boolean> ceishi(String shaValue, HttpServletRequest request) throws Exception {
//        String regFullUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
//                + "/front/blockChain?shaValue=" + shaValue;

        String url = "http://8.131.244.76:81/front/blockChain?shaValue=" + shaValue;
        String destPath = "C:\\home\\image";
        QRCodeUtils.encode(url, destPath);
        return null;
    }


    /**
     * 分页处理方法
     *
     * @param schemeVo 参数
     */
    private void pageHandle(AntiFakeQuery schemeVo) {
        Integer pageNum = schemeVo.getPageNo();
        Integer pageSize = schemeVo.getPageSize();
        if (null == pageSize || pageSize == 0) {
            pageSize = 10;
        }
        if (null == pageNum || pageNum == 0) {
            pageNum = 1;
        }
        Integer endNum = pageSize;
        Integer startNum = (pageNum - CommonAttributes.NUM_ONE) * pageSize;
        schemeVo.setEndNum(endNum);
        schemeVo.setStartNum(startNum);
        schemeVo.setPageNo(pageNum);
        schemeVo.setPageSize(pageSize);
    }
}
