package com.app.ydl.yiliao.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.WorkbookUtil;
import com.app.framework.core.support.controller.CrudControllerSupport;
import com.app.framework.core.utils.db.DBUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.util.*;

/**
 * 医疗导数据
 */
@Controller
@RequestMapping("/yiliao")
public class YiliaoController extends CrudControllerSupport {

    @Resource
    SqlSessionFactory sqlSessionFactory;

    @RequestMapping(value = "/export")
    public ModelAndView info(HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();
        return new ModelAndView("admin/business/yiliao/export.html", result);
    }

    /**
     * 问诊订单
     */
    @RequestMapping(value = "/export/inquiry")
    @DS("ydl_yiliao")
    public void export(HttpServletResponse response, String startDate, String endDate) throws Exception {
        String header[] = new String[]{"问诊订单ID", "医生ID", "医生UID", "用户UID", "问诊类型 1:图文问诊  2:电话问诊  3:视频问诊", "订单金额", "支付金额", "支付时间",
                "订单状态: 10:待支付、 20:待接诊、 30:待诊断(已接诊、问诊中)、40:已完成、50:已结束、60:已关闭", "订单支付状态 : 0未支付、1支付成功", "订单退款状态: 0未退款、1退款成功 2退款失败",
                "支付方式（0未支付 1:微信 2:支付宝 3:小程序）", "支付渠道：1支付宝-APP支付、2支付宝-h5支付、3微信-APP支付、4微信-h5支付、5微信-JSAPI(小程序)", "退款时间",
                "退款原因", "退款金额", "医生佣金比例(百分比)", "医生收人金额", "平台收入金额", "支付交易第三方流水号", "订单关闭时间", "订单关闭原因", "问诊开始时间(即接诊时间)",
                "问诊完成时间", "问诊结束时间", "创建时间"};

        String sql = "SELECT\n" +
                "        inquiry_order_id as \"问诊订单ID\",\n" +
                "        doctor_id as \"医生ID\",\n" +
                "        doctor_uid as \"医生UID\",\n" +
                "        user_id as \"用户UID\",\n" +
                "        inquiry_type as \"问诊类型 1:图文问诊  2:电话问诊  3:视频问诊\",\n" +
                "        order_amount as \"订单金额\",\n" +
                "        pay_amount as \"支付金额\",\n" +
                "        pay_time as \"支付时间\",\n" +
                "        `status` as \"订单状态: 10:待支付、 20:待接诊、 30:待诊断(已接诊、问诊中)、40:已完成、50:已结束、60:已关闭\",\n" +
                "        pay_status as \"订单支付状态 : 0未支付、1支付成功\",\n" +
                "        refund_status as \"订单退款状态: 0未退款、1退款成功 2退款失败\",\n" +
                "        pay_type as \"支付方式（0未支付 1:微信 2:支付宝 3:小程序）\",\n" +
                "        pay_channel as \"支付渠道：1支付宝-APP支付、2支付宝-h5支付、3微信-APP支付、4微信-h5支付、5微信-JSAPI(小程序)\",\n" +
                "        refund_time as \"退款时间\",\n" +
                "        refund_reason as \"退款原因\",\n" +
                "        refund_amount as \"退款金额\",\n" +
                "        doctor_brokerage_scale as \"医生佣金比例(百分比)\",\n" +
                "        doctor_amount as \"医生收人金额\",\n" +
                "        platform_amount as \"平台收入金额\",\n" +
                "        pay_third_flow_no as \"支付交易第三方流水号\",\n" +
                "        close_time as \"订单关闭时间\",\n" +
                "        close_reason as \"订单关闭原因\",\n" +
                "        begin_time as \"问诊开始时间(即接诊时间)\",\n" +
                "        finish_time as \"问诊完成时间\",\n" +
                "        end_time as \"问诊结束时间\",\n" +
                "        create_time as \"创建时间\"\n" +
                "FROM inquiry_order\n" +
                "WHERE create_time >= ? AND create_time <= ?";

        this.exportData(response, "问诊订单", header, sql, startDate, endDate);
    }

