package ink.wgink.module.form.service.design.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.DependencyException;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.exceptions.RemoveException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.interfaces.menu.IMenuBaseService;
import ink.wgink.module.form.dao.design.IFormDao;
import ink.wgink.module.form.pojo.dtos.design.FormDTO;
import ink.wgink.module.form.pojo.pos.design.FormPO;
import ink.wgink.module.form.pojo.vos.design.FormVO;
import ink.wgink.module.form.service.design.IFormFieldService;
import ink.wgink.module.form.service.design.IFormService;
import ink.wgink.module.form.service.report.IFormReportService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.bos.menu.SaveMenuBO;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.map.HashMapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
public class FormServiceImpl extends DefaultBaseService implements IFormService {

    @Autowired
    private IFormDao formDao;
    @Autowired
    private IFormReportService formReportService;
    @Autowired
    private IFormFieldService formFieldService;
    @Autowired(required = false)
    private IMenuBaseService menuBaseService;

    @Override
    public void createDynamicForm(String createTableSQL) {
        formDao.createDynamicForm(createTableSQL);
    }

    @Override
    public void deleteTable(String tableName, boolean checkExist) {
        if (checkExist) {
            Integer count = formDao.countTable(tableName);
            if (count == 0) {
                return;
            }
        }
        StringBuffer sqlSB = new StringBuffer("DROP TABLE `").append(tableName).append("`;");
        deleteDynamicForm(sqlSB.toString());
    }

    @Override
    public void deleteDynamicForm(String deleteTableSQL) {
        formDao.deleteDynamicForm(deleteTableSQL);
    }

    @Override
    public void updateTableField(String tableName, String oldField, String newField, String newFieldType) {
        StringBuffer sqlSB = new StringBuffer("ALTER TABLE");
        sqlSB.append(" `").append(tableName).append("`");
        sqlSB.append(" CHANGE");
        sqlSB.append(" `").append(oldField).append("`");
        sqlSB.append(" `").append(newField).append("`");
        sqlSB.append(newFieldType).append(";");
        updateDynamicFormField(sqlSB.toString());
    }

    @Override
    public void updateDynamicFormField(String alterFieldSQL) {
        formDao.updateDynamicFormField(alterFieldSQL);
    }

    @Override
    public void deleteTableField(String tableName, String field) {
        StringBuffer sqlSB = new StringBuffer("ALTER TABLE");
        sqlSB.append(" `").append(tableName).append("`");
        sqlSB.append(" DROP");
        sqlSB.append(" `").append(field).append("`");
        deleteDynamicFormField(sqlSB.toString());
    }

    @Override
    public void deleteDynamicFormField(String alterFieldSQL) {
        formDao.deleteDynamicFormField(alterFieldSQL);
    }

    @Override
    public Integer countDynamicTable(String tableName) {
        return formDao.countTable(tableName);
    }

    @Override
    public void save(FormVO formVO) {
        saveReturnId(formVO);
    }

    @Override
    public String saveReturnId(FormVO formVO) {
        FormPO formPO = getPOByCodeAndVersion(formVO.getFormCode(), formVO.getFormVersion());
        if (formPO != null) {
            throw new ParamsException("编码存在，请稍后重试");
        }
        String formId = UUIDUtil.getUUID();
        Map<String, Object> params = HashMapUtil.beanToMap(formVO);
        params.put("formId", formId);
        setSaveInfo(params);
        formDao.save(params);
        return formId;
    }

    @Override
    public void delete(List<String> ids) {
        List<FormDTO> formDTOs = listByIds(ids);
        deleteTable(formDTOs);
        // 删除列
        formFieldService.deleteByFormIds(ids);
        Map<String, Object> params = getHashMap(2);
        params.put("formIds", ids);
        formDao.delete(params);
    }

    @Override
    public void remove(List<String> ids) {
        // 逻辑删除不删除表
        Map<String, Object> params = getHashMap(2);
        params.put("formIds", ids);
        formDao.remove(params);
    }

    private void deleteTable(List<FormDTO> formDTOs) {
        for (FormDTO formDTO : formDTOs) {
            Integer tableCount = countDynamicTable(formDTO.getFormTableName());
            if (tableCount == 0) {
                // 表不存在
                continue;
            }
            Integer dataCount = formReportService.count(formDTO.getFormTableName());
            if (dataCount > 0) {
                throw new RemoveException(formDTO.getFormTableName() + "表中存在数据，不能删除");
            }
            deleteTable(formDTO.getFormTableName(), false);
        }
    }

