package com.cftech.showroom.appform.web;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSONObject;
import com.cftech.base.codingrule.utils.CodingruleUtils;
import com.cftech.core.util.DateUtils;
import com.cftech.core.util.MpTokenUtil;
import com.cftech.core.util.SystemConfig;
import com.cftech.shop.qrcode.service.WxQrcodeService;
import com.cftech.shop.qrcode.util.WxQrcodeUtil;
import com.cftech.showroom.appform.model.*;
import com.cftech.showroom.appform.service.AppFormService;
import com.cftech.core.poi.ExcelKit;
import com.cftech.core.scope.OrderType;
import com.cftech.core.sql.Conds;
import com.cftech.core.sql.Sort;
import com.cftech.core.util.Constants;
import com.cftech.showroom.appform.service.ShowroomEvaluateService;
import com.cftech.showroom.explainer.service.ExplainerService;
import com.cftech.showroom.sdepartment.service.SdepartmentService;
import com.cftech.showroom.visitorCategory.service.VisitorCategoryService;
import com.cftech.sys.security.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.mp.api.wxaccount.model.WxQrcode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 展厅申请单Controller
 * <p>
 * 权限字符串说明:
 * 查看:public static final String APPFORM_VIEW = "qy:appForm:view"
 * 查看:public static final String APPFORM_EDIT = "qy:appForm:edit"
 *
 * @author lisw
 * @date: 2019-07-31 15:40
 */
@Slf4j
@Controller
@RequestMapping("/a/appForm")
public class AppFormController {

    public static final String APPFORM_VIEW = "qy:appForm:view";
    public static final String APPFORM_EDIT = "qy:appForm:edit";

    @Autowired
    private AppFormService appFormService;
    @Autowired
    private CodingruleUtils codingruleUtils;

    @Autowired
    private WxQrcodeService wxQrcodeService;

    @Autowired
    private MpTokenUtil tokenUtil;

    @Autowired
    private WxQrcodeUtil wxQrcodeUtil;

    @Autowired
    private SdepartmentService sdepartmentService;

    @Autowired
    private VisitorCategoryService visitorCategoryService;

    @Autowired
    private ExplainerService explainerService;

    @Autowired
    private ShowroomEvaluateService showroomEvaluateService;

