/*
 * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.face.global.mybatisplus.method;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.google.common.base.CaseFormat;
import com.face.global.entity.BaseEntity;
import com.face.global.mybatisplus.annotation.HistoryColumn;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 插入一条历史数据
 */
public class InsertH extends AbstractMethod {

    private final static String SQL = "<script>\nINSERT INTO %s_h (%s) VALUES (%s)\n</script>";

    public InsertH() {
        super("insertH");
    }

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        Field[] baseFields = FieldUtils.getAllFields(BaseEntity.class);
        List<String> baseColumns = new ArrayList<>();
        List<String> baseFieldNames = new ArrayList<>();
        for (Field field : baseFields) {
            baseColumns.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName()));
            baseFieldNames.add(HASH_LEFT_BRACE.concat(field.getName()).concat(RIGHT_BRACE));
        }
        List<String> extraColumns = new ArrayList<>();
        List<Field> extraFields = Arrays.stream(FieldUtils.getAllFields(modelClass))
                .filter(field -> field.getAnnotation(HistoryColumn.class) != null).toList();
        List<String> extraFieldNames = new ArrayList<>();
        for (Field field : extraFields) {
            extraColumns.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName()));
            extraFieldNames.add(HASH_LEFT_BRACE.concat(field.getName()).concat(RIGHT_BRACE));
        }
        List<String> defaultColumns = new ArrayList<>();
        defaultColumns.add("id");
        defaultColumns.add("main_id");
        defaultColumns.add("content");
        defaultColumns.add("seqno");
        defaultColumns.add("operate_type");
        List<String> defaultFields = new ArrayList<>();
        defaultFields.add(HASH_LEFT_BRACE.concat("id").concat(RIGHT_BRACE));
        defaultFields.add(HASH_LEFT_BRACE.concat("mainId").concat(RIGHT_BRACE));
        defaultFields.add(HASH_LEFT_BRACE.concat("content").concat(RIGHT_BRACE));
        defaultFields.add(HASH_LEFT_BRACE.concat("seqno").concat(RIGHT_BRACE));
        defaultFields.add(HASH_LEFT_BRACE.concat("operateType").concat(RIGHT_BRACE));
        List<String> allColumns = new ArrayList<>();
        allColumns.addAll(defaultColumns);
        allColumns.addAll(baseColumns);
        allColumns.addAll(extraColumns);
        String defaultInsertColumn = StringUtils.join(allColumns, ",");
        List<String> allFields = new ArrayList<>();
        allFields.addAll(defaultFields);
        allFields.addAll(baseFieldNames);
        allFields.addAll(extraFieldNames);
        String defaultValuesColumn = StringUtils.join(allFields, ",");
        String sql = String.format(SQL, tableInfo.getTableName(), defaultInsertColumn, defaultValuesColumn);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
        return this.addInsertMappedStatement(mapperClass, modelClass, methodName, sqlSource,
                NoKeyGenerator.INSTANCE, null, null);
    }
}
