package com.bonus.material.purchase.service.impl;

import com.bonus.common.biz.config.BackstageApplication;
import com.bonus.common.biz.config.DateTimeHelper;
import com.bonus.common.biz.config.QrCodeUtils;
import com.bonus.common.biz.constant.MaterialConstants;
import com.bonus.common.biz.enums.HttpCodeEnum;
import com.bonus.common.biz.enums.MaTypeManageTypeEnum;
import com.bonus.common.biz.enums.PurchaseTaskStatusEnum;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.purchase.config.RemoteConfig;
import com.bonus.material.purchase.domain.dto.PurchaseDto;
import com.bonus.material.purchase.mapper.PurchaseBindMapper;
import com.bonus.material.purchase.service.IPurchaseBindService;
import com.bonus.material.purchase.domain.vo.PurchaseVo;
import com.bonus.material.task.mapper.TmTaskMapper;
import com.google.zxing.WriterException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Author ma_sh
 * @create 2024/10/21 18:42
 */
@Service
@Slf4j
public class PurchaseBindServiceImpl implements IPurchaseBindService {

    @Resource
    private PurchaseBindMapper purchaseBindMapper;

    @Resource
    private TmTaskMapper tmTaskMapper;

    @Resource
    private RemoteConfig remoteConfig;


    /**
     * 查询所有绑定信息
     * @param dto
     * @return
     */
    @Override
    public List<PurchaseVo> selectAll(PurchaseDto dto) {
        List<PurchaseVo> list = purchaseBindMapper.selectAll(dto);
        if (CollectionUtils.isNotEmpty(list)) {
            Iterator<PurchaseVo> iterator = list.iterator();
            while (iterator.hasNext()) {
                PurchaseVo purchaseVo = iterator.next();
                String[] split = purchaseVo.getManageType().split(",");
                // 检查是否全部为 1
                boolean allOnes = true;
                for (String manageType : split) {
                    if (MaTypeManageTypeEnum.CODE_DEVICE.getTypeId().equals(Integer.valueOf(manageType.trim()))) {
                        allOnes = false;
                        // 发现不是 1，跳出循环
                        break;
                    }
                }
                // 如果全部为 1，移除该记录
                if (allOnes) {
                    iterator.remove();
                }
            }
        }
        return list;
    }

    /**
     * 查询绑定信息
     * @param dto
     * @return
     */
    @Override
    public AjaxResult selectPurchaseCheckInfoById(PurchaseDto dto) {
        if (dto == null || dto.getTaskId() == null || dto.getTypeId() == null) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "参数不能为空");
        }
        List<PurchaseVo> list = purchaseBindMapper.selectPurchaseCheckInfoById(dto);
        //extracted(list);
        return AjaxResult.success(list);
    }

    /**
     * 获取新购绑定二级明细列表
     * @param dto
     * @return
     */
    @Override
    public List<PurchaseVo> getDetails(PurchaseDto dto) {
        List<PurchaseVo> list = purchaseBindMapper.getDetails(dto);
        Map<String, String> labelMap = remoteConfig.getDictValue("purchase_task_status");
        if (CollectionUtils.isNotEmpty(list)) {
            for (PurchaseVo purchaseVo : list) {
                // 更新状态名称
                Integer status = purchaseVo.getStatus();
                if (status != null) {
                    String dictValue = labelMap.get(status.toString());
                    purchaseVo.setStatusName(dictValue);
                }
            }
        }
        return list;
    }

    /**
     * 绑定
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult bind(PurchaseDto dto) {
        //先查询提交的编码中是否存在重复提交
        long distinctCodes = dto.getDtoList().stream().map(PurchaseDto::getMaCode).distinct().count();
        if (distinctCodes < dto.getDtoList().size()) {
            return AjaxResult.error(1113,"提交的数据中设备编码存在重复，请勿重复添加");
        }
        for (PurchaseDto purchaseDto : dto.getDtoList()) {
            //根据设备编码唯一校验
            List<PurchaseDto> tbBdDeviceRecord = purchaseBindMapper.selectByCode(purchaseDto);
            if (CollectionUtils.isNotEmpty(tbBdDeviceRecord)) {
                return AjaxResult.error(1114,"设备编码与库中重复，请勿重复添加");
            }
        }
        int result = 0;
        for (PurchaseDto purchaseDto : dto.getDtoList()) {
            purchaseDto.setCreateBy(SecurityUtils.getUserId().toString());
            purchaseDto.setCreateTime(DateUtils.getNowDate());
            purchaseDto.setTaskId(dto.getTaskId());
            purchaseDto.setTypeId(dto.getTypeId());
            purchaseDto.setStatus(0);
            result += purchaseBindMapper.add(purchaseDto);
        }
        //根据前端传参更新绑定数量
        result += purchaseBindMapper.updateNum(dto, dto.getDtoList().size());
        //根据任务id和类型id查询状态
        List<PurchaseVo> voList = purchaseBindMapper.selectPurchaseCheckInfoById(dto);
        if (CollectionUtils.isNotEmpty(voList)) {
            for (PurchaseVo purchaseVo : voList) {
                if (purchaseVo.getBindNum().equals(purchaseVo.getCheckNum())) {
                    purchaseBindMapper.updateStatusById(PurchaseTaskStatusEnum.TO_STORE.getStatus(), purchaseVo.getPurchaseId());
                }
                if (purchaseVo.getBindNum() < purchaseVo.getCheckNum()) {
                    purchaseBindMapper.updateStatusById(PurchaseTaskStatusEnum.TO_BIND.getStatus(), purchaseVo.getPurchaseId());
                }
            }
        }
//        PurchaseDto purchaseDto = new PurchaseDto();
//        purchaseDto.setTaskId(dto.getTaskId());
//        List<PurchaseVo> list = purchaseBindMapper.getDetails(purchaseDto);
//        Map<Integer, List<Integer>> groupedByIdStatus = list.stream()
//                .collect(Collectors.groupingBy(
//                        PurchaseVo::getTaskId,
//                        Collectors.mapping(PurchaseVo::getStatus, Collectors.toList())
//                ));
//        result += groupedByIdStatus.entrySet().stream()
//                .mapToInt(entry -> updateTaskStatus(entry.getKey(), entry.getValue()))
//                .sum();
        if (result > 0) {
            return AjaxResult.success("绑定成功");
        }
        return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * 提取状态更新逻辑到一个方法
     * @param taskId
     * @param statusList
     * @return
     */
