package com.lanyuanxiaoyao.service.api.service;

import club.kingon.sql.builder.SqlBuilder;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.lanyuanxiaoyao.service.common.Constants;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import static com.lanyuanxiaoyao.service.common.SQLConstants.HudiCollectBuild.TbAppHudiCompactionMetrics;
import static com.lanyuanxiaoyao.service.common.SQLConstants.HudiCollectBuild.TbAppHudiSyncState;

/**
 * 服务
 *
 * @author ZhangJiacheng
 * @date 2022-07-05
 */
@Service
public class SyncStateService {
    private static final Logger logger = LoggerFactory.getLogger(SyncStateService.class);

    private final JdbcTemplate jdbcTemplate;

    public SyncStateService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    private String syncStateId(Long flinkJobId, String alias) {
        return flinkJobId + "-" + alias;
    }

    private Date now() {
        return Date.from(Instant.now());
    }

    public String getMessageId(Long flinkJobId, String alias) {
        List<String> ids = jdbcTemplate.queryForList(
                SqlBuilder
                        .select(TbAppHudiSyncState.MESSAGE_ID_A)
                        .from(TbAppHudiSyncState._alias_)
                        .whereEq(TbAppHudiSyncState.ID_A, null)
                        .precompileSql(),
                String.class,
                syncStateId(flinkJobId, alias)
        );
        if (ObjectUtil.isNotEmpty(ids)) {
            return ids.get(0);
        }
        return "";
    }

    public void saveSyncStartTime(Long flinkJobId, String alias, String cluster, String applicationId) {
        jdbcTemplate.update(
                SqlBuilder
                        .insertInto(
                                TbAppHudiSyncState._origin_,
                                TbAppHudiSyncState.ID_O,
                                TbAppHudiSyncState.SOURCE_START_TIME_O,
                                TbAppHudiSyncState.SOURCE_CLUSTER_O,
                                TbAppHudiSyncState.SOURCE_APPLICATION_ID_O
                        )
                        .values()
                        .addValue(null, null, null, null)
                        .onDuplicateKeyUpdateColumn(TbAppHudiSyncState.SOURCE_START_TIME_O)
                        .addUpdateColumn(TbAppHudiSyncState.SOURCE_CLUSTER_O)
                        .addUpdateColumn(TbAppHudiSyncState.SOURCE_APPLICATION_ID_O)
                        .precompileSql(),
                syncStateId(flinkJobId, alias),
                now(),
                cluster,
                applicationId
        );
    }

    public void saveSyncCheckpointState(Long flinkJobId, String alias, String messageId, Long publishTime) {
        Date publishDate = Date.from(Instant.ofEpochMilli(publishTime));
        jdbcTemplate.update(
                SqlBuilder
                        .insertInto(
                                TbAppHudiSyncState._origin_,
                                TbAppHudiSyncState.ID_O,
                                TbAppHudiSyncState.MESSAGE_ID_O,
                                TbAppHudiSyncState.SOURCE_PUBLISH_TIME_O,
                                TbAppHudiSyncState.SOURCE_CHECKPOINT_TIME_O
                        )
                        .values()
                        .addValue(null, null, null, null)
                        .onDuplicateKeyUpdateColumn(TbAppHudiSyncState.MESSAGE_ID_O)
                        .addUpdateColumn(TbAppHudiSyncState.SOURCE_PUBLISH_TIME_O)
                        .addUpdateColumn(TbAppHudiSyncState.SOURCE_CHECKPOINT_TIME_O)
                        .precompileSql(),
                syncStateId(flinkJobId, alias),
                messageId,
                publishDate,
                now()
        );
    }

    public void saveSyncOperationState(Long flinkJobId, String alias, Long operationTime) {
        Date operationDate = ObjectUtil.isNull(operationTime) ? null : Date.from(Instant.ofEpochMilli(operationTime));
        jdbcTemplate.update(
                SqlBuilder
                        .insertInto(
                                TbAppHudiSyncState._origin_,
                                TbAppHudiSyncState.ID_O,
                                TbAppHudiSyncState.SOURCE_OP_TIME_O
                        )
                        .values()
                        .addValue(null, null)
                        .onDuplicateKeyUpdateColumn(TbAppHudiSyncState.SOURCE_OP_TIME_O)
                        .precompileSql(),
                syncStateId(flinkJobId, alias),
                operationDate
        );
    }

