package cn.com.smart.form.list;

import cn.com.smart.ISmart;
import cn.com.smart.bean.SmartResponse;
import cn.com.smart.form.enums.FormListDataScopeType;
import cn.com.smart.form.enums.FormType;
import cn.com.smart.form.enums.SearchExpType;
import cn.com.smart.form.list.bean.AbstractListFieldProp;
import cn.com.smart.form.list.bean.CommonListFieldProp;
import cn.com.smart.form.list.bean.FormListProp;
import cn.com.smart.form.list.bean.TableFieldClassify;
import cn.com.smart.web.service.IOPService;
import com.mixsmart.utils.CollectionUtils;
import com.mixsmart.utils.LoggerUtils;
import com.mixsmart.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 乌草坡 2019-09-02
 * @since 1.0
 */
public class GenerateSqlByListFieldDelegate {

    private static final Logger logger = LoggerFactory.getLogger(GenerateSqlByListFieldDelegate.class);

    private FormListProp formListProp;

    private IOPService opServ;

    private List<TableFieldClassify> tableFieldClassifies;

    private String sql;

    private String sqlName;

    public GenerateSqlByListFieldDelegate(FormListProp formListProp, IOPService opServ) {
        this.formListProp = formListProp;
        this.opServ = opServ;
    }

    public String getSqlName() {
        if(null != sqlName) {
            return sqlName;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        return "AU_FL"+simpleDateFormat.format(new Date()) + StringUtils.randomNum(4);
    }

    public String createSQL() {
        if(null != this.sql) {
            return this.sql;
        }
        List<TableFieldClassify> classifies = getTableFields(getFieldIds());
        if(CollectionUtils.isEmpty(classifies)) {
            return null;
        }
        StringBuilder queryFieldBuilder = new StringBuilder();
        StringBuilder formBuilder = new StringBuilder();
        StringBuilder whereBuilder = new StringBuilder();
        StringBuilder relateCndBuilder = new StringBuilder();
        int index = 1;
        int aliasIndex = 1;
        for(TableFieldClassify classify : classifies) {
            formBuilder.append(classify.getTableName()).append(" ").append(classify.getTableAlias()).append(",");
            if(index > 1) {
                relateCndBuilder.append(classifies.get(0).getTableAlias()).append(".").append("form_data_id=")
                        .append(classify.getTableAlias()).append(".").append("form_data_id").append(" and ");
            }
            index++;
        }
        for(AbstractListFieldProp fieldProp : formListProp.getListFieldProps()) {
            TableFieldClassify.FieldName fieldName = getFieldName(classifies, fieldProp.getFieldId());
            queryFieldBuilder.append(fieldName.getTableAlias()).append(".").append(fieldName.getFieldName())
                    .append(" as ").append("field").append(aliasIndex).append(",");
            //判断字段是否支持查询或排序
            if(null != fieldProp) {
                fieldProp.setFieldName(fieldName.getFieldName());
            }
            if(null != fieldProp && fieldProp.getSupportSearch()) {
                SearchExpType expType = null;
                if(fieldProp instanceof CommonListFieldProp) {
                    expType = SearchExpType.LIKE;
                } else {
                    expType = SearchExpType.EQ;
                }
                whereBuilder.append("[ and ");
                whereBuilder.append(fieldName.getTableAlias()).append(".").append(fieldName.getFieldName());
                String exp = expType.getExp();
                if(expType == SearchExpType.LEFT_LIKE || expType == SearchExpType.LIKE || expType == SearchExpType.RIGHT_LIKE) {
                    exp = exp.replace(":value", ":"+fieldName.getFieldName());
                } else {
                    exp = exp + ":"+fieldName.getFieldName();
                }
                whereBuilder.append(" ").append(exp).append("]");
            }
            aliasIndex++;
        }
        //}
        StringBuilder sqlBuilder = new StringBuilder();
        queryFieldBuilder.append(" f.form_id,f.form_data_id ");

        //获取表单类型
        FormType formType = FormType.getObj(formListProp.getFormType());
        formType = (null == formType)?FormType.NORMAL_FORM:formType;
        if(FormType.FLOW_FORM == formType) {
            formBuilder.append("t_flow_form f ");
            queryFieldBuilder.append(",f.process_id,f.order_id,f.process_name ");
        } else {
            formBuilder.append("t_form_instance f");
        }
        sqlBuilder.append("select t1.form_data_id as id,").append(queryFieldBuilder);
        sqlBuilder.append(" from ").append(formBuilder);
        relateCndBuilder.append(classifies.get(0).getTableAlias()).append(".").append("form_data_id=");
        relateCndBuilder.append("f.form_data_id and f.form_id=:formId ");
        relateCndBuilder.append(" and (f.is_delete=0 or f.is_delete is null) ");
        //拼接可选权限条件
        relateCndBuilder.append("[ and f.user_id=:").append(FormListDataScopeType.PERSONAL.getAuthFlag()).append("]");
        relateCndBuilder.append("[ and f.org_id=:").append(FormListDataScopeType.DEPT.getAuthFlag()).append("]");
        relateCndBuilder.append("[ and f.org_id in(:").append(FormListDataScopeType.DEPT_AND_SUB_DEPT.getAuthFlag()).append(")]");
        relateCndBuilder.append("[ and f.org_id in(:").append(FormListDataScopeType.AUTH_DEPT.getAuthFlag()).append(")]");

        sqlBuilder.append(" where ").append(relateCndBuilder).append(whereBuilder);
        this.sql = sqlBuilder.toString();
        LoggerUtils.debug(logger, "生成的SQL语句为：{}", this.sql);
        return this.sql;
    }

    private AbstractListFieldProp getListFieldProp(String fieldId) {
        for(AbstractListFieldProp listField : formListProp.getListFieldProps()) {
            if(listField.getFieldId().equals(fieldId)) {
                return listField;
            }
        }
        return null;
    }

    private String[] getFieldIds() {
        if(CollectionUtils.isEmpty(formListProp.getListFieldProps())) {
            return null;
        }
        String[] fieldIds = new String[formListProp.getListFieldProps().size()];
        int index = 0;
        for(AbstractListFieldProp fieldProp : formListProp.getListFieldProps()) {
            fieldIds[index] = fieldProp.getFieldId();
            index++;
        }
        return fieldIds;
    }

    /**
     * 获取表单字段
     * @param fieldIds
     * @return
     */
    private List<TableFieldClassify> getTableFields(String[] fieldIds) {
        if(null == fieldIds) {
            return null;
        }
        if(null != this.tableFieldClassifies) {
            return this.tableFieldClassifies;
        }
        Map<String, Object> param = new HashMap<>(1);
        param.put("fieldIds", fieldIds);
        SmartResponse<Object> smartResp = opServ.getDatas("get_table_and_field_by_field_ids", param);
        List<TableFieldClassify> classifies = null;
        if(ISmart.OP_SUCCESS.equals(smartResp.getResult())) {
            classifies = new ArrayList<>();
            Map<String, TableFieldClassify> classifyMap = new HashMap<>();
            int index = 1;
            for(Object obj : smartResp.getDatas()) {
                Object[] array = (Object[])obj;
                String tableId = StringUtils.handleNull(array[0]);
                TableFieldClassify classify = classifyMap.get(tableId);
                if(null == classify) {
                    classify = new TableFieldClassify();
                    classify.setTableId(tableId);
                    classify.setTableAlias("t" + index);
                    classify.setTableName(StringUtils.handleNull(array[1]));
                    classifyMap.put(tableId, classify);
                    classify.setFields(new ArrayList<TableFieldClassify.FieldName>());
                    classifies.add(classify);
                    index++;
                }
                classify.getFields().add(new TableFieldClassify.FieldName(StringUtils.handleNull(array[2]),
                        StringUtils.handleNull(array[3]), classify.getTableAlias()));
            }
        }
        this.tableFieldClassifies = classifies;
        return classifies;
    }

    /**
     * 获取字段名称对象
     * @param classifies
     * @param fieldId
     * @return
     */
    private TableFieldClassify.FieldName getFieldName(List<TableFieldClassify> classifies, String fieldId) {
        TableFieldClassify.FieldName fieldName = null;
        for(TableFieldClassify classify : classifies) {
            boolean isBreak = false;
            for(TableFieldClassify.FieldName tmp : classify.getFields()) {
                if(tmp.getFieldId().equals(fieldId)) {
                    fieldName = tmp;
                    isBreak = true;
                    break;
                }
            }
            if(isBreak) {
                break;
            }
        }
        return fieldName;
    }
}
