package cn.wise.sc.cement.business.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.wise.sc.cement.business.entity.EntityEnclosure;
import cn.wise.sc.cement.business.model.BaseResponse;
import cn.wise.sc.cement.business.enumation.FileExt;
import cn.wise.sc.cement.business.model.IndustrialElementKey;
import cn.wise.sc.cement.business.model.IndustrialReport;
import cn.wise.sc.cement.business.model.PageQuery;
import cn.wise.sc.cement.business.model.ReportDetailVo;
import cn.wise.sc.cement.business.model.SixElementKey;
import cn.wise.sc.cement.business.model.SixElementReport;
import cn.wise.sc.cement.business.model.query.SampleHandleEnclosureQuery;
import cn.wise.sc.cement.business.model.vo.EntrustVo;
import cn.wise.sc.cement.business.service.IEntityEnclosureService;
import cn.wise.sc.cement.business.service.IEntrustService;
import cn.wise.sc.cement.business.util.WordUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @description: 报告管理
 * @author: qh
 * @create: 2020-09-25 14:37
 **/
@Api(tags = "报告管理")
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/business/report")
public class ReportController {

    final
    IEntrustService iEntrustService;
    @Autowired
    IEntityEnclosureService iEntityEnclosureService;

    public ReportController(IEntrustService iEntrustService) {
        this.iEntrustService = iEntrustService;

    }