    //下载展厅二维码
    @RequiresPermissions(value = APPFORM_VIEW)
    @RequestMapping(value = "/downloadcode", method = {RequestMethod.GET, RequestMethod.POST})
    public void downloadcode(com.cftech.shop.qrcode.model.WxQrcode qrcode, HttpServletRequest request, HttpServletResponse response) throws IOException {
        JSONObject jsonObject = new JSONObject();
        Long accountsId = UserUtils.getmpaccounts(request);
        String accessToken = tokenUtil.getToken(accountsId);
        Conds conds = new Conds();
        conds.equal("type", "exhibiApp");
        com.cftech.shop.qrcode.model.WxQrcode wxQrcode = wxQrcodeService.fetchSearchByConds(conds);
        WxQrcode wxqrcode = null;
        if (wxQrcode == null) { //该研讨会已经生成可二维码
            try {
                Conds countConds = new Conds();
                countConds.equal("t.del_flag", 0);
                int count = wxQrcodeService.count(countConds);
                JSONObject wxObj = wxQrcodeUtil.createLimitQrcode(accountsId, Long.valueOf(count));
                if (wxObj.containsKey("ticket")) {
                    qrcode.setTicket(wxObj.getString("ticket"));
                }
                qrcode.setId(null);
                String tempTicket = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + qrcode.getTicket();
                qrcode.setCreateBy(UserUtils.getUser().getId());
                qrcode.setType("exhibiApp");
                qrcode.setUpdateBy(UserUtils.getUser().getId());
                qrcode.setSceneId(String.valueOf(count));
                qrcode.setBindId(0L);
                qrcode.setDelFlag(false);
                wxQrcodeService.save(qrcode);
                downPicture(request, response, tempTicket, "展厅预约二维码");
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            downPicture(request, response, "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + wxQrcode.getTicket(), "展厅预约二维码");
        }
    }

    public void downPicture(HttpServletRequest request, HttpServletResponse response, String urls, String title) throws IOException {

        String prefix = "jpg";
//获取文件

        URL url = new URL(urls);
        URLConnection conn = url.openConnection();
//设置超时间为3秒
        conn.setConnectTimeout(3 * 1000);
//防止屏蔽程序抓取而返回403错误
        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
//输出流
        InputStream fs = conn.getInputStream();

        int bytesRead = 0;
        byte[] image = new byte[8192];
        response.setHeader("Content-Type", "application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(title.getBytes("gb2312"), "ISO8859-1") + "." + prefix);
        try {
            while ((bytesRead = fs.read(image, 0, 8192)) != -1) {
                response.getOutputStream().write(image, 0, bytesRead);

            }
            fs.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        response.getOutputStream().flush();
        response.getOutputStream().close();
    }

    //列表页面
    @RequiresPermissions(value = APPFORM_VIEW)
    @RequestMapping("/list")
    public String list(HttpServletRequest request, Model model) {
        Long accountId = UserUtils.getmpaccounts(request);
        model.addAttribute("accountId", accountId);
        return "appForm/appFormlist";
    }

    //列表页面
    @RequiresPermissions(value = APPFORM_VIEW)
    @RequestMapping("/calendar")
    public String calendar(HttpServletRequest request, Model model) {
        return "appForm/canlendarList";
    }


    //编辑页面（新增、修改）
    @RequiresPermissions(value = APPFORM_VIEW)
    @RequestMapping("/form")
    public String form(HttpServletRequest request, String id, Model model) {
        if (!StringUtils.isEmpty(id)) {
            AppForm appForm = appFormService.fetchById(id);
            model.addAttribute("data", appForm);
        }
        return "appForm/appFormform";
    }

    //提交数据（新增、修改）
    @RequiresPermissions(value = APPFORM_EDIT)
    @RequestMapping("/formData")
    @ResponseBody
    public JSONObject formData(AppForm appForm, Model model, HttpServletRequest request) {
        Long accountsId = UserUtils.getmpaccounts(request);
        JSONObject rtnJson = new JSONObject();
        try {
            if (appForm != null && appForm.getId() != null) {
                appForm.setUpdateBy(UserUtils.getUser().getId());
                appFormService.update(appForm);
                rtnJson.put("errorNo", 0);
            } else {
                appForm.setNumber(codingruleUtils.getNumber(accountsId, AppForm.class.getName()));
                appForm.setAccountsId(accountsId);
                appForm.setDelFlag(false);
                appForm.setAccountsId(UserUtils.getmpaccounts(request));
                appForm.setCreateBy(UserUtils.getUser().getId());
                appForm.setUpdateBy(UserUtils.getUser().getId());
                appFormService.save(appForm);
                rtnJson.put("errorNo", 2);
            }
        } catch (Exception e) {
            rtnJson.put("errorNo", 1);
        }
        return rtnJson;
    }

    //获取列表数据
    @RequiresPermissions(value = APPFORM_VIEW)
    @RequestMapping(value = "/listData")
    @ResponseBody
    public JSONObject listData(int iDisplayStart, int iDisplayLength, AppForm appForm, HttpServletRequest request, String reservationDateStr, String createTimeStr) {
        Long accountsId = UserUtils.getmpaccounts(request);
        Conds conds = new Conds();
        conds.equal("t.del_flag", Constants.DEL_FLAG_0);
        conds.equal("t.accounts_id", accountsId);
        String dateBegin = null;
        String dateEnd = null;
        if (!StringUtils.isEmpty(reservationDateStr)) {
            dateBegin = reservationDateStr.split(" - ")[0];
            dateEnd = reservationDateStr.split(" - ")[1];
        }

        if (!StringUtils.isEmpty(createTimeStr)) {
            String credateBegin = createTimeStr.split(" - ")[0];
            String credateEnd = createTimeStr.split(" - ")[1];
            conds.greatEqual("t.create_time", credateBegin);
            conds.lessEqual("t.create_time", credateEnd);
        }

        if (!StringUtils.isEmpty(appForm.getNumber())) {
            conds.like("t.number", appForm.getNumber());
        }
        if (!StringUtils.isEmpty(appForm.getName())) {
            conds.like("t.name", appForm.getName());
        }
        if (!StringUtils.isEmpty(appForm.getDepartment())) {
            conds.equal("t.department", appForm.getDepartment());
        }
        if (!StringUtils.isEmpty(appForm.getReservationDate())) {
            conds.equal("t.reservation_date", appForm.getReservationDate());
        }

        if (!StringUtils.isEmpty(appForm.getVisitorCategory())) {
            conds.equal("t.visitor_category", appForm.getVisitorCategory());
        }
        if (!StringUtils.isEmpty(appForm.getVisitorNum())) {
            conds.equal("t.visitor_num", appForm.getVisitorNum());
        }
        if (!StringUtils.isEmpty(appForm.getApplyContent())) {
            conds.equal("t.apply_content", appForm.getApplyContent());
        }
        if (!StringUtils.isEmpty(appForm.getExplainer())) {
            conds.equal("t.explainer", appForm.getExplainer());
        }
        Sort sort = new Sort("t.reservation_begin_time", OrderType.DESC);
        List<AppFormVo> list = appFormService.fetchSearchByPageForList(conds, sort, iDisplayStart, iDisplayLength, dateBegin, dateEnd);
        Integer counts = appFormService.count(conds);
        JSONObject rtnJson = new JSONObject();
        rtnJson.put("iTotalRecords", counts);
        rtnJson.put("iTotalDisplayRecords", counts);
        rtnJson.put("aaData", list);
        return rtnJson;
    }


    @RequiresPermissions(value = APPFORM_VIEW)
    @RequestMapping(value = "/calendarData", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject calendarList(String begin, String end) {
        JSONObject object = new JSONObject();
        try {
            Conds conds = new Conds();
            conds.greatEqual("date(reservation_begin_time)", begin);
            conds.lessEqual("date(reservation_begin_time)", end);
            conds.equal("status", 0);
            List<AppFormCalendarDto> appFormCalendarDtos = appFormService.getCalendar(conds);
            object.put("errorNo", 0);
            object.put("datas", appFormCalendarDtos);
        } catch (Exception e) {
            e.printStackTrace();
            object.put("errorNo", 0);
        }
        return object;
    }

    //删除数据
    @RequiresPermissions(value = APPFORM_EDIT)
    @RequestMapping("/delete")
    @ResponseBody
    public JSONObject delete(String id) {
        JSONObject rtnJosn = new JSONObject();
        try {
            appFormService.delete(id);
            rtnJosn.put("errorNo", 0);
        } catch (Exception e) {
            rtnJosn.put("errorNo", 1);
        }
        return rtnJosn;
    }


    @RequestMapping("/exportExcel")
    @RequiresPermissions(value = APPFORM_VIEW)
    public void exportExcel(HttpServletRequest request, HttpServletResponse response, AppForm appForm, String reservationDateStr, String createTimeStr) {
        Long accountId = UserUtils.getmpaccounts(request);
        Conds conds = new Conds();
        conds.equal("t.del_flag", Constants.DEL_FLAG_0);
        conds.equal("t.accounts_id", accountId);
        String dateBegin = null;
        String dateEnd = null;
        if (!StringUtils.isEmpty(reservationDateStr)) {
            dateBegin = reservationDateStr.split(" - ")[0];
            dateEnd = reservationDateStr.split(" - ")[1];
        }


        if (!StringUtils.isEmpty(createTimeStr)) {
            String credateBegin = createTimeStr.split(" - ")[0];
            String credateEnd = createTimeStr.split(" - ")[1];
            conds.greatEqual("t.create_time", credateBegin);
            conds.lessEqual("t.create_time", credateEnd);
        }
        if (!StringUtils.isEmpty(appForm.getNumber())) {
            conds.like("t.number", appForm.getNumber());
        }
        if (!StringUtils.isEmpty(appForm.getName())) {
            conds.like("t.name", appForm.getName());
        }
        if (!StringUtils.isEmpty(appForm.getDepartment())) {
            conds.equal("t.department", appForm.getDepartment());
        }
        if (!StringUtils.isEmpty(appForm.getReservationDate())) {
            conds.equal("t.reservation_date", appForm.getReservationDate());
        }

        if (!StringUtils.isEmpty(appForm.getVisitorCategory())) {
            conds.equal("t.visitor_category", appForm.getVisitorCategory());
        }
        if (!StringUtils.isEmpty(appForm.getVisitorNum())) {
            conds.equal("t.visitor_num", appForm.getVisitorNum());
        }
        if (!StringUtils.isEmpty(appForm.getApplyContent())) {
            conds.equal("t.apply_content", appForm.getApplyContent());
        }
        if (!StringUtils.isEmpty(appForm.getExplainer())) {
            conds.equal("t.explainer", appForm.getExplainer());
        }
        Sort sort = new Sort("t.create_time", OrderType.DESC);
        List<AppForm> list = appFormService.fetchSearchByPage(conds, sort, 0, 0, dateBegin, dateEnd);
        ExcelKit.$Export(AppForm.class, response).toExcel(list, "展厅申请单");
    }

    @RequestMapping("/exportDataReportingExcel")
    @RequiresPermissions(value = APPFORM_VIEW)
    public void exportDataReportingExcel(HttpServletRequest request, HttpServletResponse response, int year) throws FileNotFoundException {
        try {
            if (year == 0) {
                Calendar cal = Calendar.getInstance();
                year = cal.get(Calendar.YEAR);
            }

            Conds d = new Conds();
            Map<String, Object> paramsConds = new HashMap<>();
            paramsConds.put("tableName", "wx_mp_showroom_department");
            paramsConds.put("columnName", "dname");
            List<String> departmentList = appFormService.fetchGetName(paramsConds);
            paramsConds.put("tableName", "wx_mp_showroom_explainer");
            paramsConds.put("columnName", "ename");
            List<String> explainerList = appFormService.fetchGetName(paramsConds);
            paramsConds.put("tableName", "wx_mp_showroom_vicategory");
            paramsConds.put("columnName", "vname");
            List<String> typeList = appFormService.fetchGetName(paramsConds);
            Map<String, Object> params = new HashMap<>();
            Conds conds = new Conds();
            conds.equal("t.del_flag", 0);
            conds.equal("t.status", 0);
            conds.equal("YEAR(t.reservation_begin_time)", year);
            params.put("conds", conds);
            List<ShowRoomRecord> showRoomRecords = appFormService.getRecordList(params);
            ExportExcelData.exportData(showRoomRecords, String.valueOf(year), typeList, departmentList, explainerList, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @RequiresPermissions(value = APPFORM_VIEW)
    @RequestMapping(value = "/submitRemarks", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject submitRemarks(Long id, String text) {
        JSONObject object = new JSONObject();
        try {
            AppForm appForm = appFormService.fetchById(id);
            appForm.setId(id);
            appForm.setRemarks(text);
            appFormService.update(appForm);
            object.put("errorNo", 0);
        } catch (Exception e) {
            e.printStackTrace();
            object.put("errorNo", 1);
        }
        return object;
    }

    /**
     * 评分导出
     * @param request
     * @param response
     * @param reservationDateStr
     * @param createTimeStr
     */
    @RequestMapping("/exportDataEvaluateExcel")
    @RequiresPermissions(value = APPFORM_VIEW)
    public void exportDataEvaluateExcel(HttpServletRequest request, HttpServletResponse response, String reservationDateStr, String createTimeStr) {
        try {
            DecimalFormat df = new DecimalFormat("0.00");
            Conds conds = new Conds();
            conds.equal("t.del_flag", "0");
            String dateBegin = null;
            String dateEnd = null;
            if (!StringUtils.isEmpty(reservationDateStr)) {
                dateBegin = reservationDateStr.split(" - ")[0];
                dateEnd = reservationDateStr.split(" - ")[1];
            }
            if (!StringUtils.isEmpty(createTimeStr)) {
                String credateBegin = createTimeStr.split(" - ")[0];
                String credateEnd = createTimeStr.split(" - ")[1];
                conds.greatEqual("t.reservation_begin_time", credateBegin);
                conds.lessEqual("t.reservation_begin_time", credateEnd);
            }
            // 总预约量
            int totalAppForm = appFormService.count(conds);
            // 申请人提交评价总数
            Conds showRoomConds = new Conds();
            showRoomConds.equal("t.del_flag", "0");
            String reservationBeginTime = null;
            String reservationEndTime = null;
            if (!StringUtils.isEmpty(createTimeStr)) {
                String credateBegin = createTimeStr.split(" - ")[0];
                String credateEnd = createTimeStr.split(" - ")[1];
                reservationBeginTime = credateBegin;
                reservationEndTime = credateEnd;
            }
            int totalEvaluate = showroomEvaluateService.countEvaluate(showRoomConds, reservationBeginTime, reservationEndTime);
            // 获取文件路径
            String basePath = SystemConfig.p.getProperty("docXmlTemplatePath");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String currntTime = sdf.format(new Date());
            //导出列表名
            String fileName = "展厅参观反馈报告%s";
            fileName = String.format(fileName, currntTime);
            Map<String, Object> map = new HashMap<>();
            // 总预约数量
            map.put("totalAppForm", totalAppForm);
            // 提交评价数量
            map.put("totalEvaluate", totalEvaluate);
            // 百分比
            float percentage = 0;
            if (totalAppForm > 0) {
                percentage = (float) totalEvaluate * 100 / totalAppForm;
            }
            map.put("percentage", df.format(percentage));
            // 平均星星
            ShowroomEvaluateVo showroomEvaluate = showroomEvaluateService.sumStartNum(showRoomConds,reservationBeginTime, reservationEndTime);
            if(showroomEvaluate!=null){
                float averageBrand = 0;
                if(totalEvaluate > 0) {
                    averageBrand = (float) showroomEvaluate.getAverageBrand() / totalEvaluate;
                }
                float averageMediaDevice = 0;
                if(totalEvaluate > 0) {
                    averageMediaDevice = (float) showroomEvaluate.getAverageMediaDevice() / totalEvaluate;
                }
                float averageExplainMajor = 0;
                if(totalEvaluate > 0) {
                    averageExplainMajor = (float) showroomEvaluate.getAverageExplainMajor() / totalEvaluate;
                }
                float averageClothing = 0;
                if(totalEvaluate > 0) {
                    averageClothing = (float) showroomEvaluate.getAverageClothing() / totalEvaluate;
                }
                map.put("averageBrand", df.format(averageBrand));
                map.put("averageMediaDevice", df.format(averageMediaDevice));
                map.put("averageExplainMajor", df.format(averageExplainMajor));
                map.put("averageClothing", df.format(averageClothing));
            }else{
                map.put("averageBrand", 0);
                map.put("averageMediaDevice", 0);
                map.put("averageExplainMajor", 0);
                map.put("averageClothing", 0);
            }

            // https://www.yuque.com/easyexcel/doc/fill
            Sort sort = new Sort("t.reservation_begin_time", OrderType.DESC);
            List<AppFormVo> list = appFormService.fetchSearchByPageForList(conds, sort, 0, 0, dateBegin, dateEnd);
            // 生成文件信息
            String templateFilePath = basePath + "BrandApplyExportEvaluateTemplate.xls";
            ExcelWriter excelWriter = EasyExcel.write(getOutputStream(fileName, response)).withTemplate(templateFilePath).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            excelWriter.fill(map, writeSheet);
            excelWriter.fill(list, writeSheet);
            excelWriter.finish();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 包装Response流信息
     *
     * @param fileName
     * @param response
     * @return
     * @throws Exception
     * @author lisw
     */
    private static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception {
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xls");
            response.setHeader("Pragma", "public");
            response.setHeader("Cache-Control", "no-store");
            response.addHeader("Cache-Control", "max-age=0");
            return response.getOutputStream();
        } catch (IOException e) {
            throw new Exception("导出excel表格失败!", e);
        }
    }


}
