package com.engine.organization.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.api.browser.bean.BrowserBean;
import com.api.browser.bean.SearchConditionGroup;
import com.api.browser.bean.SearchConditionItem;
import com.api.browser.bean.SearchConditionOption;
import com.cloudstore.eccom.result.WeaResultMsg;
import com.engine.core.impl.Service;
import com.engine.organization.component.OrganizationWeaTable;
import com.engine.organization.entity.DeleteParam;
import com.engine.organization.entity.browser.po.CustomBrowserBean;
import com.engine.organization.entity.department.po.DepartmentPO;
import com.engine.organization.entity.job.po.JobPO;
import com.engine.organization.entity.staff.bo.StaffBO;
import com.engine.organization.entity.staff.param.StaffSearchParam;
import com.engine.organization.entity.staff.po.StaffPO;
import com.engine.organization.entity.staff.po.StaffPlanPO;
import com.engine.organization.entity.staff.po.StaffsPO;
import com.engine.organization.entity.staff.vo.StaffTableVO;
import com.engine.organization.mapper.department.DepartmentMapper;
import com.engine.organization.mapper.job.JobMapper;
import com.engine.organization.mapper.staff.StaffMapper;
import com.engine.organization.mapper.staff.StaffPlanMapper;
import com.engine.organization.mapper.staff.StaffsMapper;
import com.engine.organization.service.StaffService;
import com.engine.organization.util.*;
import com.engine.organization.util.browser.OrganizationBrowserUtil;
import com.engine.organization.util.db.DBType;
import com.engine.organization.util.db.MapperProxyFactory;
import com.engine.organization.util.excel.ExcelUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;
import weaver.general.GCONST;
import weaver.general.StringUtil;
import weaver.general.Util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * @description:
 * @author:dxfeng
 * @createTime: 2022/05/25
 * @version: 1.0
 */
public class StaffServiceImpl extends Service implements StaffService {

    private static final String RIGHT_NAME = "Staff:All";

    private StaffMapper getStaffMapper() {
        return MapperProxyFactory.getProxy(StaffMapper.class);
    }

    private StaffPlanMapper getStaffPlanMapper() {
        return MapperProxyFactory.getProxy(StaffPlanMapper.class);
    }

    private JobMapper getJobMapper() {
        return MapperProxyFactory.getProxy(JobMapper.class);
    }

    private DepartmentMapper getDepartmentMapper() {
        return MapperProxyFactory.getProxy(DepartmentMapper.class);
    }

    // 判断编制导入模板是否存在，不存在则创建该文件
    static {
        try {
            String outPutPath = GCONST.getRootPath() + File.separator + "hrm" + File.separator + "import" + File.separator + "template" + File.separator + "staff.xls";
            File excelPathFile = new File(outPutPath);
            if (!excelPathFile.exists()) {
                String columns = "方案编号,方案名称,分部,部门,岗位,编制数";
                String[] split = columns.split(",");
                List<Object> columnList = new ArrayList<>(Arrays.asList(split));
                // 创建导入模板
                List<List<Object>> excelSheetData = new ArrayList<>();
                excelSheetData.add(columnList);
                XSSFWorkbook sheets = ExcelUtil.genWorkbookV2(excelSheetData, "staff");
                File excelFile = new File(outPutPath);
                if (!excelFile.exists()) {
                    String substring = outPutPath.substring(0, outPutPath.lastIndexOf(File.separator));
                    File file = new File(substring);
                    if (file.mkdirs()) {
                        boolean newFile = excelPathFile.createNewFile();
                        if (!newFile) {
                            throw new IOException(outPutPath + "文件创建失败");
                        }
                    }
                }
                FileOutputStream out = new FileOutputStream(excelPathFile);
                sheets.write(out);
                out.flush();
            }
        } catch (IOException e) {
            new BaseBean().writeLog(e);
            throw new RuntimeException(e);
        }
    }


