package cn.com.ctop.reimburse.mondule.service.impl;

import cn.com.ctop.common.module.service.ISendMessageService;
import cn.com.ctop.common.module.service.ISysDepartService;
import cn.com.ctop.common.module.service.ISysUserService;
import cn.com.ctop.common.module.service.IUserCompanyService;
import cn.com.ctop.common.module.utils.Check;
import cn.com.ctop.kuaishou.modules.report.mapper.KuaishouReportDailyAccountMapper;
import cn.com.ctop.reimburse.mondule.entity.ReimburseApply;
import cn.com.ctop.reimburse.mondule.entity.ReimburseApplyProcess;
import cn.com.ctop.reimburse.mondule.entity.ReimburseProject;
import cn.com.ctop.reimburse.mondule.mapper.ReimburseApplyMapper;
import cn.com.ctop.reimburse.mondule.service.IReimburseApplyProcessService;
import cn.com.ctop.reimburse.mondule.service.IReimburseApplyService;
import cn.com.ctop.reimburse.mondule.service.IReimburseProjectService;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.entity.SysDepart;
import org.jeecg.common.system.entity.SysUser;
import org.jeecg.common.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * 报销申请提交表
 *
 * @author jeecg-boot
 * 2022-11-21
 * @version V1.0
 */
@Slf4j
@Service
public class ReimburseApplyServiceImpl extends ServiceImpl<ReimburseApplyMapper, ReimburseApply> implements IReimburseApplyService {

    @Autowired
    private IReimburseProjectService projectService;

    @Autowired
    private IReimburseApplyProcessService processService;

    @Autowired
    private ISysDepartService sysDepartService;

    @Autowired
    private ISendMessageService sendMessageService;

    @Resource
    IUserCompanyService userCompanyService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private KuaishouReportDailyAccountMapper dailyAccountMapper;

    @Override
    public Result<Object> queryPageList(ReimburseApply reimburseApply, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<ReimburseApply> list = baseMapper.queryPageList(reimburseApply);
        return Result.ok(new PageInfo<>(list));
    }

    @Override
    public List<JSONObject> queryList(ReimburseApply reimburseApply) {
        return baseMapper.queryList(reimburseApply);
    }

    @Override
    public Result<Object> add(JSONObject data) throws Exception {
        ReimburseApply apply = JSONObject.parseObject(data.toJSONString(), ReimburseApply.class);
        List<String> ids = JSONObject.parseArray(data.getJSONArray("ids").toJSONString(), String.class);
        List<ReimburseProject> projects = projectService.getByIds(ids);
        if (!Check.isNull(projects)) {
            Integer invoices = 0;
            Double amount = 0.0;
            for (ReimburseProject project : projects) {
                invoices += project.getInvoices();
                amount += Double.valueOf(project.getAmount());
            }
            apply.setInvoices(invoices);
            apply.setAmount(amount.toString());
            apply.setType(projects.get(0).getType());
        }
        String leader = getLeader(data.getString("userId"));
        if (Check.isNull(leader)) {
            return Result.error("创建失败，userId:" + data.getString("userId") + "，未查询到下一级的审核人员，请联系管理员");
        }
        apply.setLeaderId(leader);
        SysUser user = sysUserService.getById(apply.getUserId());
        if (!Check.isNull(user)) {
            apply.setUserName(user.getRealname());
        }
        SysDepart depart = sysDepartService.getById(apply.getDepartId());
        if (!Check.isNull(depart)) {
            apply.setDepartName(depart.getDepartName());
        }
        String randomNumber = RandomUtil.randomNumbers(6);
        String today = DateUtils.formatDate(new Date());
        String todayStr = DateUtils.getDateInteger(today).toString();
        //20221125123456
        String id = todayStr + randomNumber;
        apply.setId(Long.valueOf(id));
        this.save(apply);
        for (ReimburseProject project : projects) {
            project.setApplyId(apply.getId());
            projectService.updateById(project);
        }
        baseMapper.insertRel(leader, apply.getId());

        //是否是福利费用，是则发送非空
        String welfareUser = checkWelfare(projects);
        addProcess(apply.getId(), data.getString("userId"), leader, welfareUser);

        return Result.ok();
    }

