package com.palmnest.service.repair.impl;

import cn.superdesk.libs.common.json.JsonUtils;

import com.palmnest.application.CodeConstants;
import com.palmnest.application.Constants;
import com.palmnest.application.bean.AppResultDto;
import com.palmnest.application.bean.Page;
import com.palmnest.application.core.util.AppResultUtil;
import com.palmnest.application.core.util.DateHelper;
import com.palmnest.application.core.util.ExcelUtils;
import com.palmnest.application.core.util.PropertiesKit;
import com.palmnest.application.dto.WebPageResultDto;
import com.palmnest.application.dto.output.ElementDto;
import com.palmnest.application.dto.output.RepairBillStateStatisticsDto;
import com.palmnest.dao.OrganizationDao;
import com.palmnest.model.Element;
import com.palmnest.model.ElementGroup;
import com.palmnest.model.User;
import com.palmnest.model.property.TbOrganization;
import com.palmnest.model.repair.RepairBill;
import com.palmnest.model.repair.RepairBillComment;
import com.palmnest.model.repair.RepairReturnVisit;
import com.palmnest.service.ElementGroupManager;
import com.palmnest.service.dinner.service.OrderDinnerService;
import com.palmnest.service.repair.*;

import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.directwebremoting.util.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 服务之窗1L- RepairBillAccountManagerImpl
 *
 * @Description TODO
 * @author: jiangyong
 * @since: 2020/9/2 10:05
 */
@Service("repairBillStatisticsManager")
public class RepairBillStatisticsManagerImpl implements RepairBillStatisticsManager {
    private Logger LOG = Logger.getLogger(getClass());
    public static final String CLIENTNO = PropertiesKit.readPropertiesValue("clientNo", "wechat.properties");
    @Autowired
    private RepairBillManager repairBillManager;
    @Autowired
    private ElementGroupManager elementGroupManager;
    @Autowired
    private OrganizationDao organizationDao;
    @Autowired
    private RepairBillCommentManager repairBillCommentManager;


    @Autowired
    private RepairReturnVisitManager repairReturnVisitManager;

    @Autowired
    private UserRepairTypeManager userRepairTypeManager;
    @Autowired
   	private OrderDinnerService orderDinnerService;

    @Override
    public List<RepairBillStateStatisticsDto> getRepairBillStatisticsByStatus(Integer orgId, Integer type,
                                                                              String date, String endDate) {
        List<RepairBillStateStatisticsDto> result = new ArrayList<>();
        TbOrganization org = organizationDao.getOrganizationById(orgId);
        List<Element> elementList = getRepairTypeList(orgId); //小类列表 已项目隔离


        if (null != elementList && elementList.size() > 0) {
            for (Element element :
                    elementList) {

                LOG.info("===>小类名字：" + element.getItemname());

                ElementGroup elementGroup = elementGroupManager.getElementGroupId(element.getElementGroup().getId());
                Element element1 = elementGroupManager.getByItemCode(elementGroup.getGroupcode());//查询大类

                List<RepairBill> repairBills =
                        repairBillManager.getTotalByDateAndRepairType(element.getId(), type, date, endDate, orgId.toString());

                RepairBillStateStatisticsDto dto = getRepairBillStatistics(repairBills);
                if (null != element1) {
                    dto.setRepairTypeId(element1.getId());
                    dto.setRepairTypeName(element1.getItemname());
                }
                dto.setOrgId(orgId);
                dto.setOrgName(org.getName());
                dto.setDate(date);
                dto.setRepairTypeDetailId(element.getId());//小类
                dto.setRepairTypeDetailName(element.getItemname());
                result.add(dto);
            }
        }

        return result;
    }

    public static void main(String[] args) {

        System.out.println(new BigDecimal(0).divide(
                new BigDecimal(0), 2, BigDecimal.ROUND_HALF_UP).doubleValue());
    }