    @Override
    public Map<String, Object> listPage(StaffSearchParam params) {
        Map<String, Object> resultMap = new HashMap<>();
        boolean hasRight = HasRightUtil.hasRight(user, RIGHT_NAME, true);
        resultMap.put("hasRight", hasRight);
        if (!hasRight) {
            return resultMap;
        }
        // 刷新引用状态
        RefreshIsUsedUtil.RefreshStaff("jcl_org_staff");
        OrganizationWeaTable<StaffTableVO> table = new OrganizationWeaTable<>(user, StaffTableVO.class);
        String sqlWhere = buildSqlWhere(params);
        table.setSqlwhere(sqlWhere);
        WeaResultMsg result = new WeaResultMsg(false);
        result.putAll(table.makeDataResult());
        result.success();
        resultMap.putAll(result.getResultMap());
        return resultMap;
    }

    @Override
    public int saveStaff(StaffSearchParam param) {
        HasRightUtil.hasRight(user, RIGHT_NAME, false);
        StaffPO staffPO = StaffBO.convertParamToPO(param, (long) user.getUID());
        OrganizationAssert.isFalse(staffPO.getStaffNum() < 0, "编制数不可小于0，请更正");

        checkRequired(staffPO);

        int ignoreNull = getStaffMapper().insertIgnoreNull(staffPO);
        // 同步组织架构图编制信息
        //new StaffTriggerRunnable(staffPO).run();
        return ignoreNull;
    }

    @Override
    public int updateStaff(StaffSearchParam param) {
        HasRightUtil.hasRight(user, RIGHT_NAME, false);
        StaffPO staffByID = getStaffMapper().getStaffByID(param.getId());
        StaffPO staffPO = StaffBO.convertParamToPO(param, (long) user.getUID());
        staffPO.setPermanentNum(staffByID.getPermanentNum());
        staffPO.setFreezeNum(staffByID.getFreezeNum());

        checkRequired(staffPO);

        Integer changeNum = param.getChangeNum();
        if (null == changeNum) {
            // 插入明细表数据
            StaffsPO staffsPO = StaffsPO.builder().staffId(staffPO.getId()).businessType(1).changeNum(staffPO.getStaffNum() - staffByID.getStaffNum()).businessSource(1).build();
            MapperProxyFactory.getProxy(StaffsMapper.class).insertIgnoreNull(staffsPO);

        } else {
            // 插入明细表数据
            StaffsPO staffsPO = StaffsPO.builder().staffId(staffPO.getId()).businessType(2).changeNum(changeNum).businessSource(1).description(param.getChangeDescription()).build();
            MapperProxyFactory.getProxy(StaffsMapper.class).insertIgnoreNull(staffsPO);
            // 更新编制表
            staffPO.setStaffNum(staffPO.getStaffNum() + changeNum);
        }
        OrganizationAssert.isFalse(staffPO.getStaffNum() < 0, "调整后编制数小于0，请更正");
        StaffBO.buildStaffDesc(staffPO);
        // 更新主表
        int updateStaff = getStaffMapper().updateStaff(staffPO);
        // 同步组织架构图编制信息
        //new StaffTriggerRunnable(staffPO).run();
        return updateStaff;
    }


    @Override
    public int deleteByIds(Collection<Long> ids) {
        HasRightUtil.hasRight(user, RIGHT_NAME, false);
        OrganizationAssert.notEmpty(ids, "请选择要删除的数据");
        List<StaffPO> staffsByIds = getStaffMapper().getStaffsByIds(ids);
        int deleteByIds = getStaffMapper().deleteByIds(ids);
        //for (StaffPO staffsById : staffsByIds) {
        //    new StaffTriggerRunnable(staffsById).run();
        //}
        return deleteByIds;
    }