    public void saveCompactionStartTime(Long flinkJobId, String alias, String cluster, String applicationId, String message) {
        jdbcTemplate.update(
                SqlBuilder
                        .insertInto(
                                TbAppHudiSyncState._origin_,
                                TbAppHudiSyncState.ID_O,
                                TbAppHudiSyncState.COMPACTION_START_TIME_O,
                                TbAppHudiSyncState.COMPACTION_MESSAGE_O,
                                TbAppHudiSyncState.COMPACTION_STATUS_O,
                                TbAppHudiSyncState.COMPACTION_STATUS_TIME_O,
                                TbAppHudiSyncState.COMPACTION_CLUSTER_O,
                                TbAppHudiSyncState.COMPACTION_APPLICATION_ID_O
                        )
                        .values()
                        .addValue(null, null, null, null, null, null, null)
                        .onDuplicateKeyUpdateColumn(TbAppHudiSyncState.COMPACTION_START_TIME_O)
                        .addUpdateColumn(TbAppHudiSyncState.COMPACTION_MESSAGE_O)
                        .addUpdateColumn(TbAppHudiSyncState.COMPACTION_STATUS_O)
                        .addUpdateColumn(TbAppHudiSyncState.COMPACTION_STATUS_TIME_O)
                        .addUpdateColumn(TbAppHudiSyncState.COMPACTION_CLUSTER_O)
                        .addUpdateColumn(TbAppHudiSyncState.COMPACTION_APPLICATION_ID_O)
                        .precompileSql(),
                syncStateId(flinkJobId, alias),
                now(),
                message,
                Constants.COMPACTION_STATUS_START,
                now(),
                cluster,
                applicationId
        );
    }

    public void saveCompactionFinishTime(Long flinkJobId, String alias) {
        saveCompactionFinishTime(flinkJobId, alias, Instant.now().toEpochMilli(), "");
    }

    public void saveCompactionFinishTime(Long flinkJobId, String alias, Long timestamp, String message) {
        Date finishDate = Date.from(Instant.ofEpochMilli(timestamp));
        jdbcTemplate.update(
                SqlBuilder
                        .insertInto(
                                TbAppHudiSyncState._origin_,
                                TbAppHudiSyncState.ID_O,
                                TbAppHudiSyncState.COMPACTION_FINISH_TIME_O,
                                TbAppHudiSyncState.COMPACTION_MESSAGE_O,
                                TbAppHudiSyncState.COMPACTION_STATUS_O,
                                TbAppHudiSyncState.COMPACTION_STATUS_TIME_O
                        )
                        .values()
                        .addValue(null, null, null, null, null)
                        .onDuplicateKeyUpdateColumn(TbAppHudiSyncState.COMPACTION_FINISH_TIME_O)
                        .addUpdateColumn(TbAppHudiSyncState.COMPACTION_MESSAGE_O)
                        .addUpdateColumn(TbAppHudiSyncState.COMPACTION_STATUS_O)
                        .addUpdateColumn(TbAppHudiSyncState.COMPACTION_STATUS_TIME_O)
                        .precompileSql(),
                syncStateId(flinkJobId, alias),
                finishDate,
                message,
                Constants.COMPACTION_STATUS_FINISH,
                now()
        );
    }

    public void saveCompactionMetrics(Long flinkJobId, String alias, String type, String instant, String cluster, String applicationId) {
        jdbcTemplate.update(
                SqlBuilder
                        .insertInto(
                                TbAppHudiCompactionMetrics._origin_,
                                TbAppHudiCompactionMetrics.FLINK_JOB_ID_O,
                                TbAppHudiCompactionMetrics.ALIAS_O,
                                TbAppHudiCompactionMetrics.TYPE_O,
                                TbAppHudiCompactionMetrics.COMPACTION_PLAN_INSTANT_O,
                                TbAppHudiCompactionMetrics.CLUSTER_O,
                                TbAppHudiCompactionMetrics.APPLICATION_ID_O,
                                TbAppHudiCompactionMetrics.UPDATE_TIME_O
                        )
                        .values()
                        .addValue(null, null, null, null, null, null, null)
                        .precompileSql(),
                flinkJobId,
                alias,
                type,
                Date.from(Instant.ofEpochMilli(DateUtil.parse(instant).getTime())),
                cluster,
                applicationId,
                now()
        );
    }

    public void saveCompactionLatestOperationTime(Long flinkJobId, String alias, Long latestOperationTime) {
        Date operationDate = ObjectUtil.isNull(latestOperationTime) ? null : Date.from(Instant.ofEpochMilli(latestOperationTime));
        jdbcTemplate.update(
                SqlBuilder
                        .insertInto(
                                TbAppHudiSyncState._origin_,
                                TbAppHudiSyncState.ID_O,
                                TbAppHudiSyncState.COMPACTION_LATEST_OP_TS_O
                        )
                        .values()
                        .addValue(null, null)
                        .onDuplicateKeyUpdateColumn(TbAppHudiSyncState.COMPACTION_LATEST_OP_TS_O)
                        .precompileSql(),
                syncStateId(flinkJobId, alias),
                operationDate
        );
    }
}