//    private int updateTaskStatus(Integer taskId, List<Integer> statusList) {
//        if (statusList.contains(PurchaseTaskStatusEnum.TO_STORE_AFTER_REJECT.getStatus()) ||
//                statusList.contains(PurchaseTaskStatusEnum.TO_BIND.getStatus())) {
//            return tmTaskMapper.updateStatusById(MaterialConstants.TEN_CONSTANT, taskId.toString());
//        } else if (!statusList.contains(PurchaseTaskStatusEnum.TO_STORE_AFTER_REJECT.getStatus()) &&
//                !statusList.contains(PurchaseTaskStatusEnum.TO_BIND.getStatus()) &&
//                statusList.contains(PurchaseTaskStatusEnum.TO_STORE.getStatus())) {
//            return tmTaskMapper.updateStatusById(PurchaseTaskStatusEnum.IN_STORE.getStatus(), taskId.toString());
//        }
//        return 0;
//    }

    /**
     * 下载二维码
     * @param response
     * @param purchaseDto
     */
    @Override
    public void downloadQrCode(HttpServletResponse response, PurchaseDto purchaseDto) {
         //生成二维码
        Set<String> addedEntries = new HashSet<>();
        if (purchaseDto.getPurchaseId() == null) {
            throw new RuntimeException("内层id为空");
        }
        String genMonth = DateTimeHelper.getNowMonth();
        List<PurchaseVo> codeList = purchaseBindMapper.select(genMonth);
        try (OutputStream os = response.getOutputStream();
             ZipOutputStream zos = new ZipOutputStream(os)) {
            Integer status = purchaseBindMapper.selectStatus(purchaseDto);
            if (status == null) {
                return;
            }
            //内层二维码下载
            handlePurchaseId(addedEntries, purchaseDto, codeList, status, zos, genMonth);
            zos.flush();
        } catch (WriterException | IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 驳回或批量驳回操作
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult reject(PurchaseDto dto) {
        //一级页面驳回
        int result = 0;
        if (dto.getTaskId() != null) {
            //根据任务id查询详细信息
            List<PurchaseVo> list = purchaseBindMapper.getDetails(dto);
            if (CollectionUtils.isNotEmpty(list)) {
                for (PurchaseVo purchaseVo : list) {
                    //更新状态为已驳回
                    if (purchaseVo.getStatus().equals(PurchaseTaskStatusEnum.TO_BIND.getStatus()) ||
                            purchaseVo.getStatus().equals(PurchaseTaskStatusEnum.TO_BIND_AFTER_REJECT.getStatus())) {
                        purchaseBindMapper.updateStatusById(PurchaseTaskStatusEnum.TO_BIND_AFTER_REJECT.getStatus(), purchaseVo.getPurchaseId());
                    }
                }
            }
            //result += tmTaskMapper.updateStatusById(MaterialConstants.TEN_CONSTANT, dto.getTaskId());
        }
        //二级页面驳回
        if (dto.getPurchaseId() != null) {
            List<String> idList = Arrays.asList(dto.getPurchaseId().split(","));
            for (String purchaseId : idList) {
                result += purchaseBindMapper.updateStatusById(PurchaseTaskStatusEnum.TO_BIND_AFTER_REJECT.getStatus(), purchaseId);
            }
//            for (String id : idList) {
//                //根据二级页面驳回状态更新任务状态
//                dto.setPurchaseId(id);
//                List<PurchaseVo> list = purchaseBindMapper.getDetails(dto);
//                if (CollectionUtils.isNotEmpty(list)) {
//                    for (PurchaseVo purchaseVo : list) {
//                        PurchaseDto purchaseDto = new PurchaseDto();
//                        purchaseDto.setTaskId(purchaseVo.getTaskId().toString());
//                        List<PurchaseVo> voList = purchaseBindMapper.getDetails(purchaseDto);
//                        result = getResult(result, voList);
//                    }
//                }
//            }
        }
        if (result > 0) {
            return AjaxResult.success("操作成功");
        }
        return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * 获取结果方法抽取
     * @param result
     * @param voList
     * @return
     */
//    private int getResult(int result, List<PurchaseVo> voList) {
//        Map<Integer, List<Integer>> groupedByIdStatus = voList.stream()
//                .collect(Collectors.groupingBy(
//                        PurchaseVo::getTaskId,
//                        Collectors.mapping(PurchaseVo::getStatus, Collectors.toList())
//                ));
//        result += groupedByIdStatus.entrySet().stream()
//                .mapToInt(entry -> {
//                    Integer taskId = entry.getKey();
//                    List<Integer> statusList = entry.getValue();
//                    if (statusList.contains(PurchaseTaskStatusEnum.TO_BIND_AFTER_REJECT.getStatus()) ||
//                            statusList.contains(PurchaseTaskStatusEnum.TO_BIND.getStatus())) {
//                        return tmTaskMapper.updateStatusById(MaterialConstants.TEN_CONSTANT, taskId.toString());
//                    } else if (!statusList.contains(PurchaseTaskStatusEnum.TO_BIND_AFTER_REJECT.getStatus()) && !statusList.contains(PurchaseTaskStatusEnum.TO_BIND.getStatus())
//                            && statusList.contains(PurchaseTaskStatusEnum.TO_STORE.getStatus())) {
//                        return tmTaskMapper.updateStatusById(PurchaseTaskStatusEnum.IN_STORE.getStatus(), taskId.toString());
//                    }
//                    return 0;
//                }).sum();
//        return result;
//    }

    /**
     * 内层二维码下载
     * @param purchaseDto
     * @param codeList
     * @param status
     * @param zos
     * @param genMonth
     * @throws IOException
     * @throws WriterException
     */
    private void handlePurchaseId(Set<String> addedEntries, PurchaseDto purchaseDto, List<PurchaseVo> codeList, Integer status, ZipOutputStream zos, String genMonth) throws IOException, WriterException {
        if (status == 1) {
            Select(addedEntries, purchaseDto, zos);
        } else {
            int num = getInitialNum(codeList);
            List<PurchaseVo> details = purchaseBindMapper.getDetails(purchaseDto);
            if (CollectionUtils.isNotEmpty(details)) {
                PurchaseVo detail = details.get(0);
                purchaseDto.setTaskId(detail.getTaskId().toString());
                getString(addedEntries, purchaseDto, genMonth, num, zos, detail.getMaterialModel(), detail.getMaterialName(), detail.getTypeId(), detail.getCheckNum());
                extractedUpStatus(purchaseDto);
            }
        }
    }

    /**
     * 方法抽取
     * @param purchaseDto
     * @param genMonth
     * @param num
     * @param zos
     * @param materialModel
     * @param materialName
     * @param typeId
     * @param checkNum
     * @throws WriterException
     * @throws IOException
     */
    private void getString(Set<String> addedEntries, PurchaseDto purchaseDto, String genMonth, int num, ZipOutputStream zos, String materialModel, String materialName, Integer typeId, Integer checkNum) throws WriterException, IOException {
        for (int j = 1; j <= checkNum; j++) {
            genMonth = genMonth.replace("-", "");
            String code = genMonth + "-" + String.format("%5d", num + j).replace(" ", "0");
            // 新购管理-二维码打印-新增
            String url = BackstageApplication.getUrl() + "backstage/machine/qrCodePage?qrcode=" + code;
            // // 二维码的图片格式
            String format = "jpg";
            //设置路径
            String mkdirsName = "images";
            // linux 系统路径
            String saveDirectory = "/data/imw/" + mkdirsName + "/";
            String os = System.getProperty("os.name");
            if (os.toLowerCase().startsWith("win")) {
                //本地路径
                saveDirectory = "D://files/" + mkdirsName + "/";
            }
            // 生成二维码
            File files = new File(saveDirectory);
            if (!files.exists()) {
                files.mkdirs();
            }
            QrCodeUtils.generateQRImage(url, saveDirectory, code + ".jpg", format);
            String qrUrl = saveDirectory + code + ".jpg";
            PurchaseDto dto = PurchaseDto.builder().taskId(purchaseDto.getTaskId()).typeId(typeId).qrCode(code).qrUrl(qrUrl).createBy(SecurityUtils.getUserId().toString()).build();
            purchaseBindMapper.insert(dto);
            extracted( addedEntries, zos, materialModel, materialName, code, qrUrl);
        }
    }

    /**
     * 修改任务表方法抽取
     * @param purchaseDto
     */
    private void extractedUpStatus(PurchaseDto purchaseDto) {
        //修改任务表的是否下载状态
        purchaseBindMapper.updateStatus(purchaseDto.getTaskId(), purchaseDto.getPurchaseId());
    }

    /**
     * 获取初始化num
     * @param codeList
     * @return
     */
    private int getInitialNum(List<PurchaseVo> codeList) {
        if (com.alibaba.nacos.common.utils.CollectionUtils.isNotEmpty(codeList)) {
            PurchaseVo purchaseVo = codeList.get(0);
            return Integer.parseInt(purchaseVo.getQrCode().split("-")[1]);
        }
        return 0;
    }

    /**
     * 查询方法抽取
     * @param purchaseDto
     * @param zos
     * @throws IOException
     */
    private void Select(Set<String> addedEntries, PurchaseDto purchaseDto, ZipOutputStream zos) throws IOException {
        List<PurchaseVo> list = purchaseBindMapper.selectPurchaseCheckInfoById(purchaseDto);
        if (com.alibaba.nacos.common.utils.CollectionUtils.isNotEmpty(list)) {
            for (PurchaseVo purchaseVo : list) {
                String materialModel = purchaseVo.getMaterialModel();
                String materialName = purchaseVo.getMaterialName();
                String path = purchaseVo.getQrUrl();
                String qrCode = purchaseVo.getQrCode();
                path = path.replace("filePath", "/data/imw");
                extractedQrCode(qrCode);
                extracted(addedEntries, zos, materialModel, materialName, qrCode, path);
            }
        }
    }

    /**
     * 二维码生产方法抽取
     * @param qrCode
     */
    private void extractedQrCode(String qrCode) {
        // 新购管理-二维码打印-新增
        String url = BackstageApplication.getUrl() + "backstage/machine/qrCodePage?qrcode=" + qrCode;
        // // 二维码的图片格式
        String format = "jpg";
        //设置路径
        String mkdirsName = "images";
        // linux 系统路径
        String saveDirectory = "/data/imw/" + mkdirsName + "/";
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith("win")) {
            //本地路径
            saveDirectory = "D://files/" + mkdirsName + "/";
        }
        // 生成二维码
        File files = new File(saveDirectory);
        if (!files.exists()) {
            files.mkdirs();
        }
        QrCodeUtils.generateQRImage(url, saveDirectory, qrCode + ".jpg", format);
    }

    /**
     * 二维码下载方法抽取
     * @param zos
     * @param materialModel
     * @param materialName
     * @param code
     * @param path
     * @throws IOException
     */
    private void extracted(Set<String> addedEntries, ZipOutputStream zos, String materialModel, String materialName, String code, String path) throws IOException {
        // 判断路径是否存在
        File imageFile = new File(path);
        if (!imageFile.exists()) {
            return;
        }
        String entryName = "[" + materialModel + "-" + materialName + "]" + code + ".jpg";
        if (addedEntries.contains(entryName)) {
            System.out.println("Duplicate entry skipped: " + entryName);
            return;
        }
        addedEntries.add(entryName);

        zos.setLevel(0);
        zos.putNextEntry(new ZipEntry(entryName));
        try (InputStream fis = new FileInputStream(imageFile)) {
            byte[] buffer = new byte[1024];
            int r;
            while ((r = fis.read(buffer)) != -1) {
                zos.write(buffer, 0, r);
            }
        }
        zos.closeEntry();
    }
}
