package com.prolog.rdc.tms.util;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.product.core.printer.util.PrintBuilder;
import com.prolog.rdc.tms.constant.PrintConstant;
import com.prolog.rdc.tms.model.dto.print.PrinterConfigInfoDTO;
import com.prolog.rdc.tms.model.dto.print.PrinterConfigurationDTO;
import com.prolog.rdc.tms.model.dto.print.PrinterDTO;
import com.prolog.rdc.tms.model.dto.print.PrinterTemplateDTO;
import com.prolog.rdc.tms.model.vo.print.PrinterConfigInfoVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.rmi.feign.PrintFeign;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 打印调用类
 *
 * @author KingYan
 * @date 2022/04/08
 */
@Slf4j
@Component
public class PrinterHelper {

	@Resource
	private PrintFeign printFeign;

	/**
	 * 打印
	 */
	public void print(Map<String, Object> header, List<?> table, PrinterDTO dto) {
		log.info("print ==========> header:{}", JSONObject.toJSONString(header));
		log.info("print ==========> table:{}", JSONObject.toJSONString(table));
		log.info("print ==========> configurations:{}", JSONObject.toJSONString(dto));
		PrintBuilder builder = new PrintBuilder(printBody -> {
			// 模板地址必须设置
			printBody.setUrl(dto.getTemplate().getTemplatePath());
			// 打印机名称或打印方案必须有一个不为空
			printBody.setPrintName(dto.getConfig().getPrinterName());
			printBody.setPrintSolution(dto.getTemplate().getPlanCode());
			// 若需后台打印，则必须设置
			printBody.setPrintServiceUrl(dto.getConfig().getIp());
		});
		builder.buildData(header, table);
		builder.build();
		builder.print();
	}

	/**
	 * 检查打印机并生成dto
	 *
	 * @param templateCode 模板代码
	 * @return {@link PrinterDTO}
	 */
	public PrinterDTO checkAndGeneratePrinterDTO(MaindataFeign maindataTmsResource, String templateCode) {
		if (StrUtil.isBlank(templateCode)) {
			throw new PrologException("获取打印配置失败，请确认打印方案名称");
		}

		PrinterConfigInfoDTO result = getPrinterConfigInfoDTO(templateCode);
		checkPrinterInfo(result, templateCode);
		return getPrinterDTO(maindataTmsResource, result);
	}

	/**
	 * 检查打印机信息
	 *
	 * @param printerInfo  打印机信息
	 * @param templateCode 模板代码
	 */
	private void checkPrinterInfo(PrinterConfigInfoDTO printerInfo, String templateCode) {
		Assert.notNull(printerInfo, "获取打印机配置失败");

		List<PrinterTemplateDTO> templateList = printerInfo.getTemplateList();
		Assert.notEmpty(templateList, "请配置打印模板并设置方案编码为{}", templateCode);

		List<PrinterConfigurationDTO> configurations = printerInfo.getConfigurations();
		Assert.notEmpty(configurations, "请配置打印机配置并设置打印机编码为{}", templateCode);

		List<PrinterTemplateDTO> printerTemplates = templateList.stream().filter(t -> templateCode.equals(t.getPlanCode()) && String.valueOf(PrintConstant.YES).equals(t.getStatus())).collect(Collectors.toList());
		Assert.notEmpty(printerTemplates, "请检查打印模板编码为【{}}】的模板是否存在或未启动", templateCode);
		if (printerTemplates.size() > 1) {
			throw new PrologException(String.format("启用了重复的打印模板编码为【%s】的模板", templateCode));
		}
		List<PrinterConfigurationDTO> printerCfgS = configurations.stream().filter(t -> templateCode.equals(t.getPrinterCode()) && String.valueOf(PrintConstant.YES).equals(t.getPrinterStatus())).collect(Collectors.toList());
		Assert.notEmpty(printerCfgS, "请检查打印机配置编码为【{}】的配置是否存在或未启动", templateCode);
		if (printerCfgS.size() > 1) {
			throw new PrologException(String.format("启用了重复的打印机配置编码为【%s】的配置", templateCode));
		}
	}

	/**
	 * 封装打印信息
	 */
	private PrinterDTO getPrinterDTO(MaindataFeign maindataTmsResource, PrinterConfigInfoDTO dto) {
		String templateCode = dto.getTemplateCode();
		PrinterConfigurationDTO cfg = dto.getConfigurations().stream().filter(c -> c.getPrinterCode().equals(templateCode)).findFirst().orElse(null);
		if (cfg == null) {
			throw new PrologException(String.format("打印机方案%s不存在", templateCode));
		}

		// 打印编码
		RestMessage<List<Map<String, Object>>> restMessage = maindataTmsResource.getDropDownById(PrintConstant.PRINT_CODE, null, null, null);
		Assert.isTrue(restMessage.isSuccess(), "打印编码查询失败：" + restMessage.getMessage());

		List<Map<String, Object>> list = restMessage.getData();
		Assert.isTrue(ToolKits.isNotEmpty(list), "打印编码字典【" + PrintConstant.PRINT_CODE + "】未配置");

		String code = PublicMethods.reverseChange(list, templateCode);
		Assert.isTrue(ToolKits.isNotEmpty(code), String.format("请在字典明细中配置显示名称为：%s的端口号", templateCode));

		PrinterTemplateDTO template = dto.getTemplateList().get(0);
		PrinterDTO result = new PrinterDTO();
		cfg.setIp(cfg.getIp() + ":" + code);
		result.setConfig(cfg);
		result.setTemplate(template);
		return result;
	}

	/**
	 * 获取打印机和模版信息
	 *
	 * @param templateCode 模板代码
	 * @return {@link PrinterConfigInfoDTO}
	 */
	private PrinterConfigInfoDTO getPrinterConfigInfoDTO(String templateCode) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
//		if (StrUtil.isEmpty(user.getWorkNum())) {
//			throw new PrologException("请先配置操作人工号");
//		}
		PrinterConfigInfoVO vo = new PrinterConfigInfoVO();
		vo.setEmployeeId(String.valueOf(user.getUserid()));
		vo.setTemplateCode(templateCode);
//		vo.setWarehouseId(user.getWarehouseId());

		RestMessage<PrinterConfigInfoDTO> restMessage = printFeign.queryPrinterInfo(vo);
		Assert.isTrue(restMessage.isSuccess(), restMessage.getMessage());

		return restMessage.getData();
	}

}