    @ApiOperation(value = "报告分页列表")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "startDate", value = "开始日期", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "endDate", value = "结束日期", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "clientId", value = "委托单位id", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "projectName", value = "项目名称", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "projectCode", value = "项目编号", paramType = "query", dataType = "String")
    })
    @GetMapping("/getPage")
    public BaseResponse<IPage<EntrustVo>> page(PageQuery pageQuery, String startDate, String endDate,
                                               Integer clientId, String projectName, String projectCode) {
        return iEntrustService.getReportPage(pageQuery, startDate, endDate, clientId, projectName, projectCode);
    }

    @ApiOperation(value = "置顶取消置顶 (createTime = updateTime显示置顶，否则显示取消置顶)")
    @PostMapping("/setTopping")
    public BaseResponse<String> setTopping(Integer id) {
        try {
            return iEntrustService.setTopping(id);
        } catch (Exception e) {
            log.debug("置顶取消置顶 {}", e.getMessage());
        }
        return BaseResponse.errorMsg("失败!");
    }

    @DeleteMapping("/{id}")
    @ApiOperation("删除报告")
    public BaseResponse<Boolean> deleteById(@PathVariable("id") Integer id) {
        return iEntrustService.deleteById(id);
    }

    @PostMapping("/{entrustId}")
    @ApiOperation("导出报告封面和首页")
    public void getReportDetail(@PathVariable("entrustId") Integer entrustId,
                                HttpServletResponse response) {

        //首页及封面导出
        ReportDetailVo rts = iEntrustService.getReportDetail(entrustId);
        if (rts == null) {
            return;
        }
        Map<String, Object> beanParams = new HashMap<>(10);
        beanParams.put("sendName", rts.getSendName());
        beanParams.put("sender", rts.getSender());
        beanParams.put("sendDate", rts.getSendDate());
        beanParams.put("sampleNum", rts.getSampleNum());
        beanParams.put("sampleNames", set2String(rts.getSampleNames()));
        beanParams.put("teamNames", set2String(rts.getTeamNames()));
        beanParams.put("projectName", rts.getProjectName());
        beanParams.put("printDate", rts.getPrintDate());

        beanParams.put("year", DateUtil.year(DateUtil.date()));
        beanParams.put("month",DateUtil.month(DateUtil.date()));
        beanParams.put("day",DateUtil.today());
        beanParams.put("reportNo", StrUtil.isEmpty(rts.getReportNo())?"":rts.getReportNo());

        beanParams.put("firstMethodName",getFirstSet(rts.getMethodNames()));
        beanParams.put("firstEquipment",getFirstSet(rts.getEquipmentNames()));
        beanParams.put("methodNames", moveFirst(rts.getMethodNames()));
        beanParams.put("equipmentNames", moveFirst(rts.getEquipmentNames()));


        //六元素导出
        List<SixElementReport> list = iEntrustService.getSampleSixElementCheck(entrustId);

        list.forEach(this::initMapStr2AlongPro);
        List<SixElementReport> al2o3AndTio2List = list.stream()
                .filter(arg -> !"-".equals(arg.getAl2o3AndTio2()))
                .collect(Collectors.toList());
        List<SixElementReport> al2o3SplitTio2List = list.stream()
                .filter(arg -> "-".equals(arg.getAl2o3AndTio2()))
                .collect(Collectors.toList());
        beanParams.put("list1", al2o3AndTio2List);
        beanParams.put("list2", al2o3SplitTio2List);

        //化学工业导出
        List<IndustrialReport> list1 = iEntrustService.getSampleIndustrialCheck(entrustId);
        list1.forEach(this::initMapStr2AlongPro);
        beanParams.put("list3", list1);

        WordUtil.writeWordReport(rts.getProjectName() + "(报告)", "report_new.ftl",
                beanParams, response, FileExt.EXCL);

    }

    @PostMapping("/upload")
    @ApiOperation("上传报告")
    public BaseResponse<Boolean> uploadReport(@RequestBody SampleHandleEnclosureQuery query) {

        Assert.notNull(query.getId(), "委托id不能为空!");

        QueryWrapper<EntityEnclosure> qw = new QueryWrapper();
        qw.eq("entity_type", 5);
        qw.eq("entity_id", query.getId());

        if (FileExt.EXCL.getName().equals(query.getExtName()) ||
                FileExt.EXCLX.getName().equals(query.getExtName())) {
            EntityEnclosure one = iEntityEnclosureService.getOne(qw);
            if (BeanUtil.isEmpty(one)) {
                EntityEnclosure entityEnclosure = new EntityEnclosure();
                entityEnclosure.setEntityId(query.getId());
                entityEnclosure.setExtName(query.getExtName());
                entityEnclosure.setCreateTime(LocalDateTime.now());
                entityEnclosure.setUpdateTime(LocalDateTime.now());
                entityEnclosure.setEnclosureUrl(query.getEnclosureUrl());
                entityEnclosure.setAlias(query.getAlias());
                entityEnclosure.setEntityType(5);
                entityEnclosure.setPdfUrl(query.getPdfUrl());
                iEntityEnclosureService.save(entityEnclosure);
                return BaseResponse.okData(true);
            } else {
                one.setAlias(query.getAlias());
                one.setEnclosureUrl(query.getEnclosureUrl());
                one.setExtName(query.getExtName());
                one.setUpdateTime(LocalDateTime.now());
                iEntityEnclosureService.updateById(one);
                return BaseResponse.okData(true);
            }
        } else {
            return BaseResponse.errorMsg("文件类型只能是excel!");
        }


    }

    /**
     * 将样品六元素检测Map转换成单独属性
     *
     * @param sixElement 带转换的六元素检测结果
     * @return 已转换结果
     */
    private void initMapStr2AlongPro(SixElementReport sixElement) {

        String countResult = sixElement.getCountResults();
        List<SixElementReport.Element> list = JSON.parseArray(countResult, SixElementReport.Element.class);

        HashMap<String, String> countResultMap = new HashMap<>(list.size());
        list.forEach(arg -> countResultMap.put(arg.getName(), arg.getValue()));

        sixElement.setAl2o3("-");
        sixElement.setTio2("-");
        sixElement.setAl2o3AndTio2("-");
        //判断检测结果中六元素Al2O3是否包含TiO2
        if (countResultMap.containsKey(SixElementKey.Al2O3AndTiO2.getKey())) {
            sixElement.setAl2o3AndTio2(countResultMap.get(SixElementKey.Al2O3AndTiO2.getKey()));
        } else {
            sixElement.setAl2o3(countResultMap.getOrDefault(SixElementKey.Al2O3.getKey(), "0"));
            sixElement.setTio2(countResultMap.getOrDefault(SixElementKey.TiO2.getKey(), "0"));
        }

        sixElement.setCao(countResultMap.getOrDefault(SixElementKey.CaO.getKey(), "0"));
        sixElement.setCl(countResultMap.getOrDefault(SixElementKey.Cl.getKey(), "0"));
        sixElement.setFe2o3(countResultMap.getOrDefault(SixElementKey.Fe2O3.getKey(), "0"));
        sixElement.setLoi(countResultMap.getOrDefault(SixElementKey.LOI.getKey(), "0"));
        sixElement.setMgo(countResultMap.getOrDefault(SixElementKey.MgO.getKey(), "0"));
        sixElement.setSio2(countResultMap.getOrDefault(SixElementKey.SiO2.getKey(), "0"));
        sixElement.setSo3(countResultMap.getOrDefault(SixElementKey.SO3.getKey(), "0"));
    }

    private String getFirstSet(Set<String> set){
        Iterator<String> iterator = set.iterator();
        if (iterator.hasNext()){
            return iterator.next();
        }
        return "";
    }

    private static Set<String> moveFirst(Set<String> set){
        Set<String> newSet = new HashSet<>(set.size());
        Iterator<String> iterator = set.iterator();
        if (iterator.hasNext()) {
            String next = iterator.next();
            newSet.addAll(set);
            newSet.remove(next);
            return newSet;
        }
        return null;
    }

    private void initMapStr2AlongPro(IndustrialReport industrialReport) {
        String countResult = industrialReport.getCountResults();
        List<SixElementReport.Element> list = JSON.parseArray(countResult, SixElementReport.Element.class);

        HashMap<String, String> countResultMap = new HashMap<>(list.size());
        list.forEach(arg -> countResultMap.put(arg.getName(), arg.getValue()));

        industrialReport.setAad(countResultMap.getOrDefault(IndustrialElementKey.Aad.getKey(), "0"));
        industrialReport.setJz(countResultMap.getOrDefault(IndustrialElementKey.JZ.getKey(), "0"));
        industrialReport.setMad(countResultMap.getOrDefault(IndustrialElementKey.Mad.getKey(), "0"));
        industrialReport.setMjkg(countResultMap.getOrDefault(IndustrialElementKey.QnetAdMJkg.getKey(), "0"));
        industrialReport.setStad(countResultMap.getOrDefault(IndustrialElementKey.StAd.getKey(), "0"));
        industrialReport.setVad(countResultMap.getOrDefault(IndustrialElementKey.Vad.getKey(), "0"));

    }

    private String set2String(Set<String> source) {
        if (source.size() == 0) {
            return "";
        }
        StringBuilder strBuilder = new StringBuilder();
        for (String target : source) {
            strBuilder.append("、").append(target);
        }
        return strBuilder.replace(0, 1, "").toString();
    }

    private String set2StringN(Set<String> source) {
        if (source.size() == 0) {
            return "";
        }
        StringBuilder strBuilder = new StringBuilder();
        for (String target : source) {
            strBuilder.append("&#10;").append(target);
        }

        return strBuilder.replace(0, 5, "").toString();
    }


}