    //添加流程
    private void addProcess(Long applyId, String userId, String leaderId, String welfareUserId) throws Exception {
        List<ReimburseApplyProcess> list = new ArrayList<>();
        list.add(new ReimburseApplyProcess(applyId, userId, "0", 1, DateUtils.now()));
        List<String> leaders = getProcessLeaders(userId, 2);
        for (int i = 0; i < leaders.size(); i++) {
            if (leaderId.equals(leaders.get(i))) {
                list.add(new ReimburseApplyProcess(applyId, leaders.get(i), "3", i + 2, null));
            } else {
                list.add(new ReimburseApplyProcess(applyId, leaders.get(i), "4", i + 2, null));
            }
        }
        if (!Check.isNull(welfareUserId) && !leaders.contains(welfareUserId)) {
            list.add(new ReimburseApplyProcess(applyId, welfareUserId, "4", list.size() + 1, null));
        }
        list.add(new ReimburseApplyProcess(applyId, "-", "4", list.size() + 1, null));
        processService.saveBatch(list);
    }


    /*
    流程状态 状态 1待审核、2审核通过、3审核拒绝、4审核中、5部分拒绝
    更新流程 审核状态：0-创建，1-通过，2-拒绝，3-待审核，4-未审核，5-修改
     */
    private void updateProcess(Long applyId, String userId, String leaderId, String state, String welfareUserId) throws Exception {
        List<ReimburseApplyProcess> editlist = new ArrayList<>();
        List<ReimburseApplyProcess> list = processService.getListByApplyId(applyId);
        if ("2".equals(state)) {
            ReimburseApplyProcess process = list.get(list.size() - 1);
            process.setState("1");
            process.setStatTime(DateUtils.now());
            process.setUserId(userId);
            processService.updateById(process);
        } else if ("3".equals(state) || "5".equals(state)) {
            if (JSONArray.toJSONString(list).contains(userId)) {
                for (int i = list.size() - 1; i >= 0; i--) {
                    ReimburseApplyProcess process = list.get(i);
                    if (userId.equals(process.getUserId())) {
                        process.setState("2");
                        process.setStatTime(DateUtils.now());
                        break;
                    } else {
                        list.remove(i);
                    }
                }
                editlist.addAll(list);
                editlist.add(new ReimburseApplyProcess(applyId, list.get(0).getUserId(), "5", list.size() + 1, null));
                List<String> leaders = getProcessLeaders(userId, 2);
                for (int i = 0; i < leaders.size(); i++) {
                    editlist.add(new ReimburseApplyProcess(applyId, leaders.get(i), "4", i + list.size() + 2, null));
                }
                if (!Check.isNull(welfareUserId) && !leaders.contains(welfareUserId)) {
                    editlist.add(new ReimburseApplyProcess(applyId, welfareUserId, "4", editlist.size() + 1, null));
                }
                editlist.add(new ReimburseApplyProcess(applyId, "-", "4", editlist.size() + 1, null));
            } else {
                ReimburseApplyProcess process = list.get(list.size() - 1);
                process.setUserId(userId);
                process.setState("2");
                process.setStatTime(DateUtils.now());
                editlist.addAll(list);
                editlist.add(new ReimburseApplyProcess(applyId, list.get(0).getUserId(), "5", list.size() + 1, null));
                List<String> leaders = getProcessLeaders(list.get(0).getUserId(), list.size() + 2);
                for (int i = 0; i < leaders.size(); i++) {
                    editlist.add(new ReimburseApplyProcess(applyId, leaders.get(i), "4", i + list.size() + 2, null));
                }
                if (!Check.isNull(welfareUserId) && !leaders.contains(welfareUserId)) {
                    editlist.add(new ReimburseApplyProcess(applyId, welfareUserId, "4", editlist.size() + 1, null));
                }
                editlist.add(new ReimburseApplyProcess(applyId, "-", "4", editlist.size() + 1, null));

            }
            processService.deleteByApplyId(applyId);
            processService.saveBatch(editlist);

        } else if ("4".equals(state)) {
            for (int i = list.size() - 1; i >= 0; i--) {
                ReimburseApplyProcess process = list.get(i);
                if (process.getUserId().equals(leaderId)) {
                    process.setState("3");
                    editlist.add(process);
                }
                if (userId.equals(process.getUserId())) {
                    process.setState("1");
                    process.setStatTime(DateUtils.now());
                    editlist.add(process);
                    break;
                }
            }
            for (ReimburseApplyProcess applyProcess : editlist) {
                processService.updateById(applyProcess);
            }
        }

    }