    @Override
    public WebPageResultDto getRepairStateListExcel(List<RepairBillStateStatisticsDto> list) throws IOException {
        String sheetName;
        if (list != null && list.size() > 0) {
            sheetName = "工程维修状态统计";
            String[] titles = {
                    "项目",
                    "维修大类",
                    "维修小类",
                    "时间",
                    "总工单数",
                    "未完成",
                    "完成率",

                    "平均接单耗时(h)",
                    "平均完成耗时(h)",
                    //"耗时h",
                    "工程人员",
                    "平均评星",
                    "待审核",
                    "待派单",
                    "可抢单",
                    "进行中",
                    "挂单中",
                    "转单中",
                    "已完成",
                    "已取消"};

            String[] fieldNames = {
                    "orgName",
                    "repairTypeName",
                    "repairTypeDetailName",
                    "date",
                    "allBillTotal",
                    "unfinishedTotal",
                    "fillRate",

                    "avgBillTime",
                    "avgCompleteTime",
                    //"jumpingTime",
                    "managerTotal",
                    "ki",
                    "billStatus1Total",
                    "billStatus22Total",
                    "billStatus2Total",
                    "billStatus3Total",
                    "billStatus4Total",
                    "billStatus5Total",
                    "billStatus8Total",
                    "billStatus10Total"};

            String path = exportExcelDataRecodeExcel(list, sheetName, titles, fieldNames);
            return new WebPageResultDto("200", "成功", path);
        } else {
            return new WebPageResultDto("100", "数据为空，无法导出", null);
        }
    }

    @Override
    public RepairBillStateStatisticsDto getRepairBoardTotal(String orgIds) {
        List<RepairBill> repairBills = repairBillManager.getByOrg(orgIds);

        String[] orgIdArr = orgIds.split(",");
        TbOrganization org = organizationDao.getOrganizationById(Integer.parseInt(orgIdArr[0]));

        RepairBillStateStatisticsDto result = getRepairBillStatistics(repairBills);
        result.setOrgId(org.getId());
        result.setOrgName(org.getName());
        return result;
    }

