package com.yida.data.form.customForm.service.impl;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.entity.constant.AppConstant;
import com.yida.data.common.core.entity.customform.*;
import com.yida.data.common.core.entity.notice.qywx.BaseStaffNotice;
import com.yida.data.common.core.entity.notice.qywx.inside.Text;
import com.yida.data.common.core.entity.system.EduApp;
import com.yida.data.common.core.entity.user.EduParent;
import com.yida.data.common.core.entity.user.EduStaff;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.utils.ExcelUtil;
import com.yida.data.common.core.utils.WxUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.customForm.dto.FormDataInput;
import com.yida.data.customForm.vo.ParentCommit;
import com.yida.data.form.customForm.entity.FormDataReturn;
import com.yida.data.form.customForm.entity.RedisKey;
import com.yida.data.form.customForm.mapper.CoreCustomFormDataMapper;
import com.yida.data.form.customForm.service.*;
import com.yida.data.user.feign.RemoteStaffService;
import com.yida.data.user.feign.RemoteStudentService;
import lombok.RequiredArgsConstructor;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.yida.data.common.core.entity.constant.CachePrefixConstant.STAFF_DATA;
import static com.yida.data.common.core.entity.constant.CachePrefixConstant.STUDENT_DATA;

/**
 * 自定义表单 Service实现
 *
 * @author wjm
 * @date 2021-08-11 20:55:19
 */
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class CoreCustomFormDataServiceImpl implements CoreCustomFormDataService {

    @Value("${edu.customform.dbname}")
    private String dbName;

    @Value("${febs.teacherFormUrl}")
    private String teacherFormUrl;

    @Resource
    private CoreCustomFormDataMapper coreCustomFormDataMapper;

    @Resource
    private CoreCustomFormService coreCustomFormService;

    @Resource
    private CoreCustomFormItemsService coreCustomFormItemsService;

    @Resource
    private CoreCustomFormRelationUserService userService;

    @Resource
    private RedisService redisService;

    @Resource
    private RemoteStaffService remoteStaffService;

    @Resource
    private RemoteStudentService remoteStudentService;

    @Resource
    private CoreCustomFormRelationUserParentService parentService;

    @Resource
    private CoreCustomFormRelationAdminService adminService;

    @Resource
    private WxUtil wxUtil;
    @Resource
    private CommonService commonService;

    @Override
    public void saveFormData(FormDataInput formDataInput, Map data) {
        CoreCustomForm form = coreCustomFormService.getOne(Wrappers.lambdaQuery(new CoreCustomForm())
                .eq(CoreCustomForm::getTableName, formDataInput.getTableName()));
        if (ObjectUtil.isNotEmpty(data)) {
            String sql = "DELETE FROM " + formDataInput.getTableName() + " WHERE user_id = " + formDataInput.getUserId();
            coreCustomFormDataMapper.removeBySql(sql);
        }

        List<String> filedList = coreCustomFormDataMapper.findFormFiled(dbName, formDataInput.getTableName());
        JSONObject jsonObject = JSONUtil.parseObj(formDataInput.getJsonDataString());
        List<String> parameterList = new ArrayList<>();
        Map parameterMap = new HashMap();
        String baseSql = "insert into " + formDataInput.getTableName() + "(";
        filedList.forEach(filed -> {
            parameterList.add("#{parameterMap." + filed + "}");
            parameterMap.put(filed, jsonObject.get(filed));
        });
        parameterMap.put("create_date", new Date());
        parameterMap.put("user_id", formDataInput.getUserId());
        String finalSql = baseSql + String.join(",", filedList) + ")values(" + String.join(",", parameterList) + ")";
        coreCustomFormDataMapper.initSqlWithParameterReturnVoid(finalSql, parameterMap);


        //修改填报人填报状态
        CoreCustomForm one = coreCustomFormService.getOne(Wrappers.lambdaQuery(new CoreCustomForm())
                .eq(CoreCustomForm::getTableName, formDataInput.getTableName()));

        if (one.getRecever() != 2) {
            userService.update(Wrappers.lambdaUpdate(new CoreCustomFormRelationUser())
                    .eq(CoreCustomFormRelationUser::getCustomFormId, one.getId())
                    .eq(CoreCustomFormRelationUser::getUserId, formDataInput.getUserId())
                    .set(CoreCustomFormRelationUser::getFill, 1)
                    .set(CoreCustomFormRelationUser::getFillTime, LocalDateTime.now()));
        } else if (one.getRecever() == 2) {
            parentService.update(Wrappers.lambdaUpdate(new CoreCustomFormRelationUserParent())
                    .eq(CoreCustomFormRelationUserParent::getCustomFormId, one.getId())
                    .set(CoreCustomFormRelationUserParent::getFillType, 1)
                    .set(CoreCustomFormRelationUserParent::getFillTime, LocalDateTime.now()));
        }

        //新增数据发送通知
        if (form.getRemindAdmin() == 1) {

            //查询对应管理员
            List<CoreCustomFormRelationAdmin> adminList = adminService.list(Wrappers.lambdaQuery(new CoreCustomFormRelationAdmin())
                    .eq(CoreCustomFormRelationAdmin::getCustomFormId, form.getId()));
            for (CoreCustomFormRelationAdmin relationUser : adminList) {
                EduStaff staff = remoteStaffService.getStaffNoPermission(relationUser.getAdminId()).getData();
                BaseStaffNotice textSchoolNotice = new BaseStaffNotice();
                EduApp appByCodeAndSchool = commonService.getAppByCodeAndSchool(AppConstant.INDEX_PARENT, null, form.getOrgId());
                Text text = new Text();
                textSchoolNotice.setText(text);
                textSchoolNotice.setAgentid(appByCodeAndSchool.getWxAgentId());
                String url = teacherFormUrl + appByCodeAndSchool.getWxCorpId() + "&loginType=0&userType=0&state=" + AppConstant.INDEX_PARENT + "&id=" + form.getId();
                ;

                text.setContent("<a href='" + url + "'>" + form.getRemindAdminModel() + "    " + staff.getName() + "已填报《" + form.getFormTitle() + "》" + "</a>");
                textSchoolNotice.setTouser(staff.getWxId());
                String accessToken = wxUtil.getAccessToken(appByCodeAndSchool.getWxCorpId(), appByCodeAndSchool.getWxSecret());
                wxUtil.pushStaffNotice(accessToken, textSchoolNotice);
            }
        }

    }


    @Override
    public List<Map> findSubmitFormDataListByFormId(Integer formId, Integer pageSize, Integer pageNo) {
        //查询formID对应的数据表
        CoreCustomForm coreCustomForm = null;
        if (redisService.hasKey(RedisKey.FORM_LOCAL + formId)) {
            coreCustomForm = (CoreCustomForm) redisService.get(RedisKey.FORM_LOCAL + formId);
        } else {
            coreCustomForm = coreCustomFormService.getById(formId);
        }

        if (ObjectUtil.isEmpty(pageNo) && ObjectUtil.isEmpty(pageSize)) {
            String initSql = "select * from " + coreCustomForm.getTableName();
            return coreCustomFormDataMapper.initSqlWithNUllReturnListMap(initSql);
        }

        Integer limitBeginNum = pageNo == 1 ? 0 : (pageSize * (pageNo - 1));
        Integer limitEndNum = pageNo * pageSize;
        String initSql = "select * from " + coreCustomForm.getTableName() +
                " limit " + limitBeginNum + "," + limitEndNum;
        //查询出表单数据ListMap
        //查询出表单数据
        List<Map> maps = coreCustomFormDataMapper.initSqlWithNUllReturnListMap(initSql);
        for (Map map : maps) {
            Long userId = (Long) map.get("user_id");
            //教职工
            if (coreCustomForm.getRecever() == 0) {
                EduStaff staff = (EduStaff) redisService.hget(STAFF_DATA, userId.toString());
                if (ObjectUtil.isEmpty(staff)) {
                    staff = remoteStaffService.getStaff(userId).getData();
                    redisService.hset(STAFF_DATA, userId.toString(), staff);
                }
                map.put("staff", staff);
            }
            //学生
            else if (coreCustomForm.getRecever() == 1) {
                EduStudent student = (EduStudent) redisService.hget(STUDENT_DATA, userId.toString());
                if (ObjectUtil.isEmpty(student)) {
                    student = remoteStudentService.getStudentNoPermission(userId).getData();
                    redisService.hset(STUDENT_DATA, userId.toString(), student);
                }
                map.put("student", student);
            }
            //家长
            else if (coreCustomForm.getRecever() == 2) {
                Long customUserId = parentService.getOne(Wrappers.lambdaQuery(new CoreCustomFormRelationUserParent())
                        .eq(CoreCustomFormRelationUserParent::getCustomFormId, formId)
                        .eq(CoreCustomFormRelationUserParent::getParentId, userId)).getCustomUserId();
                Long studentId = userService.getById(customUserId).getUserId();

                EduStudent student = (EduStudent) redisService.hget(STUDENT_DATA, studentId.toString());
                if (ObjectUtil.isEmpty(student)) {
                    student = remoteStudentService.getStudentNoPermission(studentId).getData();
                    redisService.hset(STUDENT_DATA, studentId.toString(), student);
                }
                EduParent parent = student.getParents().stream().filter(p -> p.getId().equals(userId)).collect(Collectors.toList()).get(0);

                ParentCommit parentCommit = new ParentCommit();
                parentCommit.setParentName(student.getStuName() + parent.getParentType());
                parentCommit.setPhone(parent.getMobile());
                parentCommit.setSchoolName(student.getSchoolName());
                parentCommit.setCampusName(student.getCampusName());
                parentCommit.setSectionName(student.getSectionName());
                parentCommit.setGradeName(student.getGradeName());
                parentCommit.setClassName(student.getClassName());
                map.put("parent", parentCommit);
            }
        }
        return coreCustomFormDataMapper.initSqlWithNUllReturnListMap(initSql);
    }


    @Override
    public Integer findSubmitFormDataTotalNumByFormId(Integer formId) {
        CoreCustomForm coreCustomForm = null;
        if (redisService.hasKey(RedisKey.FORM_LOCAL + formId)) {
            coreCustomForm = (CoreCustomForm) redisService.get(RedisKey.FORM_LOCAL + formId);
        } else {
            coreCustomForm = coreCustomFormService.getById(formId);
        }
        String initSql = "select count(id) from " + coreCustomForm.getTableName();
        //查询出表单数据ListMap
        //查询出表单数据
        return coreCustomFormDataMapper.initSqlWithNUllReturnInteger(initSql);
    }

    @Override
    public FormDataReturn findList(Integer formId, Integer pageSize, Integer pageNo) {
        List<Map> submitFormDataListByFormId = this.findSubmitFormDataListByFormId(formId, pageSize, pageNo);
        Integer submitFormDataTotalNumByFormId = this.findSubmitFormDataTotalNumByFormId(formId);
        List<CoreCustomFormItems> coreCustomFormItemList = coreCustomFormItemsService.list(Wrappers.<CoreCustomFormItems>query().lambda().eq(CoreCustomFormItems::getFormId, formId));
        return new FormDataReturn(submitFormDataListByFormId, submitFormDataTotalNumByFormId, coreCustomFormItemList);
    }


    @Override
    public void exportData(Integer formId, HttpServletResponse response) throws ParseException {
        CoreCustomForm byId = coreCustomFormService.getById(formId);
        if (byId.getRecever() == 0) {
            XSSFWorkbook workbook = new XSSFWorkbook();
            XSSFSheet sheet = workbook.createSheet();
            XSSFRow row = sheet.createRow(0);
            List<CoreCustomFormItems> coreCustomFormItemList = coreCustomFormItemsService.list(Wrappers.<CoreCustomFormItems>query().lambda().eq(CoreCustomFormItems::getFormId, formId));
            row.createCell(0).setCellValue("序号");
            row.createCell(1).setCellValue("姓名");
            row.createCell(2).setCellValue("电话");
            row.createCell(coreCustomFormItemList.size() + 3).setCellValue("时间");
            for (int i = 0; i < coreCustomFormItemList.size(); i++) {
                row.createCell(i + 4).setCellValue(coreCustomFormItemList.get(i).getItemTitle());
            }

            List<Map> submitFormDataListByFormId = this.findSubmitFormDataListByFormId(formId, null, null);
            for (int j = 0; j < submitFormDataListByFormId.size(); j++) {
                XSSFRow row1 = sheet.createRow(j + 1);
                Map map = submitFormDataListByFormId.get(j);
                Iterator<String> iter = map.keySet().iterator();
                while (iter.hasNext()) {
                    //字段名称
                    String key = iter.next();
                    //填报值
                    Object value = map.get(key);

                    if ("id".equals(key)) {
                        row1.createCell(0).setCellValue(ObjectUtil.toString(value));
                        continue;
                    }
                    if ("user_id".equals(key)) {
                        EduStaff hget = (EduStaff) redisService.hget(STAFF_DATA, value.toString());
                        row1.createCell(1).setCellValue(ObjectUtil.toString(hget.getName()));
                        row1.createCell(2).setCellValue(ObjectUtil.toString(hget.getMobile()));
                        continue;
                    }
                    if ("create_date".equals(key)) {
                        SimpleDateFormat myFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        row1.createCell(coreCustomFormItemList.size() + 2).setCellValue(myFmt.format(myFmt.parse(ObjectUtil.toString(value))));
                        continue;
                    }
                    for (int i = 0; i < coreCustomFormItemList.size(); i++) {
                        String itemFiledName = coreCustomFormItemList.get(i).getItemFiledName();
                        if (key.equals(itemFiledName)) {
                            row1.createCell(i + 3).setCellValue(ObjectUtil.toString(value));
                        }
                    }
                }
            }
            ExcelUtil.export("表单数据", "xlsx", workbook, response);
        } else if (byId.getRecever() == 1) {
            XSSFWorkbook workbook = new XSSFWorkbook();
            XSSFSheet sheet = workbook.createSheet();
            XSSFRow row = sheet.createRow(0);
            List<CoreCustomFormItems> coreCustomFormItemList = coreCustomFormItemsService.list(Wrappers.<CoreCustomFormItems>query().lambda().eq(CoreCustomFormItems::getFormId, formId));
            row.createCell(0).setCellValue("序号");
            row.createCell(1).setCellValue("班级");
            row.createCell(2).setCellValue("姓名");
            row.createCell(3).setCellValue("学号");
            row.createCell(coreCustomFormItemList.size() + 3).setCellValue("填报时间");
            for (int i = 0; i < coreCustomFormItemList.size(); i++) {
                row.createCell(i + 5).setCellValue(coreCustomFormItemList.get(i).getItemTitle());
            }
            List<Map> submitFormDataListByFormId = this.findSubmitFormDataListByFormId(formId, null, null);
            for (int j = 0; j < submitFormDataListByFormId.size(); j++) {
                XSSFRow row1 = sheet.createRow(j + 1);
                Map map = submitFormDataListByFormId.get(j);
                Iterator<String> iter = map.keySet().iterator();
                while (iter.hasNext()) {
                    //字段名称
                    String key = iter.next();
                    //填报值
                    Object value = map.get(key);

                    if ("id".equals(key)) {
                        row1.createCell(0).setCellValue(ObjectUtil.toString(value));
                        continue;
                    }
                    if ("user_id".equals(key)) {
                        EduStudent hget = (EduStudent) redisService.hget(STUDENT_DATA, value.toString());
                        String classAndGrade = hget.getGradeName() + hget.getClassName();
                        row1.createCell(1).setCellValue(ObjectUtil.toString(classAndGrade));
                        row1.createCell(2).setCellValue(ObjectUtil.toString(hget.getStuName()));
                        row1.createCell(3).setCellValue(ObjectUtil.toString(hget.getStuNumber()));
                        continue;
                    }
                    if ("create_date".equals(key)) {
                        SimpleDateFormat myFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        row1.createCell(coreCustomFormItemList.size() + 3).setCellValue(myFmt.format(myFmt.parse(ObjectUtil.toString(value))));
                        continue;
                    }
                    for (int i = 0; i < coreCustomFormItemList.size(); i++) {
                        String itemFiledName = coreCustomFormItemList.get(i).getItemFiledName();
                        if (key.equals(itemFiledName)) {
                            row1.createCell(i + 5).setCellValue(ObjectUtil.toString(value));
                        }
                    }
                }
            }
            ExcelUtil.export("表单数据", "xlsx", workbook, response);
        } else if (byId.getRecever() == 2) {
            XSSFWorkbook workbook = new XSSFWorkbook();
            XSSFSheet sheet = workbook.createSheet();
            XSSFRow row = sheet.createRow(0);
            List<CoreCustomFormItems> coreCustomFormItemList = coreCustomFormItemsService.list(Wrappers.<CoreCustomFormItems>query().lambda().eq(CoreCustomFormItems::getFormId, formId));
            row.createCell(0).setCellValue("序号");
            row.createCell(1).setCellValue("班级");
            row.createCell(2).setCellValue("家长");
            row.createCell(3).setCellValue("电话");
            row.createCell(coreCustomFormItemList.size() + 3).setCellValue("填报时间");
            for (int i = 0; i < coreCustomFormItemList.size(); i++) {
                row.createCell(i + 5).setCellValue(coreCustomFormItemList.get(i).getItemTitle());
            }

            List<Map> submitFormDataListByFormId = this.findSubmitFormDataListByFormId(formId, null, null);
            for (int j = 0; j < submitFormDataListByFormId.size(); j++) {
                XSSFRow row1 = sheet.createRow(j + 1);
                Map map = submitFormDataListByFormId.get(j);
                Iterator<String> iter = map.keySet().iterator();
                while (iter.hasNext()) {
                    //字段名称
                    String key = iter.next();
                    //填报值
                    Object value = map.get(key);

                    if ("id".equals(key)) {
                        row1.createCell(0).setCellValue(ObjectUtil.toString(value));
                        continue;
                    }
                    if ("user_id".equals(key)) {
                        CoreCustomFormRelationUserParent one = parentService.getOne(Wrappers.lambdaQuery(new CoreCustomFormRelationUserParent())
                                .eq(CoreCustomFormRelationUserParent::getCustomFormId, formId)
                                .eq(CoreCustomFormRelationUserParent::getParentId, key));
                        CoreCustomFormRelationUser relationStudent = userService.getById(one.getCustomUserId());

                        EduStudent hget = (EduStudent) redisService.hget(STUDENT_DATA, relationStudent.getUserId().toString());
                        List<EduParent> parents = hget.getParents();
                        EduParent parent = parents.stream().filter(p -> p.getWxId().equals(key)).collect(Collectors.toList()).get(0);

                        String classAndGrade = hget.getGradeName() + hget.getClassName();
                        row1.createCell(1).setCellValue(ObjectUtil.toString(classAndGrade));
                        row1.createCell(2).setCellValue(ObjectUtil.toString(parent.getParentType()));
                        row1.createCell(3).setCellValue(ObjectUtil.toString(parent.getMobile()));
                        continue;
                    }
                    if ("create_date".equals(key)) {
                        SimpleDateFormat myFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        row1.createCell(coreCustomFormItemList.size() + 3).setCellValue(myFmt.format(myFmt.parse(ObjectUtil.toString(value))));
                        continue;
                    }
                    for (int i = 0; i < coreCustomFormItemList.size(); i++) {
                        String itemFiledName = coreCustomFormItemList.get(i).getItemFiledName();
                        if (key.equals(itemFiledName)) {
                            row1.createCell(i + 4).setCellValue(ObjectUtil.toString(value));
                        }
                    }
                }
            }
            ExcelUtil.export("表单数据", "xlsx", workbook, response);
        }
    }

    @Override
    public Map findData(Long formId, Long userId) {
        CoreCustomForm form = coreCustomFormService.getById(formId);
        String sql = "select * from " + form.getTableName() + " where user_id = " + userId;

        return coreCustomFormDataMapper.findData(sql);
    }

    @Override
    public void truncateTable(String sql) {
        coreCustomFormDataMapper.truncateTable(sql);
    }

}