    /**
     * 获取审核流程全部人员
     */
    private List<String> getProcessLeaders(String userId, Integer order) throws Exception {
        JSONObject company = userCompanyService.getCompanyInfoByUserId(userId);
        if (Check.isNull(company)) {
            throw new Exception("用户ID:" + userId + ",未查询到所属公司");
        }
        List<String> list = new ArrayList<>();
        String companyId = company.getString("companyId");
        if ("6608ed13c0dd42de93c790dbdf124234".equals(companyId)) {
            //广州汇创思拓数字科技有限公司（华南） 直接返回 何田田
            list.add("1cd4c769eabb4de98fed306de2a3bbbd");
        } else if ("4b10089775c040119e139087517aed88".equals(companyId)) {
            //上海汇创思拓数字科技有限公司 直接返回 吴婵
            list.add("183dce577efb49b386369473368cf251");
        } else {
            String user = baseMapper.selectFinalLeaders(userId, companyId);
            if (userId.equals(user)) {
                list.add(userId);
            } else {
                //查询部门
                List<SysDepart> departs = sysDepartService.queryUserDeparts(userId);
                if (!departs.isEmpty()) {
                    String orgCode = departs.get(0).getOrgCode();
                    JSONObject object = sysDepartService.queryAllParentIdByOrgCode(orgCode);
                    JSONObject map = object.getJSONObject(orgCode).getJSONObject("parentMap");
                    JSONObject leader = new JSONObject();
                    //查询审核人员信息
                    List<JSONObject> leaders = baseMapper.selectLeaders(companyId);
                    for (JSONObject obj : leaders) {
                        String departName = obj.getString("depart_name");
                        if (map.toJSONString().contains(departName)) {
                            leader = obj;
                            break;
                        }
                    }
                    if (leader.isEmpty()) {
                        return Collections.emptyList();
                    }
                    //第一审核人
                    if (!Check.isNull(leader.getString("first_id"))) {
                        list.add(leader.getString("first_id"));
                    }
                    //第二审核人
                    if (!Check.isNull(leader.getString("second_id"))) {
                        list.add(leader.getString("second_id"));
                    }
                    //终极审核人
                    if (!Check.isNull(leader.getString("final_id"))) {
                        list.add(leader.getString("final_id"));
                    }
                }
            }
        }
        return list;
    }

