package com.mortals.xhx.module.product.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.util.DateUtils;
import com.mortals.xhx.base.system.message.impl.MessageProducer;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.common.code.LogTypeEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.key.Constant;
import com.mortals.xhx.common.key.QueueKey;
import com.mortals.xhx.common.model.DefaultTbQueueMsgHeaders;
import com.mortals.xhx.common.model.MessageHeader;
import com.mortals.xhx.common.pdu.site.SitePdu;
import com.mortals.xhx.feign.site.ISiteFeign;
import com.mortals.xhx.module.device.model.*;
import com.mortals.xhx.module.device.service.DeviceLogService;
import com.mortals.xhx.module.device.service.DeviceService;
import com.mortals.xhx.module.product.dao.ProductVersionDao;
import com.mortals.xhx.module.product.model.ProductEntity;
import com.mortals.xhx.module.product.model.ProductVersionEntity;
import com.mortals.xhx.module.product.model.ProductVersionQuery;
import com.mortals.xhx.module.product.service.ProductService;
import com.mortals.xhx.module.product.service.ProductVersionService;
import com.mortals.xhx.queue.DefaultTbQueueMsg;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TbQueueMsgHeaders;
import com.mortals.xhx.utils.EncodeUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.StandardCopyOption;
import java.util.Date;
import java.util.List;

import static com.mortals.xhx.common.key.Constant.MESSAGETYPE_UPGREAD;

/**
 * ProductVersionService
 * 产品客户端版本 service实现
 *
 * @author zxfei
 * @date 2022-08-22
 */
@Service("productVersionService")
@Slf4j
public class ProductVersionServiceImpl extends AbstractCRUDServiceImpl<ProductVersionDao, ProductVersionEntity, Long> implements ProductVersionService {

    @Autowired
    private ProductService productService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private MessageProducer messageProducer;
    @Autowired
    private DeviceLogService deviceLogService;
    @Autowired
    private UploadService uploadService;

    @Value("${upload.path}")
    @Getter
    private String filePathGlob;
    @Autowired
    private ISiteFeign siteFeign;


    @Override
    protected void saveBefore(ProductVersionEntity entity, Context context) throws AppException {
        if (!ObjectUtils.isEmpty(entity.getProductId())) {
            ProductEntity productEntity = productService.get(entity.getProductId(), context);
            if (!ObjectUtils.isEmpty(productEntity)) {
                entity.setProductName(productEntity.getProductName());
                entity.setProductCode(productEntity.getProductCode());
            }
        }
    }

    private void pushUpgradMsg(ProductVersionEntity entity, Context context) {
        if (!ObjectUtils.isEmpty(entity.getProductId())) {
            ProductEntity productEntity = productService.get(entity.getProductId(), context);
            if (!ObjectUtils.isEmpty(productEntity)) {
                List<DeviceEntity> deviceEntities = deviceService.find(new DeviceQuery().productId(entity.getProductId()));
                for (DeviceEntity deviceEntity : deviceEntities) {
                    TbQueueMsgHeaders header = new DefaultTbQueueMsgHeaders();
                    header.put(MessageHeader.MESSAGETYPE, MESSAGETYPE_UPGREAD);
                    header.put(MessageHeader.DEVICECODE, deviceEntity.getDeviceCode());
                    header.put(MessageHeader.TIMESTAMP, DateUtils.getCurrStrDateTime());
                    TbQueueMsg queueMsg = new DefaultTbQueueMsg(IdUtil.fastUUID(), "W10=", header);
                    messageProducer.sendMsg(QueueKey.DEFAULT_EXCHANGE, Constant.DOWN_TOPIC + deviceEntity.getDeviceCode(), JSON.toJSONString(queueMsg));

                    DeviceLogEntity deviceLogEntity = new DeviceLogEntity();
                    deviceLogEntity.initAttrValue();
                    deviceLogEntity.setTraceID(IdUtil.fastSimpleUUID());
                    deviceLogEntity.setSiteId(deviceEntity.getSiteId());
                    deviceLogEntity.setDeviceId(deviceEntity.getId());
                    deviceLogEntity.setDeviceName(deviceEntity.getDeviceName());
                    deviceLogEntity.setDeviceCode(deviceEntity.getDeviceCode());
                    deviceLogEntity.setMessageHead(MESSAGETYPE_UPGREAD);
                    deviceLogEntity.setContent("W10=");
                    deviceLogEntity.setLogType(LogTypeEnum.下发服务.getValue());
                    deviceLogEntity.setCreateUserId(1L);
                    deviceLogEntity.setCreateTime(new Date());
                    deviceLogService.save(deviceLogEntity, null);
                }
            }
        }
    }

