package com.app.service.order;

import com.app.constant.SchoolConstant;
import com.app.dto.basics.GradeClassDto;
import com.app.dto.order.OpenCourseOrderExportDto;
import com.app.dto.order.operation.ExportOrderDto;
import com.app.entity.basics.OpenCourse;
import com.app.entity.order.OpenCourseRefund;
import com.app.mapper.order.OpenCourseOrderMapper;
import com.app.mapper.order.OpenCourseRefundMapper;
import com.app.service.basics.OpenCourseService;
import com.app.service.basics.SchoolService;
import com.app.util.DateUtil;
import com.app.util.file.ExcelUtil;
import com.app.util.file.FileUtil;
import com.app.util.file.ZipUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OpenCourseOrderExportService {

    @Value("${file.path}")
    private String filePath;

    @Autowired
    private SchoolService schoolService;

    @Autowired
    private OpenCourseService openCourseService;

    @Autowired
    private OpenCourseOrderMapper openCourseOrderMapper;

    @Autowired
    private OpenCourseRefundMapper openCourseRefundMapper;

    @Autowired
    private FileUtil fileUtil;

    @Autowired
    private ExcelUtil excelUtil;

    @Autowired
    private ZipUtil zipUtil;

    /**
     * 功能描述：导出交易订单
     *
     * @param exportOrderDto
     */
    public void exportOrderExcel(ExportOrderDto exportOrderDto, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Integer schoolYear = exportOrderDto.getSchoolYear();
        Integer semester = exportOrderDto.getSemester();
        String schoolName = schoolService.findById(exportOrderDto.getSchoolId()).get().getName();

        String downloadPath = filePath + File.separator + "download";
        String folderName = DateUtil.format(new Date(), DateUtil.yyyyMMddHHmmss); // 批量导出保存至该文件夹目录（后续通过打包zip该目录进行下载文件）
        String filePath = downloadPath + File.separator + folderName;
        String fileName = String.format("%s学年-第%s学期-%s.xlsx", schoolYear, semester, schoolName);
        String sheetName = String.format("%s学年-第%s学期-%s.xlsx", schoolYear, semester, schoolName);
        List<String> titleName = new ArrayList() {{
            add("学年");
            add("学期");
            add("学校名称");
            add("年级");
            add("班级");
            add("年级班级");
            add("学生姓名");
            add("家长手机号码");
            add("下课回家方式");
            add("课程名称");
            add("课程价格");
            add("上课星期");
            add("上课时间");
            add("家长标识");
            add("订单标识");
            add("订单项标识");
            add("微信支付订单号");
        }};

        /* 总表 */
        List<OpenCourseOrderExportDto> list = openCourseOrderMapper.exportAll(schoolYear, semester, exportOrderDto.getSchoolId());
        List<List<String>> exportData = getExportData(list);
        excelUtil.createExcel(filePath, fileName, sheetName, titleName, exportData, request, response);

        /* 拆开两个维度Excel（自然班，兴趣班） */
        /* 自然班 */
        List<GradeClassDto> gradeClassDtoList = schoolService.findByGradeClass(exportOrderDto.getSchoolId());
        for (GradeClassDto gradeClassDto : gradeClassDtoList) {
            fileName = String.format("%s学年-第%s学期-%s-%s-%s.xlsx", schoolYear, semester, schoolName, gradeClassDto.getGradeName(), gradeClassDto.getClassName());
            sheetName = String.format("%s学年-第%s学期-%s-%s-%s.xlsx", schoolYear, semester, schoolName, gradeClassDto.getGradeName(), gradeClassDto.getClassName());

            List<OpenCourseOrderExportDto> _list = list.stream().filter(dto ->
                    /* 年级名称 && 班级名称 */
                    gradeClassDto.getGradeName().equals(dto.getGradeName()) && gradeClassDto.getClassName().equals(dto.getClassName())
            ).collect(Collectors.toList());
            if (_list.size() == 0) {
                continue;
            }

            exportData = getExportData(_list);
            excelUtil.createExcel(filePath + File.separator + "行政班", fileName, sheetName, titleName, exportData, request, response);
        }

        /* 兴趣班 */
        List<OpenCourse> openCourseList = openCourseService.findBySchoolId(schoolYear, semester, exportOrderDto.getSchoolId());
        for (OpenCourse openCourse : openCourseList) {
            fileName = String.format("%s学年-第%s学期-%s-%s-%s-%s.xlsx", schoolYear, semester, schoolName, openCourse.getName(), openCourse.getCycle(), openCourse.getHours().replace(":", ""));
            sheetName = String.format("%s学年-第%s学期-%s-%s-%s-%s.xlsx", schoolYear, semester, schoolName, openCourse.getName(), openCourse.getCycle(), openCourse.getHours().replace(":", ""));

            List<OpenCourseOrderExportDto> _list = list.stream().filter(dto ->
                    /* 开课标识 && 星期x && 时间段 */
                    openCourse.getId().equals(dto.getOpenCourseId()) && openCourse.getCycle().equals(dto.getCycle()) && openCourse.getHours().equals(dto.getHours())
            ).collect(Collectors.toList());
            if (_list.size() == 0) {
                continue;
            }

            exportData = getExportData(_list);
            excelUtil.createExcel(filePath + File.separator + "兴趣班", fileName, sheetName, titleName, exportData, request, response);
        }

        String zipName = String.format("%s学年-第%s学期-%s-%s.zip", schoolYear, semester, schoolName, folderName);
        String comment = String.format("%s学年-第%s学期-%s-%s", schoolYear, semester, schoolName, folderName);
        zipUtil.zip(filePath, zipName, comment);
        fileUtil.closeStream(new File(downloadPath + File.separator + zipName), request, response);
    }

    /**
     * 功能描述：根据订单课程对象转译Excel导出数据格式
     * 字段顺序与标题顺序一致！！！
     *
     * @param list
     * @return
     */
    private List<List<String>> getExportData(List<OpenCourseOrderExportDto> list) {
        List<List<String>> excelData = new ArrayList<>();
        list.forEach(openCourseOrderExportDto -> {
            excelData.add(new ArrayList<String>() {{
                add(openCourseOrderExportDto.getSchoolYear().toString()); // 学年
                add(openCourseOrderExportDto.getSemester().toString()); // 学期
                add(openCourseOrderExportDto.getSchoolName()); // 学校名称
                add(openCourseOrderExportDto.getGradeName()); // 年级
                add(openCourseOrderExportDto.getClassName()); // 班级
                add(SchoolConstant.formatSchoolClass(openCourseOrderExportDto.getGradeName(), openCourseOrderExportDto.getClassName())); // 年级班级（阿拉伯数字）
                add(openCourseOrderExportDto.getChildName()); // 学校姓名
                add(openCourseOrderExportDto.getPhoneNumber()); // 家长收集好吗
                add(openCourseOrderExportDto.getGoHome()); // 下课回家方式
                add(openCourseOrderExportDto.getOpenCourseName()); // 课程名称
                add(String.format("%.2f", openCourseOrderExportDto.getOpenCoursePrice())); // 课程价格
                add(openCourseOrderExportDto.getCycle()); // 上课星期
                add(openCourseOrderExportDto.getHours()); // 上课时间
                add(openCourseOrderExportDto.getAccountId()); // 家长标识
                add(openCourseOrderExportDto.getOpenCourseOrderId()); // 订单标识
                add(openCourseOrderExportDto.getOpenCourseOrderItemId()); // 订单项标识
                add(openCourseOrderExportDto.getTransactionId()); // 微信支付订单号
            }});
        });

        return excelData;
    }

    /**
     * 功能描述：导出退费订单
     *
     * @param exportOrderDto
     */
    public void exportRefundExcel(ExportOrderDto exportOrderDto, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Integer schoolYear = exportOrderDto.getSchoolYear();
        Integer semester = exportOrderDto.getSemester();
        String schoolName = schoolService.findById(exportOrderDto.getSchoolId()).get().getName();

        String downloadPath = filePath + File.separator + "download";
        String folderName = DateUtil.format(new Date(), DateUtil.yyyyMMddHHmmss); // 批量导出保存至该文件夹目录（后续通过打包zip该目录进行下载文件）
        String filePath = downloadPath + File.separator + folderName;
        String fileName = String.format("%s学年-第%s学期-%s-退课.xlsx", schoolYear, semester, schoolName);
        String sheetName = String.format("%s学年-第%s学期-%s-退课.xlsx", schoolYear, semester, schoolName);
        List<String> titleName = new ArrayList() {{
            add("学年");
            add("学期");
            add("学校名称");
            add("年级");
            add("班级");
            add("年级班级");
            add("学生姓名");
            add("家长手机号码");
            add("课程名称");
            add("课程价格");
            add("上课星期");
            add("上课时间");
            add("状态");
            add("家长标识");
            add("订单标识");
            add("订单项标识");
            add("微信支付订单号");
            add("微信退款单号");
        }};

        /* 总表 */
        List<OpenCourseRefund> list = openCourseRefundMapper.selectList(new QueryWrapper<OpenCourseRefund>().lambda()
                .eq(OpenCourseRefund::getSchoolYear, schoolYear)
                .eq(OpenCourseRefund::getSemester, semester)
                .eq(OpenCourseRefund::getSchoolId, exportOrderDto.getSchoolId())
                .orderByDesc(OpenCourseRefund::getId)
        );
        List<List<String>> exportData = getExportRefundData(list);
        excelUtil.createExcel(filePath, fileName, sheetName, titleName, exportData, request, response);

        String zipName = String.format("%s学年-第%s学期-%s-%s-退课.zip", schoolYear, semester, schoolName, folderName);
        String comment = String.format("%s学年-第%s学期-%s-%s-退课", schoolYear, semester, schoolName, folderName);
        zipUtil.zip(filePath, zipName, comment);
        fileUtil.closeStream(new File(downloadPath + File.separator + zipName), request, response);
    }

    /**
     * 功能描述：根据订单课程对象转译Excel导出数据格式
     * 字段顺序与标题顺序一致！！！
     *
     * @param list
     * @return
     */
    private List<List<String>> getExportRefundData(List<OpenCourseRefund> list) {
        List<List<String>> excelData = new ArrayList<>();
        list.forEach(refund -> {
            excelData.add(new ArrayList<String>() {{
                add(refund.getSchoolYear().toString()); // 学年
                add(refund.getSemester().toString()); // 学期
                add(refund.getSchoolName()); // 学校名称
                add(SchoolConstant.formatGradeName(refund.getGradeName())); // 年级
                add(SchoolConstant.formatClassName(refund.getClassName())); // 班级
                add(SchoolConstant.formatSchoolClass(refund.getGradeName(), refund.getClassName())); // 年级班级（阿拉伯数字）
                add(refund.getChildName()); // 学生姓名
                add(refund.getPhoneNumber()); // 家长手机号码
                add(refund.getOpenCourseName()); // 课程名称
                add(String.format("%.2f", refund.getOpenCoursePrice())); // 课程价格
                add(refund.getOpenCourseCycle()); // 星期X
                add(refund.getOpenCourseHours()); // 时间段

                /* 订单退款审核状态 */
                if (null == refund.getState()) {
                    add("");
                } else {
                    if (refund.getState().intValue() == -1) {
                        add("未通过");
                    } else if (refund.getState().intValue() == 0) {
                        add("待审核");
                    } else if (refund.getState().intValue() == 1) {
                        add("已通过");
                    } else {
                        add(refund.getState().toString());
                    }
                }

                add(refund.getGuardianId()); // 家长标识
                add(refund.getOpenCourseOrderId()); // 订单标识
                add(refund.getOpenCourseOrderItemId()); // 订单项标识
                add(refund.getTransactionId()); // 微信支付订单号
                add(refund.getRefundId()); // 微信退款单号
            }});
        });

        return excelData;
    }

    public List<OpenCourseOrderExportDto> findByOpenCourseId(String openCourseId) {
        return openCourseOrderMapper.findByOpenCourseId(openCourseId);
    }

}
