package com.mvc.service.produce;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mvc.constant.DeviceType;
import com.mvc.dao.TDeviceSnManagementMapper;
import com.mvc.entity.TDeviceSnManagement;
import com.mvc.entity.TDeviceSnManagementExample;
import com.mvc.model.DeviceAccModel;
import com.mvc.model.ResPageModel;
import com.mvc.model.produce.DicProductionPartModel;
import com.mvc.model.produce.TDeviceSnManagementModel;
import com.mvc.model.produce.TProductionPlanModel;
import com.mvc.service.taizhang.DeviceAccService;
import com.mvc.utils.DateUtil;
import com.mvc.utils.ImageUtil;
import com.mvc.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.util.Matrix;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class TDeviceSnManagementService {

    @Resource
    private TDeviceSnManagementMapper tDeviceSnManagementMapper;

    @Resource
    private DicProductionPartService dicProductionPartService;

    @Resource
    private DeviceAccService deviceAccService;

    private static final int QR_SIZE = 60; // 二维码大小
    private static final int COLUMNS = 5;  // 每页列数
    private static final int ROWS = 13;     // 每页行数

    public ResPageModel findAllTDeviceSnManagement(TDeviceSnManagementModel queryModel) {
        TDeviceSnManagementExample example = new TDeviceSnManagementExample();
        TDeviceSnManagementExample.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotEmpty(queryModel.getPurpose())) {
            criteria.andPurposeLike(StringUtil.getLikeFormat(queryModel.getPurpose()));
        }
        if (StringUtils.isNotEmpty(queryModel.getCreateMan())) {
            criteria.andCreateManLike(StringUtil.getLikeFormat(queryModel.getCreateMan()));
        }
        if (queryModel.getStatus() != null) {
            criteria.andStatusEqualTo(queryModel.getStatus());
        }
        if (queryModel.getProductTypeId() != null) {
            criteria.andProductTypeIdEqualTo(queryModel.getProductTypeId());
        }
        if (queryModel.getApplyYearMonth() != null) {
            criteria.andApplyYearMonthEqualTo(queryModel.getApplyYearMonth());
        }

        example.setOrderByClause(" CREATE_TIME desc ");
        Page<Object> pageObject = PageHelper.startPage(queryModel.getPageNum(), queryModel.getPageSize());
        List<TDeviceSnManagementModel> resList = selectByExample(example);

        ResPageModel resPageModel = new ResPageModel(resList, pageObject);
        return resPageModel;
    }

    public TDeviceSnManagementModel getDeviceSnByProductTypeAndYearMonth(Integer productTypeId, Integer applyYearMonth) {
        TDeviceSnManagementExample example = new TDeviceSnManagementExample();
        TDeviceSnManagementExample.Criteria criteria = example.createCriteria();
        criteria.andProductTypeIdEqualTo(productTypeId);
        criteria.andApplyYearMonthEqualTo(applyYearMonth);
        example.setOrderByClause("SERIAL_NUMBER desc");//按序列号降序

        List<TDeviceSnManagementModel> resList = selectByExample(example);
        return resList.size() > 0 ? resList.get(0) : null;
    }

    /**
     * 根据生产计划生成设备编号
     *
     * @param productionPlanModel
     */
    @Transactional
    public void generateDeviceSnByProductionPlan(TProductionPlanModel productionPlanModel) {
        DicProductionPartModel productPlanModel = dicProductionPartService.getSystemPartModel();
        if (productPlanModel == null) {
            return;
        }
        Integer productTypeId = null;
        if (productionPlanModel.getPartMap().containsKey(productPlanModel.getId())) {
            productTypeId = Integer.valueOf(productionPlanModel.getPartMap().get(productPlanModel.getId()));
        }

        TDeviceSnManagementModel model = new TDeviceSnManagementModel();
        model.setCreateMan(productionPlanModel.getCreateMan());
        model.setProducttionId(productionPlanModel.getId());
        model.setPurpose(productionPlanModel.getPlanName());//计划名称作为用途
        model.setQuantity(productionPlanModel.getProductionQty());
        model.setStatus(1);
        model.setProductTypeId(productTypeId);
        model.setDeviceType(productionPlanModel.getDeviceType());
        saveTDeviceSnManagement(model);
    }

    /**
     * 根据条件查询列表
     *
     * @param example
     * @return
     */
    private List<TDeviceSnManagementModel> selectByExample(TDeviceSnManagementExample example) {
        List<TDeviceSnManagement> deviceSnManagements = tDeviceSnManagementMapper.selectByExample(example);
        List<TDeviceSnManagementModel> resList = new ArrayList<>();
        for (TDeviceSnManagement deviceSnManagement : deviceSnManagements) {
            TDeviceSnManagementModel model = new TDeviceSnManagementModel();
            BeanUtils.copyProperties(deviceSnManagement, model);

            resList.add(model);
        }
        return resList;
    }

    public TDeviceSnManagementModel saveTDeviceSnManagement(TDeviceSnManagementModel model) {
        //生成具体编号
        int productTypeId = model.getProductTypeId();
        DicProductionPartModel productTypeModel = dicProductionPartService.getDicProductionPartById(productTypeId);
        String typeCode = StringUtils.leftPad(productTypeModel.getViewOrder().toString(), 2, '0');
        String dateStr = DateUtil.formateDate(new Date(), "yyyyMM");
        int dateInt = Integer.valueOf(dateStr);
        TDeviceSnManagementModel lastDeviceSnModel = getDeviceSnByProductTypeAndYearMonth(productTypeId, dateInt);
        int serialNumber = lastDeviceSnModel == null ? 1 : lastDeviceSnModel.getSerialNumber() + 1;

        String deviceSN = String.format("%s%s%s", dateStr.substring(2), typeCode, StringUtils.leftPad(String.valueOf(serialNumber), 5, '0'));
        model.setStartCode(deviceSN);
        List<DeviceAccModel> deviceAccList = new ArrayList<>();
        for (int i = 0; i < model.getQuantity(); i++) {
            DeviceAccModel deviceAccModel = new DeviceAccModel();
            // 设备编号(yyMM+type+serialNumber)
            deviceSN = String.format("%s%s%s", dateStr.substring(2), typeCode, StringUtils.leftPad(String.valueOf(serialNumber), 5, '0'));
            deviceAccModel.setAddflag("1");
            deviceAccModel.setDeviceSn(deviceSN);
            deviceAccModel.setDeviceType(StringUtils.isEmpty(model.getDeviceType()) ? DeviceType.WATER_METER.getCode() : model.getDeviceType());
            deviceAccModel.setCreateMan(model.getCreateMan());
            serialNumber++;
            deviceAccList.add(deviceAccModel);
        }
        serialNumber--;
        model.setApplyYearMonth(dateInt);
        model.setSerialNumber(serialNumber);
        model.setEndCode(deviceSN);
        model.setCreateTime(new Date());
        TDeviceSnManagement deviceSnManagement = new TDeviceSnManagement();
        BeanUtils.copyProperties(model, deviceSnManagement);
        tDeviceSnManagementMapper.insert(deviceSnManagement);
        model.setId(deviceSnManagement.getId());

        for (DeviceAccModel deviceAccModel : deviceAccList) {
            deviceAccModel.setDeviceSnManagementId(model.getId());
            deviceAccService.saveDeviceAcc(deviceAccModel);
        }

        return model;
    }

    public TDeviceSnManagementModel updateTDeviceSnManagement(TDeviceSnManagementModel model) {
        TDeviceSnManagement TDeviceSnManagement = tDeviceSnManagementMapper.selectByPrimaryKey(model.getId());
        BeanUtils.copyProperties(model, TDeviceSnManagement);
        int i = tDeviceSnManagementMapper.updateByPrimaryKey(TDeviceSnManagement);
        return model;
    }

    /**
     * 根据主键删除(同步删除设备台账)
     *
     * @param id
     * @return
     */
    public int deleteTDeviceSnManagement(int id) {
        int i = tDeviceSnManagementMapper.deleteByPrimaryKey(id);
        if (i > 0) {//删除台账
            deviceAccService.deleteByDeviceSnManagementId(id);
        }
        return i;
    }

    /**
     * 根据生产计划删除设备编号管理记录(同步删除设备台账)
     *
     * @param productionPlanId
     * @return
     */
    public int deleteTDeviceSnManagementByProductionPlanId(int productionPlanId) {
        TDeviceSnManagementExample example = new TDeviceSnManagementExample();
        example.createCriteria().andProducttionIdEqualTo(productionPlanId);
        List<TDeviceSnManagementModel> list = selectByExample(example);
        if (list != null && list.size() > 0) {
            return deleteTDeviceSnManagement(list.get(0).getId());//理论上不应该有多条的
        }
        return 0;
    }

    /**
     * 根据生产计划id查询设备编号管理记录
     *
     * @param planId
     * @return
     */
    public TDeviceSnManagementModel findTDeviceSnManagementModelByPlanId(int planId) {
        TDeviceSnManagementExample example = new TDeviceSnManagementExample();
        example.createCriteria().andProducttionIdEqualTo(planId);
        List<TDeviceSnManagementModel> list = selectByExample(example);
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据主键查询设备编号管理记录
     *
     * @param id
     * @return
     */
    public TDeviceSnManagementModel findTDeviceSnManagementModelById(int id) {
        TDeviceSnManagement deviceSnManagement = tDeviceSnManagementMapper.selectByPrimaryKey(id);
        if (deviceSnManagement != null) {
            TDeviceSnManagementModel model = new TDeviceSnManagementModel();
            BeanUtils.copyProperties(deviceSnManagement, model);
            return model;
        }
        return null;
    }

    /**
     * 下载设备编码PDF文件
     *
     * @param response
     */
    public void downloadDevicesnPdf(HttpServletResponse response, int planId) {
        TDeviceSnManagementModel model = findTDeviceSnManagementModelByPlanId(planId);
        if(model==null){
            return;
        }

        long startCode = Long.parseLong(model.getStartCode());
        List<String> deviceSns = new ArrayList<>();
        for (long i = startCode; i < startCode + model.getQuantity(); i++) {
            deviceSns.add(String.valueOf(i));
            //deviceSns.add(String.valueOf(i));//一式两份
        }
        String[] data = deviceSns.toArray(new String[deviceSns.size()]);
        try {
            String filename = URLEncoder.encode(model.getStartCode()+"-"+model.getEndCode()+".pdf", "UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-disposition", "attachment;filename=" + filename);
            PDDocument document = new PDDocument();
            int totalItems = data.length;
            int pages = (int) Math.ceil((double) totalItems / (COLUMNS * ROWS));

            for (int pageIndex = 0; pageIndex < pages; pageIndex++) {
                PDPage page = new PDPage(PDRectangle.A4);
                document.addPage(page);
                PDPageContentStream contentStream = new PDPageContentStream(document, page);
                contentStream.setFont(PDType1Font.HELVETICA_BOLD, 8);
                contentStream.beginText();

                int start = pageIndex * COLUMNS * ROWS;
                int end = Math.min(start + COLUMNS * ROWS, totalItems);

                for (int i = start; i < end; i++) {
                    int row = (i - start) / COLUMNS;
                    int column = (i - start) % COLUMNS;

                    // 设置二维码位置
                    float xPosition = 30 + column * (QR_SIZE + 60);// 左边距 + 每列二维码的宽度 + 间距
                    float yPosition = 763 - row * (QR_SIZE + 2.75F);// 上边距 - 每行二维码的高度 + 间距

                    // 绘制二维码
                    BufferedImage qrImage = ImageUtil.generateQRCode(QR_SIZE,data[i]);
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    ImageIO.write(qrImage, "PNG", byteArrayOutputStream);
                    byte[] qrBytes = byteArrayOutputStream.toByteArray();
                    PDImageXObject qrCode = PDImageXObject.createFromByteArray(document, qrBytes, "QR_" + i);

                    // 退出当前文本块，绘制二维码
                    contentStream.endText();  // 结束当前的文本块
                    contentStream.drawImage(qrCode, xPosition, yPosition, QR_SIZE, QR_SIZE);

                    // 开始新的文本块，绘制文本
                    contentStream.beginText();  // 开始新的文本块
                    contentStream.setFont(PDType1Font.HELVETICA, 8);

                    // 使用Matrix设置文本位置
                    Matrix matrix = new Matrix();
                    matrix.translate(xPosition + 4, yPosition); // 设置文本的偏移量
                    contentStream.setTextMatrix(matrix);  // 设置文本矩阵

                    contentStream.showText(data[i]);  // 绘制文本
                }

                contentStream.endText(); // 结束文本块
                contentStream.close();
            }

            document.save(response.getOutputStream());
            document.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