    @Override
    public void update(String formId, FormVO formVO) {
        Map<String, Object> params = HashMapUtil.beanToMap(formVO);
        params.put("formId", formId);
        setUpdateInfo(params);
        formDao.update(params);
    }

    @Override
    public void updateStatus(String formId, String formStatus) {
        Map<String, Object> params = getHashMap(8);
        params.put("formId", formId);
        params.put("formStatus", formStatus);
        setUpdateInfo(params);
        formDao.update(params);
    }

    @Override
    public void updateSavePageCode(String formId, String savePageCode) {
        Map<String, Object> params = getHashMap(4);
        params.put("formId", formId);
        params.put("savePageCode", savePageCode);
        setUpdateInfo(params);
        formDao.update(params);
    }

    @Override
    public void updateUpdatePageCode(String formId, String updatePageCode) {
        Map<String, Object> params = getHashMap(4);
        params.put("formId", formId);
        params.put("updatePageCode", updatePageCode);
        setUpdateInfo(params);
        formDao.update(params);
    }

    @Override
    public void updateShowPageCode(String formId, String showPageCode) {
        Map<String, Object> params = getHashMap(4);
        params.put("formId", formId);
        params.put("showPageCode", showPageCode);
        setUpdateInfo(params);
        formDao.update(params);
    }

    @Override
    public void updatePrintPageCode(String formId, String printPageCode) {
        Map<String, Object> params = getHashMap(4);
        params.put("formId", formId);
        params.put("printPageCode", printPageCode);
        setUpdateInfo(params);
        formDao.update(params);
    }

    @Override
    public void updateAppSavePageCode(String formId, String appSavePageCode) {
        Map<String, Object> params = getHashMap(4);
        params.put("formId", formId);
        params.put("appSavePageCode", appSavePageCode);
        setUpdateInfo(params);
        formDao.update(params);
    }

    @Override
    public void updateAppUpdatePageCode(String formId, String appUpdatePageCode) {
        Map<String, Object> params = getHashMap(4);
        params.put("formId", formId);
        params.put("appUpdatePageCode", appUpdatePageCode);
        setUpdateInfo(params);
        formDao.update(params);
    }

    @Override
    public void updateAppShowPageCode(String formId, String appShowPageCode) {
        Map<String, Object> params = getHashMap(4);
        params.put("formId", formId);
        params.put("appShowPageCode", appShowPageCode);
        setUpdateInfo(params);
        formDao.update(params);
    }

    @Override
    public void updateToMenu(String formId, String menuParentId) {
        if (menuBaseService == null) {
            throw new DependencyException("菜单业务未依赖");
        }
        FormPO formPO = getPO(formId);
        if (formPO == null) {
            throw new SearchException("表单不存在");
        }
        String menuUrl = String.format("/route/form-report/list/code/%s/version/%d/true", formPO.getFormCode(), formPO.getFormVersion());
        SaveMenuBO saveMenuBO = new SaveMenuBO();
        saveMenuBO.setMenuParentId(menuParentId);
        saveMenuBO.setMenuName(formPO.getFormName());
        saveMenuBO.setMenuUrl(menuUrl);
        saveMenuBO.setMenuStatus(0);
        saveMenuBO.setMenuOrder("9999");
        menuBaseService.saveAndReturnId(saveMenuBO);
    }

    @Override
    public FormDTO get(Map<String, Object> params) {
        params = params == null ? getHashMap(0) : params;
        return formDao.get(params);
    }

    @Override
    public FormDTO get(String formId) {
        Map<String, Object> params = getHashMap(2);
        params.put("formId", formId);
        return get(params);
    }

    @Override
    public FormPO getPO(Map<String, Object> params) {
        params = params == null ? getHashMap(0) : params;
        return formDao.getPO(params);
    }

    @Override
    public FormPO getPO(String formId) {
        Map<String, Object> params = getHashMap(2);
        params.put("formId", formId);
        return getPO(params);
    }

    @Override
    public FormPO getPOByCode(String formCode) {
        Map<String, Object> params = getHashMap(2);
        params.put("formCode", formCode);
        return getPO(params);
    }

    @Override
    public FormPO getPOByCodeAndVersion(String formCode, Integer formVersion) {
        Map<String, Object> params = getHashMap(4);
        params.put("formCode", formCode);
        params.put("formVersion", formVersion);
        return getPO(params);
    }