    @Override
    public Result<Object> edit(JSONObject data) throws Exception {

        String sender = null;
        String msg = null;
        String type = "1";
        //是否到财务审核
        boolean isFinancialReview = false;
        ReimburseApply apply = JSONObject.parseObject(data.toJSONString(), ReimburseApply.class);
        Long id = apply.getId();
        List<ReimburseProject> projects = null;
        if (Check.isNull(data.getJSONArray("ids"))) {
            QueryWrapper<ReimburseProject> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("apply_id", id);
            projects = projectService.list(queryWrapper);
        } else {
            List<String> ids = JSONObject.parseArray(data.getJSONArray("ids").toJSONString(), String.class);
            projects = projectService.getByIds(ids);
        }
        if (!Check.isNull(projects)) {
            Integer invoices = 0;
            Double amount = 0.0;
            for (ReimburseProject project : projects) {
                invoices += project.getInvoices();
                amount += Double.valueOf(project.getAmount());
                msg += project.getAuditDescription();
            }
            apply.setInvoices(invoices);
            apply.setAmount(amount.toString());
        }
        String welfareUser = welfareUser = checkWelfare(projects);
        //登录人ID
        String loginId = data.getString("loginId");
        //创建人操作，直接修改
        if (loginId.equals(apply.getUserId())) {
            //获取下次审核人信息
            sender = getLeader(loginId);
            if (Check.isNull(sender)) {
                return Result.error("修改失败，userId:" + loginId + "，未查询到下一级的审核人员，请联系管理员");
            }
            apply.setLeaderId(sender);
            apply.setStatus("1");
            this.updateById(apply);
            for (ReimburseProject project : projects) {
                project.setApplyId(apply.getId());
                project.setAuditDescription("");
                projectService.updateById(project);
            }
            updateProcess(id, loginId, sender, "4", welfareUser);
            return Result.ok();
        } else {
            ReimburseApply entity = this.getById(apply.getId());
            //状态 1待审核、2审核通过、3审核拒绝、4审核中、5部分拒绝
            String status = data.getString("status");
            String leader = null;
            if ("1".equals(entity.getFinalStatus())) {
                if ("4".equals(status)) {
                    //判断是否是 财务人员
                    String roleCode = dailyAccountMapper.getRoleCodeByUserId(loginId);
                    if ("financialReview".equals(roleCode)) {
                        apply.setStatus("2");
                        status = apply.getStatus();
                    } else {
                        //发送 财务审核
                        isFinancialReview = true;
                        apply.setLeaderId("");
                    }
                } else if ("3".equals(status) || "5".equals(status)) {
                    apply.setLeaderId("");
                    apply.setFinalStatus("0");
                    sender = apply.getUserId();
                }
                updateProcess(id, loginId, sender, status, welfareUser);
            } else if (loginId.equals(entity.getLeaderId())) {
                //获取下次审核人信息
                leader = getLeader(entity.getLeaderId());
                if (Check.isNull(leader)) {
                    return Result.error("编辑失败，userId:" + entity.getLeaderId() + "，未查询到下一级的审核人员，请联系管理员");
                }
                //审核人 操作流程：↓↓↓
                if ("4".equals(status)) {
                    if (loginId.equals(leader)) {
                        //登录人和待审核人一样，则是部门最后审核人
                        apply.setFinalStatus("1");
                        //是否是福利费用，是则发送审核 到指定审核人;否则 发送到财务
                        if (!Check.isNull(welfareUser) && !welfareUser.equals(loginId)) {
                            apply.setLeaderId(welfareUser);
                            sender = welfareUser;
                        } else {
                            //发送 财务审核
                            isFinancialReview = true;
                            apply.setLeaderId("");
                        }
                    } else {
                        sender = leader;
                        apply.setLeaderId(leader);
                    }
                } else if ("3".equals(status) || "5".equals(status)) {
                    apply.setLeaderId("");
                    apply.setFinalStatus("0");
                    sender = apply.getUserId();
                }
                updateProcess(id, loginId, sender, status, welfareUser);
            }
            this.updateById(apply);
            if (!Check.isNull(sender)) {
                baseMapper.insertRel(sender, apply.getId());
            }
            //流程到财务审核
            if (isFinancialReview) {
                //财务审核roleId : 32825ea6b43cb61bffa09bf05ad69cf2
                List<SysUser> users = sysUserService.getUserListByRoleId("32825ea6b43cb61bffa09bf05ad69cf2");
                for (SysUser user : users) {
                    sendMsg(user.getId(), type, id, msg);
                }
            } else {
                if (!Check.isNull(sender)) {
                    sendMsg(sender, type, id, msg);
                }
            }
        }
        return Result.ok();
    }

    @Override
    public Result<Object> submitReview(String id) {
        ReimburseApply apply = this.getById(id);
        apply.setStatus("4");
        this.updateById(apply);
        if (!Check.isNull(apply.getLeaderId())) {
            sendMsg(apply.getLeaderId(), "1", id, null);
        }
        return Result.ok();
    }

    @Override
    public List<JSONObject> getCompanyList() {
        return baseMapper.queryLeaderCompanyList();
    }

    @Override
    public List<JSONObject> queryProcess(Long applyId) {
        return processService.queryProcess(applyId);
    }