    /**
     * 药品订单
     */
    @RequestMapping(value = "/export/medicine")
    @DS("ydl_yiliao")
    public void exportMedicine(HttpServletResponse response, String startDate, String endDate) throws Exception {
        String header[] = new String[]{"药品订单ID", "处方ID", "问诊订单ID", "医生ID", "医生UID", "用户ID", "快递运费", "药品总金额", "订单总金额(药品总金额+快递运费)",
                "订单状态 10-待支付 20-待发货 30-已发货(待收货) 40-已完成 50-已关闭", "支付金额", "支付状态 0-未支付 1-已支付",
                "支付方式 0-未支付 1-微信 2-支付宝）", "支付渠道 1-支付宝APP支付 2-支付宝h5支付 3-微信APP支付 4-微信h5支付 5-微信小程序", "支付时间",
                "支付交易第三方流水号", "退款状态 0-未退款 1-退款成功 2-退款失败", "退款时间", "退款原因", "退款金额", "完成类型 0-未完成 1-用户完成 2-系统自动完成）",
                "完成时间", "关闭类型 0-未关闭 1-用户取消 2-医生关闭 3-平台关闭 4-支付超时自动关闭 5-退款关闭", "关闭时间", "关闭原因", "创建时间"};

        String sql = "SELECT\n" +
                "        medicine_order_id AS \"药品订单ID\",\n" +
                "        recipel_id AS \"处方ID，关联处方表\",\n" +
                "        inquiry_order_id AS \"问诊订单ID，关联问诊订单表主键\",\n" +
                "        doctor_id AS \"医生ID(冗余问诊订单中字段)\",\n" +
                "        doctor_uid AS \"医生UID(冗余问诊订单中字段)\",\n" +
                "        user_id AS \"用户ID(冗余问诊订单中字段)\",\n" +
                "        sd_freight AS \"快递运费\",\n" +
                "        medicine_total_amount AS \"药品总金额\",\n" +
                "        order_total_amount AS \"订单总金额(药品总金额+快递运费)\",\n" +
                "        order_status AS \"订单状态 10-待支付 20-待发货 30-已发货(待收货) 40-已完成 50-已关闭\",\n" +
                "        pay_amount AS \"支付金额(实际支付金额，无优惠时即为订单总金额)\",\n" +
                "        pay_status AS \"支付状态 0-未支付 1-已支付\",\n" +
                "        pay_type AS \"支付方式 0-未支付 1-微信 2-支付宝）\",\n" +
                "        pay_channel AS \"支付渠道 1-支付宝APP支付 2-支付宝h5支付 3-微信APP支付 4-微信h5支付 5-微信小程序\",\n" +
                "        pay_time AS \"支付时间\",\n" +
                "        pay_third_flow_no AS \"支付交易第三方流水号\",\n" +
                "        refund_status AS \"退款状态 0-未退款 1-退款成功 2-退款失败\",\n" +
                "        refund_time AS \"退款时间\",\n" +
                "        refund_reason AS \"退款原因\",\n" +
                "        refund_amount AS \"退款金额\",\n" +
                "        done_type AS \"完成类型 0-未完成 1-用户完成 2-系统自动完成）\",\n" +
                "        done_time AS \"完成时间\",\n" +
                "        close_type AS \"关闭类型 0-未关闭 1-用户取消 2-医生关闭 3-平台关闭 4-支付超时自动关闭 5-退款关闭\",\n" +
                "        close_time AS \"关闭时间\",\n" +
                "        close_reason AS \"关闭原因\",\n" +
                "        create_time AS \"创建时间\" \n" +
                "FROM medicine_order \n" +
                "WHERE create_time >= ? AND create_time <= ?";

        this.exportData(response, "药品订单", header, sql, startDate, endDate);
    }

    /**
     * 药品订单明细
     */
    @RequestMapping(value = "/export/medicineDetail")
    @DS("ydl_yiliao")
    public void exportMedicineDetail(HttpServletResponse response, String startDate, String endDate) throws Exception {
        String header[] = new String[]{"药品订单ID", "问诊订单ID", "订单状态 10-待支付 20-待发货 30-已发货(待收货) 40-已完成 50-已关闭", "药品总金额",
                "订单总金额(药品总金额+快递运费)", "支付金额", "药品ID", "药品名称", "生产厂商", "开药数量", "药品单价", "药品总价(单价*数量)",
                "医生姓名", "创建时间"};

        String sql = "select t.medicine_order_id     as '药品订单id',\n" +
                "       t.inquiry_order_id      as '问诊订单id',\n" +
                "       t.order_status          as '订单状态 10-待支付 20-待发货 30-已发货(待收货) 40-已完成 50-已关闭',\n" +
                "       t.medicine_total_amount as '药品总金额',\n" +
                "       t.order_total_amount    as '订单总金额(药品总金额+快递运费)',\n" +
                "       t.pay_amount            as '支付金额',\n" +
                "       t1.medicine_id          as '药品id',\n" +
                "       t1.medicine_name        as '药品名称',\n" +
                "       t3.factory_name         as '生产厂商',\n" +
                "       t1.nums                 as '开药数量',\n" +
                "       t1.medicine_price       as '药品单价',\n" +
                "       t1.medicine_sum_price   as '药品总价(单价*数量)',\n" +
                "       t2.name                 as '医生姓名',\n" +
                "       t1.create_time          as '创建时间'\n" +
                "from medicine_order t\n" +
                "         left join medicine_order_detail t1 on t.medicine_order_id = t1.medicine_order_id\n" +
                "         left join user t2 on t.doctor_uid = t2.user_id\n" +
                "         left join yl_medicine t3 on t1.medicine_id = t3.medicine_id\n" +
                "where t.pay_status = 1\n" +
                "  and order_status in (20, 30, 40)\n" +
                "  and t.create_time >= ? and t.create_time <= ?";

        this.exportData(response, "药品订单明细", header, sql, startDate, endDate);
    }