    @Override
    public String getSavePageCodeByCodeAndVersion(String formCode, Integer formVersion) {
        Map<String, Object> params = getHashMap(4);
        params.put("formCode", formCode);
        params.put("formVersion", formVersion);
        return formDao.getSavePageCodeByCodeAndVersion(params);
    }

    @Override
    public String getUpdatePageCodeByCodeAndVersion(String formCode, Integer formVersion) {
        Map<String, Object> params = getHashMap(4);
        params.put("formCode", formCode);
        params.put("formVersion", formVersion);
        return formDao.getUpdatePageCodeByCodeAndVersion(params);
    }

    @Override
    public String getShowPageCodeByCodeAndVersion(String formCode, Integer formVersion) {
        Map<String, Object> params = getHashMap(4);
        params.put("formCode", formCode);
        params.put("formVersion", formVersion);
        return formDao.getShowPageCodeByCodeAndVersion(params);
    }

    @Override
    public String getPrintPageCodeByCodeAndVersion(String formCode, Integer formVersion) {
        Map<String, Object> params = getHashMap(4);
        params.put("formCode", formCode);
        params.put("formVersion", formVersion);
        return formDao.getPrintPageCodeByCodeAndVersion(params);
    }

    @Override
    public String getAppSavePageCodeByCodeAndVersion(String formCode, Integer formVersion) {
        Map<String, Object> params = getHashMap(4);
        params.put("formCode", formCode);
        params.put("formVersion", formVersion);
        return formDao.getAppSavePageCodeByCodeAndVersion(params);
    }

    @Override
    public String getAppUpdatePageCodeByCodeAndVersion(String formCode, Integer formVersion) {
        Map<String, Object> params = getHashMap(4);
        params.put("formCode", formCode);
        params.put("formVersion", formVersion);
        return formDao.getAppUpdatePageCodeByCodeAndVersion(params);
    }

    @Override
    public String getAppShowPageCodeByCodeAndVersion(String formCode, Integer formVersion) {
        Map<String, Object> params = getHashMap(4);
        params.put("formCode", formCode);
        params.put("formVersion", formVersion);
        return formDao.getAppShowPageCodeByCodeAndVersion(params);
    }

    @Override
    public FormDTO getFormSourceData(String formId) {
        FormPO formPO = getPO(formId);
        FormDTO formDTO = new FormDTO();
        formDTO.setFormSourceData(formPO.getFormSourceData());
        return formDTO;
    }

    @Override
    public Integer getLatestVersionByCode(String formCode) {
        return formDao.getLatestVersionByCode(formCode);
    }

    @Override
    public List<FormDTO> list(Map<String, Object> params) {
        params = params == null ? getHashMap(2) : params;
        return formDao.list(params);
    }

    @Override
    public List<FormDTO> listLatest(Map<String, Object> params) {
        params = params == null ? getHashMap(2) : params;
        params.put("latestVersion", "true");
        return list(params);
    }

    @Override
    public List<FormDTO> listByIds(List<String> formIds) {
        Map<String, Object> params = getHashMap(2);
        params.put("formIds", formIds);
        return list(params);
    }

    @Override
    public List<FormPO> listPO(Map<String, Object> params) {
        params = params == null ? getHashMap(2) : params;
        return formDao.listPO(params);
    }

    @Override
    public List<FormPO> listPOLatest(Map<String, Object> params) {
        params = params == null ? getHashMap(2) : params;
        params.put("latestVersion", ISystemConstant.IS_TRUE);
        return listPO(params);
    }

    @Override
    public SuccessResultList<List<FormDTO>> listPage(ListPage page) {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<FormDTO> dataDTOs = list(page.getParams());
        PageInfo<FormDTO> pageInfo = new PageInfo<>(dataDTOs);
        return new SuccessResultList<>(dataDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public SuccessResultList<List<FormDTO>> listPageLatest(ListPage page) {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<FormDTO> dataDTOs = listLatest(page.getParams());
        PageInfo<FormDTO> pageInfo = new PageInfo<>(dataDTOs);
        return new SuccessResultList<>(dataDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public SuccessResultList<List<FormDTO>> listPageHistoryByFormId(String formId, ListPage page) {
        FormPO latestFormPO = getPO(formId);
        if (latestFormPO == null) {
            throw new SearchException("表单不存在");
        }
        page.getParams().put("isHistory", ISystemConstant.IS_TRUE);
        page.getParams().put("latestFormId", formId);
        page.getParams().put("formCode", latestFormPO.getFormCode());
        return listPage(page);
    }
}
