package com.yida.data.form.apply.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.applyForm.*;
import com.yida.data.common.core.enums.EnableStatusEnum;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.form.apply.service.*;
import com.yida.data.form.apply.mapper.CoreApplyFormMapper;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.customForm.dto.apply.ApplyFormSelectPageDTO;
import com.yida.data.customForm.vo.apply.ApplyFormInfoVO;
import com.yida.data.customForm.vo.apply.ApplyFormSelectPageVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * 申请类型表单 Service
 *
 * @author ZYJ
 * @date 2023/11/14
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class CoreApplyFormServiceImpl extends ServiceImpl<CoreApplyFormMapper, CoreApplyForm>
        implements CoreApplyFormService {

    private final CoreApplyFormItemService coreApplyFormItemService;
    private final CoreApplyFormFillUserService coreApplyFormFillUserService;
    private final CoreApplyFormItemChildrenService coreApplyFormItemChildrenService;
    private final CoreApplyFormApprovalProcessService coreApplyFormApprovalProcessService;

    public static final String BASE_APPLY_TABLE_NAME = "core_apply_form_data_z_";

    @Override
    public IPage<ApplyFormSelectPageVO> listApplyFormPage(ApplyFormSelectPageDTO dto) {
        // TODO: 2023/11/14 此处暂时只有学校角色
        dto.setDeptId(FebsUtil.getDeptId());
        IPage<ApplyFormSelectPageVO> page = baseMapper.listApplyFormPage(dto.toPage(), dto);
        page.getRecords().forEach(form ->
                form.setSubmitNum(
                        coreApplyFormFillUserService.count(Wrappers.lambdaQuery(new CoreApplyFormFillUser())
                                .eq(CoreApplyFormFillUser::getApplyFormId, form.getId()))
                ));
        return page;
    }

    @Override
    public ApplyFormInfoVO getApplyFormInfo(Long id) {
        // 返回数据
        ApplyFormInfoVO vo = new ApplyFormInfoVO();
        CoreApplyForm applyForm = getById(id);
        if (Objects.nonNull(applyForm)) {
            BeanUtils.copyProperties(applyForm, vo);
            // 查询组件信息
            List<CoreApplyFormItem> itemList = coreApplyFormItemService.list(Wrappers.<CoreApplyFormItem>query().lambda()
                    .eq(CoreApplyFormItem::getFormId, id));
            itemList.forEach(item -> {
                // 查询组件选项信息
                List<CoreApplyFormItemChildren> childrenList =
                        coreApplyFormItemChildrenService.list(Wrappers.<CoreApplyFormItemChildren>query().lambda()
                                .eq(CoreApplyFormItemChildren::getFormItemId, item.getId()));
                item.setChildrenList(childrenList);
            });
            vo.setItemList(itemList);
        }
        return vo;
    }

    @Override
    public void deleteApplyForm(Long id) {
        CoreApplyForm applyForm = getById(id);
        // 判断是否有填报数据
        long count = coreApplyFormFillUserService.count(Wrappers.lambdaQuery(new CoreApplyFormFillUser())
                .eq(CoreApplyFormFillUser::getApplyFormId, id));
        if (count > 0) {
            throw new FebsException("当前表单已有填报数据，无法删除！");
        }
        // 删除申请表信息
        removeById(id);
        // 删除数据表信息
        String dropTableSql = "DROP TABLE IF EXISTS `" + applyForm.getTableName() + "`; \n";
        baseMapper.initSqlReturnVoid(dropTableSql);
        // 删除附表信息
        coreApplyFormItemService.remove(Wrappers.lambdaQuery(new CoreApplyFormItem())
                .eq(CoreApplyFormItem::getFormId, id));
        coreApplyFormItemChildrenService.remove(Wrappers.lambdaQuery(new CoreApplyFormItemChildren())
                .eq(CoreApplyFormItemChildren::getFormId, id));
    }

    @Override
    public Long saveApplyForm(CoreApplyForm applyForm) {
        String tableName = BASE_APPLY_TABLE_NAME + System.currentTimeMillis();
        // 编辑
        if (Objects.nonNull(applyForm.getId())) {
            // 判断是否有填报数据
            long count = coreApplyFormFillUserService.count(Wrappers.lambdaQuery(new CoreApplyFormFillUser())
                    .eq(CoreApplyFormFillUser::getApplyFormId, applyForm.getId()));
            if (count > 0) {
                throw new FebsException("当前表单已有填报数据，无法删除！");
            }
            // 删除附表信息
            coreApplyFormItemService.remove(Wrappers.lambdaQuery(new CoreApplyFormItem())
                    .eq(CoreApplyFormItem::getFormId, applyForm.getId()));
            coreApplyFormItemChildrenService.remove(Wrappers.lambdaQuery(new CoreApplyFormItemChildren())
                    .eq(CoreApplyFormItemChildren::getFormId, applyForm.getId()));
            // 删除数据表信息
            String dropTableSql = "DROP TABLE IF EXISTS `" + applyForm.getTableName() + "`; \n";
            baseMapper.initSqlReturnVoid(dropTableSql);
            applyForm.setTableName(tableName);
            updateById(applyForm);
        } else {
            // TODO: 2023/11/15 此处暂时只有学校角色
            applyForm.setSchoolId(FebsUtil.getDeptId());
            // 对应表名称
            applyForm.setTableName(tableName);
            save(applyForm);
        }
        // 保存审核流程节点信息
        if (CollUtil.isNotEmpty(applyForm.getProcessList())) {
            coreApplyFormApprovalProcessService.saveApplyFormApprovalProcess(applyForm.getId(), applyForm.getProcessList());
        }
        // 动态生成填报表
        StringBuilder stringBuilder = new StringBuilder();
        String createTableSql = "CREATE TABLE " + applyForm.getTableName() + "( \n" + "`id` bigint(20) NOT NULL AUTO_INCREMENT,\n";
        stringBuilder.append(createTableSql);
        // 处理组件数据
        applyForm.getItemList().forEach(item -> {
            String typeValue;
            if ("moreInput".equals(item.getItemType())) {
                typeValue = "text";
            } else {
                typeValue = "varchar(255)";
            }
            // 添加选项信息
            String sql = "`" + item.getItemFiledName() + "` " + typeValue + " DEFAULT NULL COMMENT '" + item.getItemTitle() + "'";
            stringBuilder.append(sql).append(",");
            // 保存选项信息
            item.setId(null);
            item.setFormId(applyForm.getId());
            coreApplyFormItemService.save(item);

            item.getChildrenList().forEach(itemChildren -> {
                itemChildren.setId(null);
                itemChildren.setFormItemId(item.getId());
                itemChildren.setFormId(applyForm.getId());
                coreApplyFormItemChildrenService.save(itemChildren);
            });
        });
        // 创建数据表sql
        String initSql = stringBuilder +
                "`user_id` bigint(20) DEFAULT NULL COMMENT '学生id',\n" +
                "`create_date` datetime DEFAULT NULL COMMENT '创建时间',\n" +
                "`examine_status` tinyint(1) DEFAULT '0' COMMENT '审核状态:默认0未审核，1已通过，2已拒绝，3审核中',\n" +
                "PRIMARY KEY (`id`)\n" +
                ") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8";

        baseMapper.initSqlReturnVoid(initSql);
        return applyForm.getId();
    }

    @Override
    public void updateEnableStatus(Long formId, Integer enableStatus) {
        if (EnableStatusEnum.ENABLE_STATUS.getStatus().equals(enableStatus)) {
            // 判断当前表单是否有流程信息
            long count = coreApplyFormApprovalProcessService.count(Wrappers.lambdaQuery(new CoreApplyFormApprovalProcess())
                    .eq(CoreApplyFormApprovalProcess::getApplyFormId, formId));
            if (count == 0) {
                throw new FebsException("当前表单暂无审核流程，请添加审核流程后再启用！");
            }
        }
        CoreApplyForm applyForm = new CoreApplyForm();
        applyForm.setId(formId);
        applyForm.setStatus(enableStatus);
        updateById(applyForm);
    }
}