    /**
     * 资金明细
     */
    @RequestMapping(value = "/export/finance")
    @DS("ydl_yiliao")
    public void exportFinance(HttpServletResponse response, String startDate, String endDate) throws Exception {
        String header[] = new String[]{
                "财务流水明细",
                "业务类型：1-问诊订单支付 2-问诊订单退款 3-问诊订单佣金收入 4-平台问诊订单佣金收入、5-药品订单支付、6药品订单退款、7平台药品药品收人、8平台药品运费收人、9：提现，10：核销  11：患者报到激励收入",
                "业务关联用户账户类型：0平台、1普通用户、2医生",
                "业务关联用户账户ID，类型和ID对应关系：0平台（无）、1普通用户、2医生",
                "业务关联类型：1-问诊订单 2-处方单 3-药品订单 4-电子签名 5-提现 6-奖励",
                "业务编号（业务订单号）",
                "交易类型：1收入、2支出",
                "交易类型：0系统自动结算、1微信支付、2支付宝支付、3（business_type 为1:小程序支付；business_type 为9或者10为：手动核销",
                "交易金额",
                "交易第三方流水号",
                "创建时间"};

        String sql = "SELECT\n" +
                "        money_flow_id AS \"财务流水明细\",\n" +
                "        business_type AS \"业务类型：1-问诊订单支付 2-问诊订单退款 3-问诊订单佣金收入 4-平台问诊订单佣金收入、5-药品订单支付、6药品订单退款、7平台药品药品收人、8平台药品运费收人、9：提现，10：核销  11：患者报到激励收入\",\n" +
                "        account_type AS \"业务关联用户账户类型：0平台、1普通用户、2医生\",\n" +
                "        account_id AS \"业务关联用户账户ID，类型和ID对应关系：0平台（无）、1普通用户、2医生\",\n" +
                "        business_rele_type AS \"业务关联类型：1-问诊订单 2-处方单 3-药品订单 4-电子签名 5-提现 6-奖励\",\n" +
                "        business_rele_id AS \"业务编号（业务订单号）\",\n" +
                "        trade_type AS \"交易类型：1收入、2支出\",\n" +
                "        trade_way AS \"交易类型：0系统自动结算、1微信支付、2支付宝支付、3（business_type 为1:小程序支付；business_type 为9或者10为：手动核销\",\n" +
                "        trade_amount AS \"交易金额\",\n" +
                "        trade_third_flow_no AS \"交易第三方流水号\",\n" +
                "        create_time AS \"创建时间\" \n" +
                "FROM finance_money_flow \n" +
                "WHERE create_time >= ? AND create_time <= ?";

        this.exportData(response, "资金明细", header, sql, startDate, endDate);
    }

    private void exportData(HttpServletResponse response, String filenamePrefix, String header[], String sql, String startDate, String endDate) throws Exception {
        if (StringUtils.isBlank(startDate)) {
            startDate = DateUtil.formatDate(new Date());
        }
        if (StringUtils.isBlank(endDate)) {
            endDate = DateUtil.formatDate(new Date());
        }

        String filename = String.format("%s数据(%s-%s).xlsx", filenamePrefix, startDate, endDate);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/x-msdownload");
        response.setHeader("Content-disposition", "attachment; filename=" + new String(filename.getBytes("utf-8"), "ISO8859-1"));

        String startTime = startDate + " 00:00:00", endTime = endDate + " 23:59:59";

        DBUtil dbUtil = new DBUtil(sqlSessionFactory);
        List<Map<String, String>> list = dbUtil.executeQuery(sql, new Object[]{startTime, endTime});

        ByteArrayOutputStream stream = this.writeExcelData(header, list);
        stream.writeTo(response.getOutputStream());
    }

    private ByteArrayOutputStream writeExcelData(String header[], List<Map<String, String>> list) throws Exception {
        String sheetName = "Sheet1";
        List<String[]> dataList = new ArrayList<>();
        for (Map<String, String> map : list) {
            dataList.add(map.values().toArray(new String[]{}));
        }

        Workbook workbook = WorkbookUtil.createBook(true);
        Sheet sheet = workbook.createSheet(sheetName);

        //创建表头行
        int headerRow = 0;
        if (header != null) {
            headerRow = 1;

            CellStyle cellStyle = workbook.createCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            Row title = sheet.createRow(0);
            for (int i = 0; i < header.length; i++) {
                Cell cell = title.createCell(i);
                cell.setCellValue(header[i]);
                cell.setCellStyle(cellStyle);
            }
        }

        //追加数据
        int size = dataList != null ? dataList.size() : 0;
        for (int i = 0; i < size; i++) {
            Row nextrow = sheet.createRow(i + headerRow);
            String[] data = dataList.get(i);
            for (int j = 0; j < data.length; j++) {
                Cell cell2 = nextrow.createCell(j);
                cell2.setCellValue(data[j]);
            }
        }

        //将表格写入ByteArrayOutputStream
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        workbook.write(stream);
        stream.close();
        return stream;
    }
}
