package com.tduck.cloud.api.web.controller;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tduck.cloud.api.annotation.Login;
import com.tduck.cloud.api.annotation.NoRepeatSubmit;
import com.tduck.cloud.api.util.HttpUtils;
import com.tduck.cloud.common.email.MailService;
import com.tduck.cloud.common.util.CacheUtils;
import com.tduck.cloud.common.util.Result;
import com.tduck.cloud.common.validator.ValidatorUtils;
import com.tduck.cloud.form.entity.*;
import com.tduck.cloud.form.entity.enums.FormItemTypeEnum;
import com.tduck.cloud.form.request.QueryFormResultRequest;
import com.tduck.cloud.form.service.UserFormDataService;
import com.tduck.cloud.form.service.UserFormItemService;
import com.tduck.cloud.form.service.UserFormService;
import com.tduck.cloud.form.service.UserFormSettingService;
import com.tduck.cloud.form.util.FormDataImportUtils;
import com.tduck.cloud.wx.mp.service.WxMpUserMsgService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

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

import static com.tduck.cloud.form.constant.FormConstants.FORM_VIEW_COUNT;


/**
 * @author : smalljop
 * @description : 表单数据页 当前用户自己使用接口
 * @create : 2020-11-18 18:17
 **/

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/user/form/data")
public class UserFormResultController {
    private final UserFormService userFormService;
    private final UserFormDataService formResultService;
    private final UserFormSettingService userFormSettingService;
    private final MailService mailService;
    private final WxMpUserMsgService userMsgService;
    private final FormDataImportUtils formDataImportUtils;
    private final CacheUtils cacheUtils;
    private final UserFormItemService formItemService;
    private final UserFormService formService;


    /***
     * 查看表单
     *  记录查看的IP 统计查看用户数
     * @return
     */
    @GetMapping("view/{formKey}")
    public Result viewForm(HttpServletRequest request, @PathVariable("formKey") String formKey) {
        Long incr = cacheUtils.incr(StrUtil.format(FORM_VIEW_COUNT, formKey), 1);
        return Result.success();
    }

    /**
     * 查询数据
     *
     * @param request
     * @return
     */
    @PostMapping("query")
    public Result queryFormDataTable(@RequestBody QueryFormResultRequest request) {
        return Result.success(formResultService.listFormDataTable(request));
    }


    /**
     * 填写附件导出
     *
     * @param request
     * @return
     */
    @Login
    @PostMapping("/download/file")
    public Result downloadFormResultFile(@RequestBody QueryFormResultRequest request) {
        return formResultService.downloadFormResultFile(request);
    }

    /**
     * 填写
     *
     * @param entity
     * @param request
     * @return
     */
    @NoRepeatSubmit
    @PostMapping("/create")
    public Result createFormResult(@RequestBody UserFormDataEntity entity, HttpServletRequest request) {
        ValidatorUtils.validateEntity(entity);
        entity.setSubmitRequestIp(HttpUtils.getIpAddr(request));
        formResultService.saveFormResult(entity);
        ThreadUtil.execAsync(() -> {
            UserFormNotifySettingEntity notifySettingEntity = userFormSettingService.getNotifySettingByKey(entity.getFormKey());
            this.sendWriteResultNotify(notifySettingEntity, entity);
        });
        return Result.success();
    }