    // 获取审核人ID
    private String getLeader(String userId) throws Exception {
        JSONObject company = userCompanyService.getCompanyInfoByUserId(userId);
        if (Check.isNull(company)) {
            throw new Exception("用户ID:" + userId + ",未查询到所属公司");
        }
        String companyId = company.getString("companyId");
        if ("6608ed13c0dd42de93c790dbdf124234".equals(companyId)) {
            //广州汇创思拓数字科技有限公司（华南） 直接返回 何田田
            return "1cd4c769eabb4de98fed306de2a3bbbd";
        } else if ("4b10089775c040119e139087517aed88".equals(companyId)) {
            //上海汇创思拓数字科技有限公司 直接返回 吴婵
            return "183dce577efb49b386369473368cf251";
        } else {
            return getCompanyLeader(userId, companyId);
        }
    }

    // 获取公司审核人ID
    private String getCompanyLeader(String userId, String companyId) {
        String leaderId = "";
        String user = baseMapper.selectFinalLeaders(userId, companyId);
        if (userId.equals(user)) {
            return userId;
        }
        //查询部门
        List<SysDepart> departs = sysDepartService.queryUserDeparts(userId);
        if (!departs.isEmpty()) {
            String orgCode = departs.get(0).getOrgCode();
            JSONObject object = sysDepartService.queryAllParentIdByOrgCode(orgCode);
            JSONObject map = object.getJSONObject(orgCode).getJSONObject("parentMap");
            JSONObject leader = new JSONObject();
            //查询审核人员信息
            List<JSONObject> list = baseMapper.selectLeaders(companyId);
            for (JSONObject obj : list) {
                String departName = obj.getString("depart_name");
                if (map.toJSONString().contains(departName)) {
                    leader = obj;
                    break;
                }
            }
            if (leader.isEmpty()) {
                return null;
            }
            //第一审核人
            String firstId = leader.getString("first_id");
            //第二审核人
            String secondId = leader.getString("second_id");
            //终极审核人
            String finalId = leader.getString("final_id");
            if (userId.equals(finalId)) {
                return finalId;
            } else {
                if (Check.isNull(firstId)) {
                    //第一审核人为空，则直接取终极审核人
                    leaderId = finalId;
                } else {
                    if (Check.isNull(secondId)) {
                        //第二审核人为空
                        if (firstId.equals(userId)) {
                            leaderId = finalId;
                        } else {
                            leaderId = firstId;
                        }
                    } else {
                        if (firstId.equals(userId)) {
                            leaderId = secondId;
                        } else {
                            if (secondId.equals(userId)) {
                                leaderId = finalId;
                            } else {
                                leaderId = firstId;
                            }
                        }
                    }
                }
            }
        }
        return leaderId;
    }

    /**
     * 发送提示到审核人
     *
     * @return void
     * @throws
     * @Param type 1:成功;2：失败
     */
    private void sendMsg(String userId, String type, Object id, String msg) {
        try {
            StringBuilder text = new StringBuilder();
            if ("1".equals(type)) {
                text.append("报销提示:").append("<br/>")
                        .append("您好，现在有报销单（编号：").append(id)
                        .append("）待您审批，请您及时查看审批！");
            } else {
                text.append("报销提示").append("<br/>")
                        .append("您好，你的报销单（编号：").append(id).append("）审批未通过，");
                if (!Check.isNull(msg)) {
                    text.append("未通过原因：").append(msg).append("，");
                }
                text.append("请及时修改报销内容，以免耽误您的报销！");
            }
            sendMessageService.sendMessage(userId, text.toString());
            SysUser user = sysUserService.getById(userId);
            log.info("发送报销提醒，user:{}（{}）  msg:{}", user.getRealname(), userId, text.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 判断是否是福利费用，若是则将审核人返回
     * 考试费-郭艳玲(16eab477cd7a43538c1049d9678753e0)、
     * 团建费,伯乐奖,结婚礼金,生育礼金-李盼(4afbd7ef38804a558aca1329d4008d37)
     */
    private String checkWelfare(List<ReimburseProject> projects) {
        String type = "KS";
        String typ = "BL,TJ,JH,SY";
        for (ReimburseProject project : projects) {
            if (type.equals(project.getProject())) {
                return baseMapper.selectWelfareLeader("考试福利");
            } else if (typ.contains(project.getProject())) {
                return baseMapper.selectWelfareLeader("其他福利");
            }
        }
        return null;
    }


}