    @Override
    public void appPublish(ProductVersionEntity productVersionEntity, Context context) {
        String filePath = productVersionEntity.getFilePath();
        String targetFilePath = uploadService.getFilePath(productVersionEntity.getFilePath());
        String mainName = FileUtil.mainName(targetFilePath);
        String type = FileUtil.extName(filePath);
        if ("zip".equals(type)) {
            String disPath = filePath + "/file/fileupload/" + mainName;
            String replace = StrUtil.replace(productVersionEntity.getFilePath(), FileUtil.getName(productVersionEntity.getFilePath()), "");
            disPath = filePathGlob + "/" + replace + mainName + "/";
            if (!FileUtil.isDirectory(new File(disPath))) {
                FileUtil.mkdir(disPath);
            }
            String fileEncode = "UTF-8";
            try {
                fileEncode = EncodeUtil.getEncode(targetFilePath, true);
            } catch (Exception e) {
                log.error("异常", e);
            }
            log.info("unzip disPath:{}", disPath);
            ZipUtil.unzip(targetFilePath, disPath, Charset.forName(fileEncode));
        }
        pushUpgradMsg(productVersionEntity, context);
    }

    @Override
    public Rest<String> cloneAppBySite(ProductVersionEntity productVersionEntity, Context context) {
        //拷贝应用
        Long targetSiteId = productVersionEntity.getTargetSiteId();
        Long sourceSiteId = productVersionEntity.getSourceSiteId();

        Rest<SitePdu> sitePduRest = siteFeign.info(targetSiteId);

        if (YesNoEnum.NO.getValue() == sitePduRest.getCode()) {
            throw new AppException("未查询到当前站点！");
        }

        SitePdu sitePdu = sitePduRest.getData();

        ProductVersionQuery productVersionQuery = new ProductVersionQuery();
        productVersionQuery.setSiteId(sourceSiteId);
        List<ProductVersionEntity> productVersionEntities = this.find(productVersionQuery);

        //如果已存在 则不复制
        for (ProductVersionEntity productVersion : productVersionEntities) {
            ProductVersionQuery query = new ProductVersionQuery();
            query.setSiteId(targetSiteId);
            query.setProductId(productVersion.getProductId());
            query.setVersion(productVersion.getVersion());
            int count = this.count(query, context);
            if (count == 0) {
                productVersion.setId(null);
                productVersion.setSiteId(sitePdu.getId());
                productVersion.setSiteName(sitePdu.getSiteName());
                productVersion.setSiteCode(sitePdu.getSiteCode());
                String sourceFilePath = uploadService.getFilePath(productVersion.getFilePath());
                boolean exist = FileUtil.exist(sourceFilePath);
                if (exist) {
                    String mainName = FileUtil.mainName(productVersion.getFilePath());
                    //todo 复制附件 和地址
                    String targetFilePath = uploadService.getFilePath(sitePdu.getSiteCode() + "/" + mainName);
                    FileUtil.copyFile(sourceFilePath, targetFilePath, StandardCopyOption.REPLACE_EXISTING);
                    productVersion.setFilePath(targetFilePath);
                }else {
                    productVersion.setFilePath("");
                }
                this.save(productVersion, context);
            }
        }
        return Rest.ok();
    }
}