package com.xxfc.platform.order.biz;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageInfo;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xxfc.platform.order.contant.enumerate.AccountTypeEnum;
import com.xxfc.platform.order.contant.enumerate.BookkeepingTypeEnum;
import com.xxfc.platform.order.contant.enumerate.OrderTypeEnum;
import com.xxfc.platform.order.pojo.Achievement;
import com.xxfc.platform.order.pojo.QueryCriteria;
import com.xxfc.platform.order.pojo.ReturnOrderAmount;
import com.xxfc.platform.order.pojo.TotalOrderRevenue;
import com.xxfc.platform.order.pojo.account.OrderAccountDetail;
import io.swagger.models.auth.In;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 总业绩报表service层
 *
 * @author Administrator
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TotalPerformanceBiz {
    private final BaseOrderBiz baseOrderBiz;
    private final OrderAccountBiz accountBiz;


    /**
     * 入账数据统计
     *
     * @param queryCriteria 查询条件
     */
    public TotalOrderRevenue entryStatisticalData(QueryCriteria queryCriteria) {

        //获取总数据
        TotalOrderRevenue totalOrderRevenue = incomeDataProcessing(queryCriteria);
        //设置订单明细并分页
        getAchievementPageInfo(totalOrderRevenue, queryCriteria);
        return totalOrderRevenue;
    }

    /**
     * 核算总收益
     *
     * @param queryCriteria
     * @return
     */
    private TotalOrderRevenue incomeDataProcessing(QueryCriteria queryCriteria) {
        List<Achievement> achievements = baseOrderBiz.entryStatisticalData(queryCriteria);

        if (CollectionUtil.isEmpty(achievements)) {
            return new TotalOrderRevenue();
        }
        //应收总额
        BigDecimal totalReceivables = BigDecimal.ZERO;
        //优惠总额
        BigDecimal discount = BigDecimal.ZERO;
        //实收总额
        BigDecimal actual = BigDecimal.ZERO;
        for (Achievement achievement : achievements) {
            totalReceivables = totalReceivables.add(achievement.getOrderAmount());
            actual = actual.add(achievement.getRealAmount());
            discount = discount.add(achievement.getOrderAmount().subtract(achievement.getRealAmount()));
        }
        return TotalOrderRevenue
                .builder()
                .orderSum(achievements.size())
                .totalReceivables(totalReceivables)
                .discount(discount)
                .actual(actual)
                .build();

    }

    /**
     * 设置支出明细
     *
     * @param totalOrderRevenue
     * @param queryCriteria     条件
     */
    private void getAchievementPageInfo(TotalOrderRevenue totalOrderRevenue, QueryCriteria queryCriteria) {
        PageInfo<Achievement> achievementPageInfo = baseOrderBiz.getAchievementPageInfo(queryCriteria);
        totalOrderRevenue.setAchievements(achievementPageInfo);
    }


    /**
     * 获取支出明细
     *
     * @param queryCriteria
     * @return
     */
    public List<ReturnOrderAmount> outStatisticalData(QueryCriteria queryCriteria) {

        List<ReturnOrderAmount> returnOrderAmounts = accountBiz.outStatisticalData(queryCriteria);
        if (CollectionUtils.isEmpty(returnOrderAmounts)) {
            return Lists.newArrayList();
        }
        //拆分明细
        return splitReturnOrderAmountList(returnOrderAmounts);
    }

    /**
     * 进行对支出记录拆分,拆分为-押金、订单和违章
     *
     * @param returnOrderAmounts
     * @return
     */
    private List<ReturnOrderAmount> splitReturnOrderAmountList(List<ReturnOrderAmount> returnOrderAmounts) {
        ArrayList<ReturnOrderAmount> arrayList = Lists.newArrayList();
        //进行遍历拆分出-押金、订单和违章
        for (ReturnOrderAmount returnOrderAmount : returnOrderAmounts) {
            OrderAccountDetail accountDetailStr = returnOrderAmount.getAccountDetail();
            //押金退还金额
            BigDecimal depositAmount = accountDetailStr.getDepositAmount();
            //订单退还
            BigDecimal orderAmount = accountDetailStr.getOrderAmount();
            if (OrderTypeEnum.RENT_VEHICLE.getCode().equals(returnOrderAmount.getTypeInt())&&depositAmount.compareTo(BigDecimal.ZERO) > 0) {
                //判断押金退还是否大于0
                    ReturnOrderAmount returnOrderAmountClone = ObjectUtil.clone(returnOrderAmount);
                    //判断是违章还是租车
                    if (AccountTypeEnum.OUT_RESIDUE_DEPOSIT.getCode().equals(returnOrderAmount.getAccountType())) {
                        returnOrderAmountClone.setRefundInstruction("违章押金");
                        returnOrderAmountClone.setRefundAmount(accountDetailStr.getDepositAmount());
                    } else {
                        returnOrderAmountClone.setRefundInstruction("租车押金");
                        returnOrderAmountClone.setRefundAmount(accountDetailStr.getDepositAmount());
                    }
                    arrayList.add(returnOrderAmountClone);

            }

            //判断订单退款是否大于0
            if (orderAmount.compareTo(BigDecimal.ZERO) > 0) {
                ReturnOrderAmount returnOrderAmountClone = ObjectUtil.clone(returnOrderAmount);
                returnOrderAmountClone.setRefundInstruction("订单退款");
                returnOrderAmountClone.setRefundAmount(accountDetailStr.getOrderAmount());
                arrayList.add(returnOrderAmountClone);
            }

        }
        return arrayList;
    }


    /**
     * 导出入账记录
     *
     * @param queryCriteria
     * @param name
     * @param outputStream
     */
    public void exportEntry(QueryCriteria queryCriteria, String name, ServletOutputStream outputStream) throws IOException {

        XSSFWorkbook wb = new XSSFWorkbook();
        XSSFSheet sheet = wb.createSheet("收入");
        CellStyle generalCellStyle = createGeneralCellStyle(wb);
        XSSFRow row1 = sheet.createRow(0);
        String[] head = new String[]{"下单时间", "订单ID", "订单类型", "应收金额", "优惠金额", "实收金额", "客户姓名", "客户手机号", "邀约人/身份", "要约人手机号", "业绩所属公司", "支付方式"};
        createHeader(row1, head, generalCellStyle);
        List<Achievement> achievements = baseOrderBiz.entryStatisticalData(queryCriteria);
        if (CollectionUtil.isEmpty(achievements)) {
            throw new BaseException("无数据");
        }
        //计算合计
        HashMap<Integer, BigDecimal> map = Maps.newHashMap();


        List<String[]> achievementArray = getAchievementArrays(achievements, 12,map);
        createCellData(sheet, 1, generalCellStyle, achievementArray);


        //设置最后一行
        int lastRowNum = sheet.getLastRowNum();
        XSSFRow rown = sheet.createRow(lastRowNum);
        //设置第一列
        XSSFCell cell1 = rown.createCell(0);
        cell1.setCellValue("合计");
        //第五列求和
        int[] cel = new int[]{3, 4, 5};
        sum(rown, cel,map);
        wb.write(outputStream);
        wb.close();
    }


    public void sum(XSSFRow row, int[] cel, Map<Integer, BigDecimal> map) {
        for (int i = 0; i < cel.length; i++) {
//            String colString = CellReference.convertNumToColString(i);
//            //该求和公式的意思就是：sum（第几列+第几个 ： 第几列+需要累计到的第几个单元格位置）
//            String sumstring = "SUM(" + colString + "2:" + colString + (lastRowNum) + ")";
//            sheet.getRow(lastRowNum).createCell(i).setCellFormula(sumstring);
            XSSFCell cell = row.createCell(cel[i]);
            cell.setCellValue(map.get(i).toString());
        }

    }

    /**
     * 获取入账数组
     *
     * @param achievements
     * @param length
     * @return
     */
    private List<String[]> getAchievementArrays(List<Achievement> achievements, int length, Map<Integer, BigDecimal> map) {
        BigDecimal totalReceivable =BigDecimal.ZERO;
        BigDecimal totalReality =BigDecimal.ZERO;
        BigDecimal totalDiscount =BigDecimal.ZERO;
        ArrayList<String[]> arrayList = Lists.newArrayList();
        for (Achievement achievement : achievements) {
            String[] data = new String[length];
            data[0] = achievement.getCrtTime();
            data[1] = achievement.getNo();
            data[2] = achievement.getType();
            data[3] = achievement.getOrderAmount().toString();
            totalReceivable=totalReceivable.add(achievement.getOrderAmount());
            data[4] = achievement.getFavorablePrice().toString();
            totalReality=totalReality.add(achievement.getFavorablePrice());
            data[5] = achievement.getRealAmount().toString();
            totalDiscount=totalDiscount.add(achievement.getRealAmount());
            data[6] = achievement.getRealname();
            data[7] = achievement.getUsername();
            data[8] = String.format("%s/%s", achievement.getParentRealname() == null ? "" : achievement.getParentRealname(), achievement.getPositionName() == null ? "" : achievement.getPositionName());
            data[9] = achievement.getParentUsername();
            data[10] = achievement.getCompanyName();
            data[11] = achievement.getPayWay();
            arrayList.add(data);
        }
        map.put(0,totalReceivable);
        map.put(1,totalReality);
        map.put(2,totalDiscount);


        return arrayList;
    }


    /**
     * 导出支出
     *
     * @param queryCriteria
     * @param name
     * @param outputStream
     */
    public void exportAccount(QueryCriteria queryCriteria, String name, ServletOutputStream outputStream) throws IOException {
        XSSFWorkbook wb = new XSSFWorkbook();
        XSSFSheet sheet = wb.createSheet("支出");
        CellStyle generalCellStyle = createGeneralCellStyle(wb);

        XSSFRow row1 = sheet.createRow(0);
        String[] head = new String[]{"退款日期", "订单ID", "订单类型", "退还类型", "退还押金", "客户名", "客户手机号"};
        createHeader(row1, head, generalCellStyle);

        HashMap<String, BigDecimal> map = Maps.newHashMap();

        List<ReturnOrderAmount> returnOrderAmounts = outStatisticalData(queryCriteria);
        List<String[]> achievementArray = getReturnOrderAmountArrays(returnOrderAmounts, 7,map);
        if (CollectionUtil.isEmpty(achievementArray)) {
            throw new BaseException("无数据");
        }
        createCellData(sheet, 1, generalCellStyle, achievementArray);

        //设置最后一行
        int lastRowNum = sheet.getLastRowNum();
        XSSFRow rown = sheet.createRow(lastRowNum);
        //设置第一列
        XSSFCell cell1 = rown.createCell(0);
        cell1.setCellValue("合计");
        cell1.setCellStyle(generalCellStyle);
        //第五列求和
//        String colString = CellReference.convertNumToColString(4);
//        //该求和公式的意思就是：sum（第几列+第几个 ： 第几列+需要累计到的第几个单元格位置）
//        String sumstring = "SUM(" + colString + "2:" + colString + (lastRowNum) + ")";
        XSSFCell cell = sheet.getRow(lastRowNum).createCell(4);
        cell.setCellValue(map.get("totalRefund").toString());
        cell.setCellStyle(generalCellStyle);
        wb.write(outputStream);
        wb.close();
    }

    /**
     * 获取支出数组
     *
     * @param returnOrderAmounts
     * @param length
     * @return
     */
    private List<String[]> getReturnOrderAmountArrays(List<ReturnOrderAmount> returnOrderAmounts, int length,Map<String,BigDecimal> map) {
        BigDecimal totalRefund = BigDecimal.ZERO;
        ArrayList<String[]> arrayList = Lists.newArrayList();
        for (ReturnOrderAmount returnOrderAmount : returnOrderAmounts) {
            String[] data = new String[length];
            data[0] = returnOrderAmount.getTime();
            data[1] = returnOrderAmount.getNo();
            data[2] = returnOrderAmount.getType();
            data[3] = returnOrderAmount.getRefundInstruction();
            data[4] = returnOrderAmount.getRefundAmount().toString();
            totalRefund=totalRefund.add(returnOrderAmount.getRefundAmount());
            data[5] = returnOrderAmount.getRealname();
            data[6] = returnOrderAmount.getUsername();
            arrayList.add(data);
        }
        map.put("totalRefund",totalRefund);
        return arrayList;
    }


    private CellStyle createGeneralCellStyle(XSSFWorkbook wb) {
        CellStyle cellStyleGeneral = createHeaderCellStyle(wb);
        cellStyleGeneral.setWrapText(true);
        XSSFFont generalFont = createFont(wb);
        generalFont.setBold(false);
        cellStyleGeneral.setFont(generalFont);
        return cellStyleGeneral;
    }


    private void createHeader(Row row, String[] header, CellStyle cellStyle) {
        for (int i = 0; i < header.length; i++) {
            Cell cell = row.createCell(i);
            cell.setCellValue(header[i]);
            cell.setCellStyle(cellStyle);
        }
    }

    private CellStyle createHeaderCellStyle(XSSFWorkbook wb) {
        XSSFCellStyle cellStyleHeader = wb.createCellStyle();
        XSSFDataFormat dataFormat = wb.createDataFormat();
        cellStyleHeader.setDataFormat(dataFormat.getFormat("#,##0.00"));
        cellStyleHeader.setAlignment(HorizontalAlignment.CENTER);
        cellStyleHeader.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyleHeader.setLocked(false);
        cellStyleHeader.setBorderBottom(CellStyle.BORDER_THIN);
        cellStyleHeader.setBorderLeft(CellStyle.BORDER_THIN);
        cellStyleHeader.setBorderTop(CellStyle.BORDER_THIN);
        cellStyleHeader.setBorderRight(CellStyle.BORDER_THIN);

        XSSFFont headerFont = createFont(wb);
        cellStyleHeader.setFont(headerFont);

        return cellStyleHeader;
    }


    private XSSFFont createFont(XSSFWorkbook wb) {
        XSSFFont font = wb.createFont();
        font.setFontName("黑体");
        font.setBold(true);
        return font;
    }

    private void createCellData(Sheet sheet, int startRowIndex, CellStyle cellStyle, List<String[]> memberOrderList) {

        for (String[] data : memberOrderList) {
            Row row = sheet.createRow(startRowIndex++);
            createHeader(row, data, cellStyle);
        }
    }




}
