package com.ruoyi.system.service.form;


import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.system.domain.form.*;
import com.ruoyi.system.domain.form.enums.EnumFormPublishStatus;
import com.ruoyi.system.domain.form.enums.EnumFormStatus;
import com.ruoyi.system.domain.form.enums.EnumFormType;
import com.ruoyi.system.domain.form.params.FormAddTemplateBody;
import com.ruoyi.system.domain.form.params.FormCopyBody;
import com.ruoyi.system.domain.form.params.FormQuery;
import com.ruoyi.system.domain.form.vo.FormVo;
import com.ruoyi.system.mapper.system.SysUserMapper;
import com.ruoyi.system.service.system.ISysUserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class FormManager {
    private ExecutorService threadPools = new ThreadPoolExecutor(8, 30, 10,
            TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5000), new ThreadPoolExecutor.CallerRunsPolicy());

    @Autowired
    private MdFormService formService;
    @Autowired
    private MdFormTemplateService mdFormTemplateService;
    @Autowired
    private MdFormTemplateService formTemplateService;
    @Autowired
    private MdFormReadService formReadService;
    @Autowired
    private FormRecordManager recordManager;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private FormMsgManager msgManager;

    /**
     * 正则表达式：验证手机号
     */
    public static final String REGEX_MOBILE = "^(1)\\d{10}$";


    public List<MdForm> query(FormQuery query) {
        MdFormExample example = buildEx(query);
        example.setOrderByClause("create_time desc");
        List<MdForm> formList = formService.selectByExampleWithBLOBs(example);
        List<MdForm> formListNew = new ArrayList<>();
        for (MdForm form : formList) {
            if (!"".equals(form.getOwnUser())) {
                SysUser sysUser = sysUserService.selectUserById(form.getOwnUser());
                form.setOwnUserName(sysUser == null ? "" : sysUser.getNickName());
            }
            if (null == form.getReadType() || 2 == form.getReadType() || StringUtils.isEmpty(query.getUserId()) || StringUtils.isEmpty(query.getIsMasterAdmin()) || "1".equals(query.getIsMasterAdmin())) {
                formListNew.add(form);
            } else if (1 == form.getReadType()) {

                SysUser queryUser = sysUserService.selectUserById(query.getUserId());
                SysUser ownUser = sysUserService.selectUserById(form.getOwnUser());

                if (queryUser.getDeptId() != null && ownUser.getDeptId() != null && queryUser.equals(ownUser)) {
                    formListNew.add(form);
                }
            } else if (3 == form.getReadType()) {
                if (query.getUserId().equals(form.getOwnUser())) {
                    formListNew.add(form);
                }
            } else if (4 == form.getReadType()) {
                MdFormReadExample example3 = new MdFormReadExample();
                MdFormReadExample.Criteria criteria = example3.createCriteria();
                criteria.andFormIdEqualTo(form.getId()).andUserIdEqualTo(query.getUserId());
                List<MdFormRead> reads = formReadService.selectByExample(example3);
                if (reads.size() > 0) {
                    formListNew.add(form);
                }
            }
        }
        return formListNew;
    }

    public int count(FormQuery query) {
        MdFormExample example = buildEx(query);
        return formService.countByExample(example);
    }


    public MdForm detail(String id) {
        MdForm mdForm = formService.selectByPrimaryKey(id);
        return mdForm;
    }

    //此处怕别处引用了detail，而使用update等操作失败问题
    public FormVo detail2(String id) {
        MdForm mdForm = formService.selectByPrimaryKey(id);
        String name = "";
        try {
            if (mdForm.getPublishMode() != null && mdForm.getPublishMode() == 0) {
                //部分
                List<String> list = Arrays.asList(mdForm.getPublishUser().split(","));
                if (CollectionUtils.isNotEmpty(list)) {

                    List<SysUser> sysUserList = sysUserMapper.listByIds(list);
                    if (CollectionUtils.isNotEmpty(sysUserList)) {
                        for (SysUser sysUser : sysUserList) {
                            name = sysUser.getNickName() + ",";
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        FormVo formVo = new FormVo();
        BeanUtils.copyProperties(mdForm, formVo);

        if (StringUtils.isNotBlank(mdForm.getOwnUser()) && !"".equals(mdForm.getOwnUser())) {
            formVo.setCreateRealName(sysUserService.selectUserById(mdForm.getOwnUser()).getNickName());
        }
        formVo.setUserName(name);
        if (4 == mdForm.getReadType()) {
            String userId = "";
            MdFormReadExample example3 = new MdFormReadExample();
            MdFormReadExample.Criteria criteria = example3.createCriteria();
            criteria.andFormIdEqualTo(mdForm.getId());
            List<MdFormRead> reads = formReadService.selectByExample(example3);
            for (MdFormRead read : reads) {
                userId += read.getUserId() + ",";
            }
            formVo.setUserId(userId);
        }
        return formVo;
    }

    /**
     * 设计保存
     */
    public String save(MdForm body) {

        if (body == null
                || StringUtils.isBlank(body.getFormConfig())) {
            throw new RuntimeException("表单定义为空");
        }

        if (StringUtils.isBlank(body.getId())) {
            body.setId("form-" + UUID.randomUUID().toString());
            body.setPublishStatus(EnumFormPublishStatus.toPublish.code);
            body.setStatus(EnumFormStatus.normal.code);

            body.setRecordNum(0);
            body.setCreateTime(System.currentTimeMillis());

            if (formService.insertSelective(body) > 0) {
                return body.getId();
            }

            throw new RuntimeException("保存表单失败");
        } else {

            if (formService.updateByPrimaryKeySelective(body) > 0) {
                return body.getId();
            }

            throw new RuntimeException("更新表单失败");
        }
    }

    private void saveToTemplate(MdForm mdForm) {
        //是否保存到模板
        MdFormTemplate mdFormTemplate = new MdFormTemplate();
        mdFormTemplate.setId(UUID.randomUUID().toString());
        mdFormTemplate.setName(mdForm.getName());
        //校验模板名称
        MdFormTemplateExample example = new MdFormTemplateExample();
        MdFormTemplateExample.Criteria c = example.createCriteria();
        c.andNameEqualTo(mdFormTemplate.getName());
        c.andStatusEqualTo(1);

        //先判定是否有重复的名称
        int templateNameCount = mdFormTemplateService.countByExample(example);
        if (templateNameCount > 0) {
            mdFormTemplate.setName(mdForm.getName() + templateNameCount);
        }

        mdFormTemplate.setImg(mdForm.getImg());
        mdFormTemplate.setStatus(1);
        mdFormTemplate.setFormConfig(mdForm.getFormConfig());
        mdFormTemplate.setCreateTime(System.currentTimeMillis());
        mdFormTemplate.setOwnUser(mdForm.getOwnUser());
        mdFormTemplate.setOwnDept(mdForm.getOwnDept());
        formTemplateService.insertSelective(mdFormTemplate);
    }

    public void createRecords(MdForm mdForm) {
        if (mdForm.getPublishMode() == null) {
            return;
        }

        //发布方式 0-部分 1-全部
        if (1 == mdForm.getPublishMode()) {
            SysUser sysUser = new SysUser();
            sysUser.setStatus("0");

            List<SysUser> sysUserList = sysUserService.selectUserList(sysUser);
            // 查出所有用户
            List<String> userIds = sysUserList.stream().map(SysUser::getUserId)
                    .distinct().collect(Collectors.toList());
            insertRecords(userIds, mdForm);

        } else {
            if (StringUtils.isEmpty(mdForm.getPublishUser())) {
                throw new RuntimeException("部分用户不能为空！");
            }
            String[] strings = mdForm.getPublishUser().split(",");
            insertRecords(Arrays.asList(strings), mdForm);
        }
    }

    public void insertRecords(List<String> userIds, MdForm mdForm) {

        if (CollectionUtils.isEmpty(userIds)) {
            return;
        }

        List<MdFormRecord> list = new ArrayList<>();
        for (String string : userIds) {
            MdFormRecord record = new MdFormRecord();
            record.setFormId(mdForm.getId());
            record.setId("record-" + UUID.randomUUID().toString());
            record.setStatus(1);
            record.setCommitStatus(0);
            record.setOwnUser(string);
            record.setCommitCycle(mdForm.getCycleNow());
            list.add(record);
        }

        int count = recordManager.insertBatch(list);
        if (count > 0) {
            //发送消息
            msgManager.send4Publish(userIds, mdForm);
        } else {
            throw new RuntimeException("发布失败");
        }
    }

    /**
     * 给万事通用的基于template的表单保存
     *
     * @param templateId
     */
    public String saveFormTemplateWithWST(String templateId, String userId) {

        MdFormTemplate mdFormTemplate = formTemplateService.selectByPrimaryKey(templateId);

        FormAddTemplateBody body = new FormAddTemplateBody();
        body.setUserId(userId);
        body.setSaveTemplateFlag(0);

        body.setName(mdFormTemplate.getName());
        body.setImg(mdFormTemplate.getImg());
        body.setCategoryId(mdFormTemplate.getCategoryId());
        body.setCollectMode(EnumFormType.fix.text);
        body.setFixStart(946656000L);
        body.setFixEnd(32503651200L);
        body.setFormConfig(mdFormTemplate.getFormConfig());
        body.setNeedRation(0);
        body.setPublishMode(null);
        body.setReadType(2);
        return publish(body);
    }

    /**
     * 表单发布
     */
    @Transactional
    public String publish(FormAddTemplateBody body) {

        if (body == null) {
            throw new RuntimeException("表单内容不能为空");
        }
        if (StringUtils.isBlank(body.getFormConfig())) {
            throw new RuntimeException("表单定义为空");
        }

        //获取当前周期
        if (EnumFormType.cycle.text.equals(body.getCollectMode())) {
            body.setCycleNow(getCycleNow(body.getCycleType()));
        }
        //如果是临时表单
        if (EnumFormType.fix.text.equals(body.getCollectMode())) {
            body.setFixStart(DateUtil.beginOfDay(DateUtil.date(body.getFixStart())).getTime());
            body.setFixEnd(DateUtil.endOfDay(DateUtil.date(body.getFixEnd())).getTime());
            long nowTime = System.currentTimeMillis();
            if (body.getFixStart() <= nowTime && nowTime < body.getFixEnd()) {
                //如果当前时间在发布期间，则更改当前时间为发布状态
                body.setPublishStatus(1);
            }
            if (nowTime >= body.getFixEnd()) {
                body.setPublishStatus(2);
            }
            if (body.getFixStart() > nowTime) {
                body.setPublishStatus(1);
            }
        }

        MdForm mdForm = new MdForm();
        BeanUtils.copyProperties(body, mdForm);

        String readFormId = "";
        //保存表单或者更新表单
        if (StringUtils.isBlank(mdForm.getId())) {
            String formId = UUID.randomUUID().toString();
            mdForm.setId("form-" + formId);
            mdForm.setStatus(EnumFormStatus.normal.code);
            mdForm.setRecordNum(0);
            mdForm.setCreateTime(System.currentTimeMillis());
            mdForm.setPublishStatus(EnumFormPublishStatus.collecting.code);
            mdForm.setPublishTime(System.currentTimeMillis());
            mdForm.setReadType(body.getReadType());
            if (formService.insertSelective(mdForm) == 0) {
                throw new RuntimeException("保存表单失败");
            }
            //创建表单数据记录
            createRecords(mdForm);
            readFormId = "form-" + formId;
        } else {
            MdForm old = formService.selectByPrimaryKey(mdForm.getId());
            mdForm.setOwnUser(old.getOwnUser());
            mdForm.setOwnDept(old.getOwnDept());
            mdForm.setRecordNum(old.getRecordNum());
            if (null != old.getIsSend()) {
                mdForm.setIsSend(old.getIsSend());
            }
            mdForm.setReadType(body.getReadType());
            //根据mdForm.getId()删除之前数据 新增绑定userId
            MdFormReadExample example3 = new MdFormReadExample();
            MdFormReadExample.Criteria criteria = example3.createCriteria();
            criteria.andFormIdEqualTo(mdForm.getId());
            formReadService.deleteByExample(example3);
            readFormId = mdForm.getId();
            //未发布 ->发布
            if (old.getPublishStatus() == null || old.getPublishStatus() == EnumFormPublishStatus.toPublish.code) {
                if (EnumFormType.cycle.text.equals(body.getCollectMode())) {
                    mdForm.setPublishStatus(EnumFormPublishStatus.collecting.code);
                    mdForm.setPublishTime(System.currentTimeMillis());
                } else {
                    mdForm.setPublishTime(System.currentTimeMillis());
                }
                if (formService.updateByPrimaryKeySelective(mdForm) == 0) {
                    throw new RuntimeException("更新表单失败");
                }

                //创建表单数据记录
                createRecords(mdForm);

            }
            //已发布 -> 更新
            else {
                //更新数据
                if (formService.updateByPrimaryKeySelective(mdForm) == 0) {
                    throw new RuntimeException("更新表单失败");
                }

                /*
                 * 新增企业：周期表单从下周期生效，提醒使用截止日期前多少天提醒；普通表单若是新增企业，需消息提醒
                 * 删除企业：若是企业已填写数据，保留数据；未填写则删除
                 */

                //更新表单数据
                if (old.getPublishMode() == 0) {

                    List<String> old_list = Lists.newArrayList(old.getPublishUser().split(","));
                    List<String> new_list = Lists.newArrayList(mdForm.getPublishUser().split(","));

                    List<String> delete_list = old_list.stream().filter(item -> !new_list.contains(item))
                            .collect(Collectors.toList());
                    List<String> add_list = new_list.stream().filter(item -> !old_list.contains(item))
                            .collect(Collectors.toList());

                    //删除企业：若是企业已填写数据，保留数据；未填写则删除
                    if (!CollectionUtils.isEmpty(delete_list)) {
                        recordManager.deleteNoCommit(mdForm.getId(), mdForm.getCycleNow(), delete_list);
                    }

                    //新增企业：周期表单从下周期生效，提醒使用截止日期前多少天提醒；普通表单若是新增企业，需消息提醒
                    if (!CollectionUtils.isEmpty(add_list) && EnumFormType.fix.text.equals(mdForm.getCollectMode())) {
                        insertRecords(add_list, mdForm);
                    }
                }
            }

        }

        //新增查看人员
        if (null != body.getReadType()) {
            if (4 == body.getReadType()) {
                if (StringUtils.isNotEmpty(body.getUserId())) {
                    String userId = body.getUserId();
                    if (StringUtils.isNotEmpty(body.getOwnUser())) {
                        userId = body.getOwnUser() + "," + userId;
                        addUserRead(readFormId, userId);
                    }
                }
            }
        }
        //是否保存到模板
        if (body.getSaveTemplateFlag() == 1) {//保存到模板
            saveToTemplate(mdForm);
        }
        return readFormId;
    }

    public AjaxResult readAuth(String userId, String formId) {
        Integer data = 0;
        MdForm form = formService.selectByPrimaryKey(formId);
        if (null == form.getReadType()) {
            //默认为同部门
            form.setReadType(1);
        }
        if (1 == form.getReadType()) {
            //判断是否同部门
            SysUser queryUser = sysUserService.selectUserById(userId);
            SysUser ownUser = sysUserService.selectUserById(form.getOwnUser());

            if (queryUser.getDeptId() != null && ownUser.getDeptId() != null && queryUser.equals(ownUser)) {
                data = 1;
            }
        } else if (2 == form.getReadType()) {
            //所有人
            data = 1;
        } else if (3 == form.getReadType()) {
            if (userId.equals(form.getOwnUser())) {
                data = 1;
            } else {
                data = 0;
            }
        } else if (4 == form.getReadType()) {
            MdFormReadExample example3 = new MdFormReadExample();
            MdFormReadExample.Criteria criteria = example3.createCriteria();
            criteria.andFormIdEqualTo(formId).andUserIdEqualTo(userId);
            List<MdFormRead> reads = formReadService.selectByExample(example3);
            if (reads.size() > 0) {
                data = 1;
            }
        }
        return AjaxResult.success(data);
    }

    private void addUserRead(String formId, String userId) {
        String[] userIdArray = userId.split(",");
        //去重
        LinkedHashSet<String> temp = new LinkedHashSet<>();
        for (int i = 0; i < userIdArray.length; i++) {
            temp.add(userIdArray[i]);
        }
        for (String id : temp) {
            MdFormRead read = new MdFormRead();
            read.setId(UUID.randomUUID().toString());
            read.setFormId(formId);
            read.setUserId(id);
            int result = formReadService.insert(read);
            if (result == 0) {
                throw new RuntimeException("保存查看人员失败");
            }
        }
    }

    private String getCycleNow(String cycleType) {
        StringBuffer cycle = new StringBuffer();
        LocalDate localDate2 = LocalDate.now();
        int year = localDate2.getYear();
        switch (cycleType) {
            //周
            case "ww":
                WeekFields weekFields = WeekFields.of(Locale.getDefault());
                int weekNumber = LocalDate.now().get(weekFields.weekOfWeekBasedYear());
                cycle.append(year).append("ww").append(weekNumber);
                break;
            //月
            case "m":
                LocalDate localDate = LocalDate.now();
                int m = localDate.getMonthValue();
                cycle.append(year).append("m").append(m);
                break;
            //季度
            default:
                LocalDate local = LocalDate.now();
                int mm = local.getMonthValue();
                String q = "";
                if (mm >= 1 && mm == 3) {
                    q = "1";
                } else if (mm >= 4 && mm <= 6) {
                    q = "2";
                } else if (mm >= 7 && mm <= 9) {
                    q = "3";
                } else {
                    q = "4";
                }
                cycle.append(year).append("q").append(q);
                break;
        }
        return cycle.toString();
    }

    public MdFormExample buildEx(FormQuery query) {
        MdFormExample example = new MdFormExample();
        if (query == null) {
            return example;
        }

        MdFormExample.Criteria c0 = example.createCriteria();

        if (query.getPublishStatus() != null) {
            c0.andPublishStatusEqualTo(query.getPublishStatus());
        }

        if (StringUtils.isNotEmpty(query.getCategoryId())) {
            c0.andCategoryIdEqualTo(query.getCategoryId());
        }

        if (StringUtils.isNotEmpty(query.getCollectMode())) {
            c0.andCollectModeEqualTo(query.getCollectMode());
        }

        if (StringUtils.isNotBlank(query.getKeyword())) {
            c0.andNameLike("%" + query.getKeyword() + "%");
        }

        if (query.getStatus() != null) {
            c0.andStatusEqualTo(query.getStatus());
        }
        //只看自己的
        if (StringUtils.isNotEmpty(query.getSelectByOwn())) {
            c0.andOwnUserEqualTo(query.getSelectByOwn());
            return example;
        }
        return example;
    }

    public int deleteById(MdForm body) {
        body.setStatus(2);
        int count = formService.updateByPrimaryKeySelective(body);
        return count;
    }

    public int copyForm(FormCopyBody formCopyBody) {
        MdForm mdForm = formService.selectByPrimaryKey(formCopyBody.getFormId());
        if (mdForm == null) return 0;

        MdForm mdForm2 = new MdForm();
        mdForm2.setId("form-" + UUID.randomUUID().toString());
        mdForm2.setName(formCopyBody.getName());
        mdForm2.setFormConfig(mdForm.getFormConfig());
        mdForm2.setCreateTime(System.currentTimeMillis());
        mdForm2.setOwnDept(formCopyBody.getOwnDept());
        mdForm2.setOwnUser(formCopyBody.getOwnUser());
        mdForm2.setStatus(1);
        mdForm2.setPublishStatus(0);
        int count = formService.insert(mdForm2);
        return count;
    }

    public Object stopById(String id) {
        MdForm mdForm = new MdForm();
        mdForm.setId(id);
        mdForm.setPublishStatus(2);
        int count = formService.updateByPrimaryKeySelective(mdForm);
        return count;
    }
}