    @Override
    public Map<String, Object> getSearchCondition(Map<String, Object> params) {
        Map<String, Object> apiDatas = new HashMap<>();
        List<SearchConditionGroup> addGroups = new ArrayList<>();
        List<SearchConditionItem> conditionItems = new ArrayList<>();


        // 分部
        SearchConditionItem compIdItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "分部", "164", "ecCompany", "");
        // 部门
        SearchConditionItem deptIdItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "部门", "4", "ecDepartment", "");
        // 岗位
        SearchConditionItem jobIdItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "岗位", "666", "jobId", "");
        // 编制数
        SearchConditionItem staffNumItem = OrganizationFormItemUtil.inputNumberItem(user, 2, 16, 2, "编制数", "staffNum");
        // 在编
        SearchConditionItem permanentNumItem = OrganizationFormItemUtil.inputNumberItem(user, 2, 16, 2, "在编", "permanentNum");
        // 冻结数
        SearchConditionItem freezeNumItem = OrganizationFormItemUtil.inputNumberItem(user, 2, 16, 2, "冻结数", "freezeNum");
        // 缺编状态
        List<SearchConditionOption> selectOptions = new ArrayList<>();
        SearchConditionOption lackOption = new SearchConditionOption("1", "缺编");
        SearchConditionOption fullOption = new SearchConditionOption("2", "满员");
        SearchConditionOption overOption = new SearchConditionOption("3", "超编");
        selectOptions.add(lackOption);
        selectOptions.add(fullOption);
        selectOptions.add(overOption);
        SearchConditionItem lackStatusItem = OrganizationFormItemUtil.selectItem(user, selectOptions, 2, 16, 6, false, "缺编状态", "lackStatus");
        // 编制描述
        SearchConditionItem staffDescItem = OrganizationFormItemUtil.inputItem(user, 2, 16, 2, 50, "编制描述", "staffDesc");
        // 说明
        SearchConditionItem descriptionItem = OrganizationFormItemUtil.inputItem(user, 2, 16, 2, 50, "说明", "description");

        //conditionItems.add(planIdItem);
        conditionItems.add(compIdItem);
        conditionItems.add(deptIdItem);
        conditionItems.add(jobIdItem);
        conditionItems.add(staffNumItem);
        conditionItems.add(permanentNumItem);
        conditionItems.add(freezeNumItem);
        conditionItems.add(lackStatusItem);
        conditionItems.add(staffDescItem);
        conditionItems.add(descriptionItem);

        addGroups.add(new SearchConditionGroup("高级搜索条件", true, conditionItems));
        apiDatas.put("conditions", addGroups);
        return apiDatas;
    }

    @Override
    public Map<String, Object> getForm(Map<String, Object> params) {
        HasRightUtil.hasRight(user, RIGHT_NAME, false);
        Map<String, Object> apiDatas = new HashMap<>();
        List<SearchConditionItem> selectItems = new ArrayList<>();
        List<SearchConditionGroup> addGroups = new ArrayList<>();
        // 方案
        SearchConditionItem planIdItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 3, false, "方案", "161", "planId", "staffPlanBrowser");
        planIdItem.setRules("required|string");
        // 分部
        SearchConditionItem ecCompanyItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "分部", "164", "ecCompany", "compBrowser");
        // 部门
        SearchConditionItem ecDepartmentItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "部门", "4", "ecDepartment", "deptBrowser");
        // 岗位
        SearchConditionItem jobIdItem = OrganizationFormItemUtil.browserItem(user, 2, 16, 2, false, "岗位", "666", "jobId", "");
        BrowserBean browserBean = jobIdItem.getBrowserConditionParam();
        String s = JSONObject.toJSONString(browserBean);
        CustomBrowserBean customBrowserBean = JSONObject.parseObject(s, CustomBrowserBean.class);
        customBrowserBean.setHasLeftTree(true);
        customBrowserBean.setLeftToSearchKey("treeKey");
        jobIdItem.setBrowserConditionParam(customBrowserBean);

        // 编制数
        SearchConditionItem staffNumItem = OrganizationFormItemUtil.inputNumberItem(user, 2, 16, 3, "编制数", "staffNum");
        staffNumItem.setRules("required");
        staffNumItem.setMin("0");
        // 控制策略
        List<SearchConditionOption> selectOptions = new ArrayList<>();
        SearchConditionOption option1 = new SearchConditionOption("1", "弱控");
        SearchConditionOption option2 = new SearchConditionOption("2", "强控");
        SearchConditionOption option3 = new SearchConditionOption("3", "不控");
        selectOptions.add(option1);
        selectOptions.add(option2);
        selectOptions.add(option3);
        SearchConditionItem controlPolicyItem = OrganizationFormItemUtil.selectItem(user, selectOptions, 2, 16, 6, false, "控制策略", "controlPolicy");
        controlPolicyItem.setViewAttr(3);
        controlPolicyItem.setValue("1");
        controlPolicyItem.setRules("required|string");
        SearchConditionItem descriptionItem = OrganizationFormItemUtil.textareaItem(user, 2, 16, true, 2, 200, "描述说明", "description");


        // 编辑状态下赋值操作
        String id = Util.null2String(params.get("id"));
        if (!StringUtil.isEmpty(id)) {
            StaffPO staffPO = getStaffMapper().getStaffByID(Integer.parseInt(id));
            OrganizationAssert.notNull(staffPO, "选择的数据不存在，或数据已删除");

            BrowserBean planIdItemBean = planIdItem.getBrowserConditionParam();
            List<Map<String, Object>> planIdMaps = getStaffPlanMapper().listPlansByIds(DeleteParam.builder().ids(staffPO.getPlanId().toString()).build().getIds());
            planIdItemBean.setReplaceDatas(planIdMaps);
            planIdItem.setBrowserConditionParam(planIdItemBean);

            if (null != staffPO.getEcCompany()) {
                OrganizationBrowserUtil.assignBrowser(user, staffPO.getEcCompany().toString(), 164, ecCompanyItem);
            }

            if (null != staffPO.getEcDepartment()) {
                OrganizationBrowserUtil.assignBrowser(user, staffPO.getEcDepartment().toString(), 4, ecDepartmentItem);
            }

            if (null != staffPO.getJobId()) {
                BrowserBean jobIdItemBean = jobIdItem.getBrowserConditionParam();
                List<Map<String, Object>> jobIdMaps = getJobMapper().listJobsByIds(DeleteParam.builder().ids(staffPO.getJobId().toString()).build().getIds());
                jobIdItemBean.setReplaceDatas(jobIdMaps);
                jobIdItem.setBrowserConditionParam(jobIdItemBean);
            }

            staffNumItem.setValue(staffPO.getStaffNum());
            controlPolicyItem.setValue(Util.null2String(staffPO.getControlPolicy()));
            descriptionItem.setValue(staffPO.getDescription());
        }
        selectItems.add(planIdItem);
        selectItems.add(ecCompanyItem);
        selectItems.add(ecDepartmentItem);
        selectItems.add(jobIdItem);
        selectItems.add(staffNumItem);
        selectItems.add(controlPolicyItem);
        selectItems.add(descriptionItem);
        String operateType = (String) params.get("operateType");
        if ("2".equals(operateType)) {
            selectItems.forEach(item -> {
                item.setViewAttr(1);
                item.setRules(null);
            });
            SearchConditionItem changeNumItem = OrganizationFormItemUtil.inputNumberItem(user, 2, 16, 3, "调整数量", "changeNum");
            changeNumItem.setHelpfulTip("提示:正数为增加，负数为减少编制数");
            staffNumItem.setRules("required");
            selectItems.add(changeNumItem);
            SearchConditionItem changeDescriptionItem = OrganizationFormItemUtil.textareaItem(user, 2, 16, false, 2, 50, "变更说明", "changeDescription");
            selectItems.add(changeDescriptionItem);

        }

        addGroups.add(new SearchConditionGroup("基本信息", true, selectItems));
        apiDatas.put("condition", addGroups);
        return apiDatas;
    }

    @Override
    public Map<String, Object> getHasRight() {
        Map<String, List<MenuBtn>> datas = MenuBtn.getCommonBtnDatas();
        datas.get("topMenu").add(MenuBtn.builder().isBatch("1").isTop("1").menuFun("import").menuIcon("icon-coms-leading-in").menuName("批量导入").type("BTN_BatchImport").build());
        datas.get("rightMenu").add(MenuBtn.builder().isBatch("1").isTop("0").menuFun("import").menuIcon("icon-coms-leading-in").menuName("批量导入").type("BTN_BatchImport").build());
        Map<String, Object> map = new HashMap<>(datas);
        List<SearchConditionGroup> addGroups = new ArrayList<>();
        List<SearchConditionItem> selectItems = new ArrayList<>();
        // 方案
        SearchConditionItem planIdItem = OrganizationFormItemUtil.browserItem(user, 4, 3, 2, false, "编制方案", "161", "planId", "staffPlanBrowser");
        planIdItem.setRules("required|string");
        planIdItem.setHelpfulTip("请选择编制方案后查看数据");
        planIdItem.setLabelcol(2);

        selectItems.add(planIdItem);
        addGroups.add(new SearchConditionGroup("基本信息", true, selectItems));
        map.put("condition", addGroups);
        return map;
    }

    /**
     * 查询条件
     *
     * @param param
     * @return
     */
    private String buildSqlWhere(StaffSearchParam param) {
        DBType dbType = DBType.get(new RecordSet().getDBType());
        String sqlWhere = " where t.delete_type ='0' ";

        Long planId = param.getPlanId();
        if (null != planId) {
            sqlWhere += " AND t.plan_id = '" + planId + "'";
        } else {
            sqlWhere = " where 1 = 2 ";
        }
        Integer compId = param.getCompId();
        if (null != compId) {
            sqlWhere += " AND t.comp_id = '" + compId + "'";
        }
        Integer deptId = param.getDeptId();
        if (null != deptId) {
            sqlWhere += " AND t.dept_id = '" + deptId + "'";
        }
        Integer ecCompany = param.getEcCompany();
        if (null != ecCompany) {
            sqlWhere += " AND t.ec_company = '" + ecCompany + "'";
        }
        Integer ecDepartment = param.getEcDepartment();
        if (null != ecDepartment) {
            sqlWhere += " AND t.ec_department = '" + ecDepartment + "'";
        }
        Long jobId = param.getJobId();
        if (null != jobId) {
            sqlWhere += " AND t.job_id = '" + jobId + "'";
        }
        Integer staffNum = param.getStaffNum();
        if (null != staffNum) {
            sqlWhere += " AND t.staff_num = '" + staffNum + "'";
        }
        Integer controlPolicy = param.getControlPolicy();
        if (null != controlPolicy) {
            sqlWhere += " AND t.control_policy = '" + controlPolicy + "'";
        }
        Integer permanentNum = param.getPermanentNum();
        if (null != permanentNum) {
            sqlWhere += " AND t.permanent_num = '" + permanentNum + "'";
        }
        Integer freezeNum = param.getFreezeNum();
        if (null != freezeNum) {
            sqlWhere += " AND t.freeze_num = '" + freezeNum + "'";
        }
        Integer lackStatus = param.getLackStatus();
        if (null != lackStatus) {
            sqlWhere += " AND t.lack_status = '" + lackStatus + "'";
        }
        String staffDesc = param.getStaffDesc();
        if (StringUtils.isNotBlank(staffDesc)) {
            sqlWhere += " AND t.staff_desc " + dbType.like(staffDesc);
        }
        String description = param.getDescription();
        if (StringUtils.isNotBlank(description)) {
            sqlWhere += " AND t.description " + dbType.like(description);
        }
        String staffName = param.getStaffName();
        if (StringUtils.isNotBlank(staffName)) {
            sqlWhere += " AND t.plan_id in ( select id from jcl_org_staffplan where plan_name " + dbType.like(staffName) + ") ";
        }

        return sqlWhere;
    }

    /**
     * 校验必填字段
     *
     * @param staffPO
     */
    private void checkRequired(StaffPO staffPO) {
        // 根据维度、校验必填字段
        StaffPlanPO staffPlanByID = getStaffPlanMapper().getStaffPlanByID(staffPO.getPlanId());
        switch (staffPlanByID.getControlDimension()) {
            case "1":// 分部
                OrganizationAssert.notNull(staffPO.getEcCompany(), "编制维度选择分部时，分部必填！");
                staffPO.setCompId(staffPO.getEcCompany());
                break;
            case "2":// 部门
                OrganizationAssert.notNull(staffPO.getEcDepartment(), "编制维度选择部门时，部门必填！");
                DepartmentPO jclDepartmentId = getDepartmentMapper().getDeptById(staffPO.getEcDepartment());
                if (null != jclDepartmentId) {
                    staffPO.setDeptId(jclDepartmentId.getId());
                    staffPO.setCompId(jclDepartmentId.getSubCompanyId1());
                    staffPO.setEcCompany(jclDepartmentId.getSubCompanyId1());
                }
                break;
            case "3": // 岗位
                OrganizationAssert.notNull(staffPO.getJobId(), "编制维度选择岗位时，岗位必填！");
                JobPO jobById = getJobMapper().getJobById(staffPO.getJobId());
                if (null != jobById) {
                    staffPO.setDeptId(jobById.getEcDepartment());
                    staffPO.setEcDepartment(jobById.getEcDepartment());
                    staffPO.setCompId(jobById.getEcCompany());
                    staffPO.setEcCompany(jobById.getEcCompany());
                }
                break;
            default:
                break;
        }
    }

}