    /**
     * 公开填写
     *
     * @param entity
     * @param request
     * @return
     */
    @NoRepeatSubmit
    @PostMapping("/public/create")
    public Result createPublicFormResult(@RequestBody UserFormDataEntity entity, HttpServletRequest request) {
        ValidatorUtils.validateEntity(entity);
        entity.setSubmitRequestIp(HttpUtils.getIpAddr(request));
        Result<UserFormWriteSettingEntity> userFormSettingStatus = userFormSettingService.getUserFormWriteSettingStatus(entity.getFormKey(), entity.getSubmitRequestIp(), entity.getWxOpenId());
        if (StrUtil.isNotBlank(userFormSettingStatus.getMsg())) {
            return Result.failed(userFormSettingStatus.getMsg());
        }
        formResultService.saveFormResult(entity);
        ThreadUtil.execAsync(() -> {
            UserFormNotifySettingEntity notifySettingEntity = userFormSettingService.getNotifySettingByKey(entity.getFormKey());
            this.sendWriteResultNotify(notifySettingEntity, entity);
        });

        //解析原始数据
        Map<String, Object> originalData = entity.getOriginalData();
        List<UserFormItemEntity> userFormItemEntities = formItemService
                .list(Wrappers.<UserFormItemEntity>lambdaQuery().eq(UserFormItemEntity::getFormKey, entity.getFormKey()));

        Map<String, UserFormItemEntity> userFormItemMap = userFormItemEntities.stream().collect(Collectors.toMap(UserFormItemEntity::getFormItemId, t->t,(t1, t2)->t1));
        UserFormEntity userFormEntity = formService
                .getOne(Wrappers.<UserFormEntity>lambdaQuery().eq(UserFormEntity::getKey, entity.getFormKey()));
        StringBuilder columnSql = new StringBuilder();
        StringBuilder valueSql = new StringBuilder();
        columnSql.append("form_key,")
                .append("serial_number,")
//                .append("submit_ua,")
                .append("submit_os,")
                .append("submit_browser,")
                .append("submit_request_ip,")
                .append("submit_address,")
                .append("complete_time,")
                .append("wx_open_id,")
//                .append("wx_user_info,")
        ;
        valueSql.append(String.format("'%s',",entity.getFormKey()))
                .append(entity.getSerialNumber()+",")
//                .append(entity.getSubmitUa()+",")
                .append(String.format("'%s',",entity.getSubmitOs()))
                .append(String.format("'%s',",entity.getSubmitBrowser()))
                .append(String.format("'%s',",entity.getSubmitRequestIp()))
                .append(String.format("'%s',",entity.getSubmitAddress()))
                .append(entity.getCompleteTime()+",")
                .append(String.format("'%s',",entity.getWxOpenId()))
//                .append(entity.getWxUserInfo()+",")
        ;


        for(Map.Entry<String, Object> entry : originalData.entrySet()) {
            if (userFormItemMap.containsKey(entry.getKey())){
                UserFormItemEntity itemEntity = userFormItemMap.get(entry.getKey());
                itemEntity.setFormItemId(itemEntity.getFormItemId().replaceAll("-","_"));
                Object object = originalData.get(entry.getKey());
                if (FormItemTypeEnum.PROVINCE_CITY.equals(itemEntity.getType())){//省市联动
                    ArrayList values = (ArrayList)object;
                    columnSql.append(itemEntity.getFormItemId()+"_0,");
                    columnSql.append(itemEntity.getFormItemId()+"_1,");
                    columnSql.append(itemEntity.getFormItemId()+"_2,");
                    if (values.size()==0){
                        valueSql.append(null+",");
                        valueSql.append(null+",");
                        valueSql.append(null+",");
                    }else {
                        valueSql.append(String.format("'%s',",values.get(0)));
                        valueSql.append(String.format("'%s',",values.get(1)));
                        valueSql.append(String.format("'%s',",values.get(2)));
                    }

                }else if (FormItemTypeEnum.CHECKBOX.equals(itemEntity.getType())){//多选框组
                    List<Integer> values = (ArrayList)object;
                    if (values.size()>0){
                        for (Integer i : values){
                            columnSql.append(itemEntity.getFormItemId()+"_"+i+",");
                            valueSql.append(String.format("'%s',",1));
                        }
                    }
                }else if (FormItemTypeEnum.UPLOAD.equals(itemEntity.getType()) || FormItemTypeEnum.IMAGE_UPLOAD.equals(itemEntity.getType())){//多选框组
                    List<Map<String,Object>> values = (ArrayList)object;
                    columnSql.append(itemEntity.getFormItemId()+",");
                    StringBuilder uploadValueSql = new StringBuilder();
                    for (Map<String,Object> value : values){
                        uploadValueSql.append(value.get("url")+",");
                    }
                    uploadValueSql.deleteCharAt(uploadValueSql.length() - 1);
                    valueSql.append(String.format("'%s',",uploadValueSql.toString()));
                } else {
                    if (object == null|| object.equals("")){
                        columnSql.append(itemEntity.getFormItemId()+",");
                        valueSql.append(null+",");
                    }else {
                        if (FormItemTypeEnum.NUMBER.equals(itemEntity.getType())
                                ||FormItemTypeEnum.SELECT.equals(itemEntity.getType())
                                ||FormItemTypeEnum.RADIO.equals(itemEntity.getType())
                                ||FormItemTypeEnum.RATE.equals(itemEntity.getType())
                        ){
                            Integer value=(Integer)object;
                            columnSql.append(itemEntity.getFormItemId()+",");
                            valueSql.append(String.format("'%s',",value));

                        }else {
                            String value=(String)object;
                            columnSql.append(itemEntity.getFormItemId()+",");
                            valueSql.append(String.format("'%s',",value));
                        }

                    }

                }

            }
        }

        columnSql.deleteCharAt(columnSql.length() - 1);
        valueSql.deleteCharAt(valueSql.length() - 1);
        String insertSql= String.format("insert into %s(%s) values(%s)","form_"+userFormEntity.getId(),columnSql,valueSql);
        formService.executeSql(insertSql);
        return Result.success();
    }


    @PostMapping("/delete/{formKey}")
    public Result deleteFormData(@RequestBody List<String> dataIdList, @PathVariable("formKey") String formKey) {
        formResultService.deleteByIds(dataIdList, formKey);
        return Result.success();
    }


    @NoRepeatSubmit
    @PostMapping("/update")
    public Result updateFormResult(@RequestBody UserFormDataEntity entity, HttpServletRequest request) {
        ValidatorUtils.validateEntity(entity);
        formResultService.updateFormResult(entity);
        return Result.success();
    }

    /**
     * 下载导入模板
     *
     * @param response
     * @param formKey
     */
    @GetMapping("/import/template")
    public void downloadImportTemplate(HttpServletResponse response, String formKey) {
        formDataImportUtils.importTemplateExcel(response, formKey);
    }


    /**
     * 导入表单数据
     *
     * @param file
     * @return
     */
    @PostMapping("import")
    public Result importFormData(@RequestParam("file") MultipartFile file, UserFormDataEntity dataEntity) throws IOException {
        return Result.success(formDataImportUtils.importFile(file.getInputStream(), dataEntity.getFormKey()));
    }


    private void sendWriteResultNotify(UserFormNotifySettingEntity settingEntity, UserFormDataEntity entity) {
        if (ObjectUtil.isNull(settingEntity)) {
            return;
        }
        String formKey = entity.getFormKey();
        UserFormEntity Form = userFormService.getByKey(formKey);
        if (StrUtil.isNotBlank(settingEntity.getNewWriteNotifyEmail())) {
            mailService.sendTemplateHtmlMail(settingEntity.getNewWriteNotifyEmail(), "新回复通知", "mail/form-write-notify", MapUtil.of("FormName", Form.getName()));
        }

        if (StrUtil.isNotBlank(settingEntity.getNewWriteNotifyWx())) {
            List<String> openIdList = StrUtil.splitTrim(settingEntity.getNewWriteNotifyWx(), ";");
            openIdList.stream().forEach(openId -> {
                userMsgService.sendKfTextMsg("", openId, "收到新的反馈，请去Pc端查看");
            });
        }
    }


}