    /**
     * 通用统计维修单方法
     *
     * @param repairBills
     * @return
     */
    private RepairBillStateStatisticsDto getRepairBillStatistics(List<RepairBill> repairBills) {
        RepairBillStateStatisticsDto dto = new RepairBillStateStatisticsDto();
        if (null != repairBills && repairBills.size() > 0) {
            Long billRepairType = repairBills.get(0).getRepairType();

            int hours = 0;
            int singleMinutes = 0; //抢单总分钟数
            int completedMinutes = 0; //完成总分钟数
            int commentTotal = 0; //总评价数
            int allCommentStars = 0; //总评星数
            
            BigDecimal todayEnd=BigDecimal.ZERO;
            BigDecimal todayCreate=BigDecimal.ZERO;

            for (RepairBill repairBill : repairBills) {

                LOG.info("===>code:{}"+ repairBill.getCode());

                int status = repairBill.getStatus().intValue();

                if (status != CodeConstants.CANCEL &&
                        status != CodeConstants.UNAUDIT) {
                    dto.setAllBillTotal(dto.getAllBillTotal() + 1); //总工单数 排除审核未通过、已取消订单
                }

                if (status != CodeConstants.COMPLETED &&
                        status != CodeConstants.UNAUDIT &&
                        status != CodeConstants.CANCEL) {
                    //未完成的 排除已取消、审核未通过、已完成订单
                    dto.setUnfinishedTotal(dto.getUnfinishedTotal() + 1);
                }

                if (status == CodeConstants.TO_AUDIT) {
                    //待审核数
                    dto.setBillStatus1Total(dto.getBillStatus1Total() + 1);
                }

                if (status == CodeConstants.TO_SEND) {
                    //待派单数
                    dto.setBillStatus22Total(dto.getBillStatus22Total() + 1);
                }

                if (status == CodeConstants.IS_SINGLE) {
                    //可抢单数
                    dto.setBillStatus2Total(dto.getBillStatus2Total() + 1);
                }

                if (status == CodeConstants.IN_PROGRESS) {
                    //进行中
                    dto.setBillStatus3Total(dto.getBillStatus3Total() + 1);
                }

                if (status == CodeConstants.IN) {
                    //挂单中
                    dto.setBillStatus4Total(dto.getBillStatus4Total() + 1);
                }

                if (status == CodeConstants.TRANSFERED) {
                    //转单中
                    dto.setBillStatus5Total(dto.getBillStatus5Total() + 1);
                }

                Date minutes_startTime = DateHelper.parseToDate(DateHelper.toDateTimeString(repairBill.getCreateTime()),"yyyy-MM-dd HH:mm"); //格式化到分
                LOG.info("===>minutes_startTime:{}"+ DateHelper.toDateTimeString(minutes_startTime));
                Date minutes_endTime = null;
                if(null != repairBill.getEndTime()){
                    minutes_endTime = DateHelper.parseToDate(DateHelper.toDateTimeString(repairBill.getEndTime()),"yyyy-MM-dd HH:mm"); //格式化到分
                    LOG.info("===>minutes_endTime:{}"+ DateHelper.toDateTimeString(minutes_endTime));
                }

                Date minutes_singleTime = null;
                if(null != repairBill.getSingleTime()){
                    minutes_singleTime = DateHelper.parseToDate(DateHelper.toDateTimeString(repairBill.getSingleTime()),"yyyy-MM-dd HH:mm"); //格式化到分
                    LOG.info("===>minutes_singleTime:{}"+ DateHelper.toDateTimeString(minutes_singleTime));
                }


                if (status == CodeConstants.COMPLETED) {
                    //已完成
                    dto.setBillStatus8Total(dto.getBillStatus8Total() + 1);
                    //已完成的总耗时
                    hours += DateHelper.getHoursBetween(repairBill.getCreateTime(), repairBill.getEndTime());
                    completedMinutes += DateHelper.getMinutesBetween(minutes_startTime, minutes_endTime);

                }

                //已抢单-数量
                if(null != repairBill.getSingleTime()){
                    dto.setBillSingleTotal(dto.getBillSingleTotal() + 1);
                    singleMinutes += DateHelper.getMinutesBetween(minutes_startTime, minutes_singleTime);
                }

                if (status == CodeConstants.UNAUDIT || status == CodeConstants.CANCEL) {
                    //已取消 包括已取消、审核未通过订单
                    dto.setBillStatus10Total(dto.getBillStatus10Total() + 1);
                }
                if(null != repairBill.getEndTime()){
                	 String endDay=DateHelper.formatDate(repairBill.getEndTime(), DateHelper.CURRENT_DATE);
                	 String sysDay=DateHelper.formatDate(new Date(), DateHelper.CURRENT_DATE);
                	 //完成日期是今天且状态是完成的订单
                     if(status == CodeConstants.COMPLETED && sysDay.equals(endDay)){
                    	 dto.setBillTodayEndTotal(dto.getBillTodayEndTotal() + 1);
                     }
                }
                
                if(null != repairBill.getCreateTime()){
                	 String endDay=DateHelper.formatDate(repairBill.getCreateTime(), DateHelper.CURRENT_DATE);
                	 String sysDay=DateHelper.formatDate(new Date(), DateHelper.CURRENT_DATE);
                	 if(sysDay.equals(endDay)){
                		 todayCreate=todayCreate.add(BigDecimal.ONE);
                		 if(status == CodeConstants.COMPLETED){
                        	 	todayEnd=todayEnd.add(BigDecimal.ONE);
                         }
                	 }
                }
               

                //平均评星 总评星数/总评价单数
                RepairBillComment repairBillComment = repairBillCommentManager.findBy(repairBill.getId());

                RepairReturnVisit repairReturnVisit = repairReturnVisitManager.findBy(repairBill.getId());


                int commentStar = 0 ; //评价星级
                if (null != repairBillComment) {
                    //commentTotal++;
                    //allCommentStars += repairBillComment.getStar() == null ?
                    //        5 : repairBillComment.getStar().intValue(); //默认5星

                    commentStar = repairBillComment.getStar() == null ? 5 : repairBillComment.getStar().intValue();
                }

                int returnVisitStar = 0 ; //回访星级
                if(null != repairReturnVisit){
                    returnVisitStar = repairReturnVisit.getStar() == null ? 5 : repairReturnVisit.getStar().intValue();
                }

                if(commentStar != 0 || returnVisitStar != 0){
                    commentTotal++;

                    Integer returnStar = commentStar >  returnVisitStar ? commentStar : returnVisitStar;
                    allCommentStars += returnStar; //工单星级

                }

            }

            //平均接单耗时 -1
            if(dto.getBillSingleTotal() > 0){

                LOG.info("===>singleMinutes:{}"+ singleMinutes);
                LOG.info("===>billSingleTotal:{}"+ dto.getBillSingleTotal());

                BigDecimal avgBillTime =new BigDecimal(singleMinutes).
                        divide(new BigDecimal("60"),2, BigDecimal.ROUND_HALF_UP).divide(new BigDecimal(dto.getBillSingleTotal()),2, BigDecimal.ROUND_HALF_UP);


                dto.setAvgBillTime(avgBillTime);
            }else{
                dto.setAvgBillTime(BigDecimal.ZERO);
            }

            //平均完成耗时 -2
            if(dto.getBillStatus8Total() > 0){

                LOG.info("===>completedMinutes:{}"+ completedMinutes);
                LOG.info("===>billStatus8Total:{}"+ dto.getBillStatus8Total());

                BigDecimal avgCompleteTime =new BigDecimal(completedMinutes).
                        divide(new BigDecimal("60"),2, BigDecimal.ROUND_HALF_UP).divide(new BigDecimal(dto.getBillStatus8Total()),2, BigDecimal.ROUND_HALF_UP);

                dto.setAvgCompleteTime(avgCompleteTime);
            }else{
                dto.setAvgCompleteTime(BigDecimal.ZERO);
            }


            //完成率  已完成/总工单 X 100
            if (dto.getAllBillTotal() > 0) {

                BigDecimal fillRate = new BigDecimal(dto.getBillStatus8Total())
                        .divide(new BigDecimal(dto.getAllBillTotal()),
                                2, BigDecimal.ROUND_HALF_UP);

                dto.setFillRate(fillRate.multiply(new BigDecimal(100)).intValue());
            } else {
                dto.setFillRate(0);
            }


            //耗时 已完成的总耗时/已完成单数
            if (dto.getBillStatus8Total() > 0) {
                dto.setJumpingTime(new BigDecimal(hours).divide(
                        new BigDecimal(dto.getBillStatus8Total()),
                        2, BigDecimal.ROUND_HALF_UP).doubleValue());
            } else {
                dto.setJumpingTime(0.0d);
            }

            //平均评星 总评星数/总评价单数
            if (commentTotal > 0) {
                dto.setKi(new BigDecimal(allCommentStars).divide(
                        new BigDecimal(commentTotal), 2, BigDecimal.ROUND_HALF_UP).doubleValue());
            } else {
                dto.setKi(0.0d);
            }
            
            if(BigDecimal.ZERO.compareTo(todayCreate) != 0){
            	BigDecimal fillTodayEndRate=todayEnd.divide(todayCreate,2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")).setScale(2,BigDecimal.ROUND_HALF_UP);
            	DecimalFormat df = new DecimalFormat("###.##");
            	dto.setFillTodayEndRate(new BigDecimal(df.format(fillTodayEndRate)));
            }

            //总工程人员数
            List<User> users = userRepairTypeManager.findBy(billRepairType);
            dto.setManagerTotal(users == null ? 0 : users.size());
        }
        return dto;
    }

    public String setPath(String fileName) {
        String classpath = getClass().getResource("/").getPath();
        LOG.info("begin exportExcel  classpath:" + classpath);
        if (StringUtils.isNotEmpty(classpath)) {
            LOG.info("begin exportExcel  CLIENTNO:" + CLIENTNO);
            if ("dev".equals(CLIENTNO)) {
                String str = classpath.substring(0, 1);
                if ("/".equals(str)) {
                    classpath = classpath.replaceFirst("/", "");
                }
            }
        }
        LOG.info("path:" + classpath);
        String webappRoot = classpath.replaceAll("WEB-INF/classes", "");
        LOG.info("path:" + webappRoot);
        //"upload/OrderExcel.xls"
        String path = webappRoot + fileName;
        if (StringUtils.isNotEmpty(path)) {
            path = path.replace("//", "/");
        }

        LOG.info("path:" + path);
        return path;
    }

    public String exportExcelDataRecodeExcel(List<RepairBillStateStatisticsDto> list, String sheetName, String[] titles, String[] fieldNames) throws IOException {
        HSSFWorkbook wb = new HSSFWorkbook();
        String path = setPath("upload/repairStatus.xls");
        File file = new File(new ExcelUtils().getPath(path));
        System.out.println("path:" + path);

        ExcelUtils.exportExcel(file, wb, sheetName, list, titles, fieldNames);
        return path;
    }

    /**
     * 查询项目绑定的所有小类
     *
     * @param orgId
     * @return
     */
    private List<Element> getRepairTypeList(Integer orgId) {
        List<Element> elementList = new ArrayList<>();
        //大类
        List<ElementDto> elementDtos = elementGroupManager.getOrgElementGroupInfoV2(String.valueOf(orgId), Constants.REPAIR_TYPE_CODE);
        if (null != elementDtos && elementDtos.size() > 0) {
            for (ElementDto elementDto :
                    elementDtos) {
                //小类
                List<Element> repairTypeaDetailGroup = elementGroupManager.getElementsByGroupName(elementDto.getItemcode());
                if (null != repairTypeaDetailGroup && repairTypeaDetailGroup.size() > 0) {
                    elementList.addAll(repairTypeaDetailGroup);
                }
            }
        }
        return elementList;
    }

    @Override
    public Page getRepairBillBoard(String orgIds, Integer pageSize, Integer pageNo) {

        Map<String, Object> conditions = new HashedMap();
        conditions.put("orgIds", orgIds);
        Page page = repairBillManager.findBordPage(conditions, pageSize, pageNo);

        return page;
    }


	/**
	 * 获取微信端创建的所有工单数、收费数、费用
	 * @param orgId
	 * @param virtId
	 * @param type
	 * @param date
	 * @param endDate
	 * @return
	 */
	@Override
	public Page getAllWxOrder(Map<String, Object> conditions, int type,
			int pageNo, int pageSize) {
		return repairBillManager.getAllWxOrder(conditions, type, pageNo, pageSize);
	}

	/**
	 * 获取订单明细
	 * @param orgId
	 * @param virtId
	 * @param isFree  ==1获取所有工单数的明细 ==0获取收费工单数的明细
	 * @param type
	 * @param date
	 * @param endDate
	 * @return
	 */
	@Override
	public Page getWxAmountOrder(Map<String, Object> conditions, int isFree,
			int type, int pageNo, int pageSize) {
		return repairBillManager.getWxAmountOrder(conditions, isFree, type, pageNo, pageSize);
	}

	/**
	 * 导出企业订单统计
	 */
	@Override
	public AppResultDto exportAllWxOrderStatistics(Map<String, Object> conditions,int type) {
		LOG.info("begin exportAllWxOrderStatistics/conditions:"+JsonUtils.toJson(conditions));
		HSSFWorkbook wb = new HSSFWorkbook();
		List<Map<String,Object>> mapList=repairBillManager.getExportAllWxOrder(conditions, type);
		String path=orderDinnerService.setPath("upload/RepairExcel.xls");
		LOG.info("begin exportAllWxOrderStatistics/path:"+path);
		try {
			if(mapList!=null&&mapList.size()>0){
				String sheetName="企业订单统计";
				File file =new File( new ExcelUtils().getPath(path));
				String[] titles={"项目","企业","统计时间","总工单数","收费工单数","总费用"};
				String [] fieldNames={"orgName","virtName","dateInfo","sumCount","amountCount","sumAmount"};
				ExcelUtils.exportExcel(file,wb, sheetName, mapList, titles, fieldNames);
			}
		} catch (Exception e) {
			LOG.error(e.getMessage());
			e.printStackTrace();
			return AppResultUtil.createErrorDto("100", "导出异常");
		}
		return AppResultUtil.createSuccesDto(path);
	}
	/**
	 * 导出企业订单明细统计
	 */
	@Override
	public AppResultDto exportWxAmountOrderStatistics(Map<String, Object> conditions,int isFree,int type) {
		LOG.info("begin exportWxAmountOrderStatistics/conditions:"+JsonUtils.toJson(conditions));
		HSSFWorkbook wb = new HSSFWorkbook();
		List<Map<String,Object>> mapList=repairBillManager.getExportWxAmountOrder(conditions, isFree, type);
		String path=orderDinnerService.setPath("upload/RepairAmountExcel.xls");
		LOG.info("begin exportWxAmountOrderStatistics/path:"+path);
		try {
			if(mapList!=null&&mapList.size()>0){
				String sheetName="企业订单明细统计";
				File file =new File( new ExcelUtils().getPath(path));
				String[] titles={"企业","订单号","报修时间","下单人","联系方式","耗材","总费用"};
				String [] fieldNames={"virtName","number","createTime","repairUser","contactWay","material","repairCost"};
				ExcelUtils.exportExcel(file,wb, sheetName, mapList, titles, fieldNames);
			}
		} catch (Exception e) {
			LOG.error(e.getMessage());
			e.printStackTrace();
			return AppResultUtil.createErrorDto("100", "导出异常");
		}
		return AppResultUtil.createSuccesDto(path);
	}

    @Override
    public Page getPeoplecOrderList(Map<String, Object> conditions, int type,int pageNo, int pageSize) {
        return repairBillManager.getPeoplecOrderList(conditions, type, pageNo, pageSize);
    }

    @Override
    public WebPageResultDto getPeoplecOrderListExcel(List<Map<String, Object>> list) throws IOException {

        String sheetName;
        if (list != null && list.size() > 0) {
            sheetName = "人员工单统计";
            String[] titles = {
                    "运营中心","项目","人员","时间","总接单数","待完成","已完成","完成率","协办单","协办率","转单","转单率","挂单","挂单率","差评数","差评率"
              };

            String[] fieldNames = {
                    "centerName",
                    "orgName",
                    "serverName",
                    "dateInfo",
                    "totalServerNum",
                    "unFinishedNum",
                    "completeNum",
                    "completeRate",
                    "supportUserNum",
                    "supportUserRate",
                    "turnNum",
                    "turnRate",
                    "hangNum",
                    "hangRate",
                    "negativeNum",
                    "negativeRate"
             };

            String path = exportPeoplecOrderListExcel(list, sheetName, titles, fieldNames);
            return new WebPageResultDto("200", "成功", path);
        } else {
            return new WebPageResultDto("100", "数据为空，无法导出", null);
        }
    }

    @Override
    public WebPageResultDto getBillCommentListExcel(List<Map<String, Object>> list) throws IOException {

        String sheetName;
        if (list != null && list.size() > 0) {
            sheetName = "工单评价统计";
            String[] titles = {
                    "运营中心","项目","时间","平均星级","五星工单数","四星工单数","三星工单数","二星工单数","一星工单数"
            };

            String[] fieldNames = {
                    "centerName",
                    "orgName",
                    "dateInfo",
                    "avgStar",
                    "fiveStar",
                    "fourStar",
                    "threeStar",
                    "twoStar",
                    "oneStar"
            };

            String path = exportBillCommentListExcel(list, sheetName, titles, fieldNames);
            return new WebPageResultDto("200", "成功", path);
        } else {
            return new WebPageResultDto("100", "数据为空，无法导出", null);
        }
    }

    @Override
    public Page getBillCommentList(Map<String, Object> conditions, int type, int pageNo, int pageSize) {
        return repairBillManager.getBillCommentList(conditions, type, pageNo, pageSize);
    }

    public String exportPeoplecOrderListExcel(List<Map<String, Object>> list, String sheetName, String[] titles, String[] fieldNames) throws IOException {

	    HSSFWorkbook wb = new HSSFWorkbook();
        String path = setPath("upload/peopleOrderList.xls");
        File file = new File(new ExcelUtils().getPath(path));
        System.out.println("path:" + path);

        ExcelUtils.exportExcel(file, wb, sheetName, list, titles, fieldNames);
        return path;
    }




    public String exportBillCommentListExcel(List<Map<String, Object>> list, String sheetName, String[] titles, String[] fieldNames) throws IOException {

        HSSFWorkbook wb = new HSSFWorkbook();
        String path = setPath("upload/billCommentList.xls"); //工单评价统计
        File file = new File(new ExcelUtils().getPath(path));
        System.out.println("path:" + path);

        ExcelUtils.exportExcel(file, wb, sheetName, list, titles, fieldNames);
        return path;
    }
}
