package com.yice.webadmin.app.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yice.common.core.object.MyPageParam;
import com.yice.webadmin.app.constant.DatasetConstant;
import com.yice.webadmin.app.constant.MongoConstant;
import com.yice.webadmin.app.data.DatasetData;
import com.yice.webadmin.app.service.DatasetCleanService;
import com.yice.webadmin.app.service.DatasetDataService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;

/**
 * 数据集版本数据操作服务类。
 *
 * @author linking
 * @date 2023-04-13
 */
@Slf4j
@Service("datasetDataService")
public class DatasetDataServiceImpl implements DatasetDataService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private DatasetCleanService datasetCleanService;

    /**
     * 保存新增对象。
     *
     * @param datasetData 新增对象。
     * @return 返回新增对象。
     */
    @Override
    public void save(DatasetData datasetData) {
        if (StringUtils.isNotBlank(datasetData.getData())) {
            List<Document> documents = new ArrayList<>();
            JSONArray jsonArray = JSONArray.parseArray(datasetData.getData());
            if (null != jsonArray && jsonArray.size() > 0) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    Integer markStatus = jsonObject.getString(MongoConstant.OUTPUT) != null
                            && !jsonObject.getString(MongoConstant.OUTPUT).equals(MongoConstant.EMPTY) ? 1 : 0;
                    Document document = new Document(MongoConstant.DATA,jsonObject)
                            .append(MongoConstant.VERSION, datasetData.getVersionId())
                            .append(MongoConstant.CREATE_TIME, datasetData.getCreateTime())
                            .append(MongoConstant.MARK_STATUS, markStatus);
                    documents.add(document);
                }
            }
            mongoTemplate.insert(documents,
                    MongoConstant.COLLECT_NAME + datasetData.getVersionId());
        }
    }

    /**
     * 查询列表集合
     * @param versionId 版本标识
     * @param pageParam 页码参数
     * @return 返回查看对象列表
     */
    @Override
    public List<DatasetData> list(Long versionId, MyPageParam pageParam) {
        Query query = new Query(Criteria.where(MongoConstant.VERSION).is(versionId))
                .skip((pageParam.getPageNum() - 1) * pageParam.getPageSize())
                .limit(pageParam.getPageSize());

        return mongoTemplate.find(query, DatasetData.class,
                MongoConstant.COLLECT_NAME + versionId);
    }

    /**
     * 开始清洗工作
     * @param datasetId 数据集对应的版本
     * @param cleanId 清洗任务标识
     */
    @Async
    @Override
    public void doDatasetCleanHandler(Long datasetId, Long cleanId) {
        MyPageParam param = new MyPageParam();
        param.setPageNum(DatasetConstant.PAGE_NUM);
        param.setPageSize(DatasetConstant.MAX_PAGE_SIZE);
        List<DatasetData> dataList = this.list(datasetId, param);
        if(CollUtil.isNotEmpty(dataList)) {
            datasetCleanService.executeCleanTaskAsync(dataList, cleanId, datasetId);
        }
    }

    /**
     * 根据条件查询数据集数据。
     *
     * @param filter  过滤对象。
     * @param pageParam 分页对象。
     * @return 查询结果集。
     */
    @Override
    public List<DatasetData> list(DatasetData filter, MyPageParam pageParam) {
        Query query = new Query();
        query.addCriteria(Criteria.where(MongoConstant.VERSION).is(filter.getVersionId()));
        if (filter.getMarkStatus() != null) {
            query.addCriteria(Criteria.where(MongoConstant.MARK_STATUS).is(filter.getMarkStatus()));
        }
        query.skip((pageParam.getPageNum() - 1) * pageParam.getPageSize())
                .limit(pageParam.getPageSize());
        return mongoTemplate.find(query, DatasetData.class,
                MongoConstant.COLLECT_NAME + filter.getVersionId());
    }

    /**
     * 根据条件查询列表集合总条数
     * @param filter 版本标识
     * @return 返回总条数
     */
    @Override
    public Long count(DatasetData filter) {
        Query query = new Query();
        query.addCriteria(Criteria.where(MongoConstant.VERSION).is(filter.getVersionId()));
        if (filter.getMarkStatus() != null) {
            query.addCriteria(Criteria.where(MongoConstant.MARK_STATUS).is(filter.getMarkStatus()));
        }
        return mongoTemplate.count(query, DatasetData.class,
                MongoConstant.COLLECT_NAME + filter.getVersionId());
    }

    /**
     * 查询列表集合总条数
     * @param versionId 版本标识
     * @return 返回总条数
     */
    @Override
    public Long count(Long versionId) {
        Query query = new Query(Criteria.where(MongoConstant.VERSION).is(versionId));
        return mongoTemplate.count(query, DatasetData.class,
                MongoConstant.COLLECT_NAME + versionId);
    }

    /**
     * 根据id查询该条信息。
     *
     * @param id 文档标识。
     * @param versionId 版本标识。
     * @return 返回查看对象。
     */
    @Override
    public DatasetData view(String id, Long versionId) {
        return mongoTemplate.findById(id, DatasetData.class,
                MongoConstant.COLLECT_NAME + versionId);
    }

    /**
     * 更新数据对象。
     *
     * @param datasetData 更新的对象。
     * @return 成功返回true，否则false。
     */
    @Override
    public void update(DatasetData datasetData) {
        mongoTemplate.save(datasetData,
                MongoConstant.COLLECT_NAME + datasetData.getVersionId());
    }

    /**
     * 更新数据对象。
     *
     * @param dataList 更新的对象。
     * @param versionId 更新的对象。
     * @return 成功返回true，否则false。
     */
    @Override
    public void updateBatch(List<DatasetData> dataList, Long versionId) {
        if(CollUtil.isNotEmpty(dataList)) {
            for(DatasetData datasetData : dataList) {

                // 解析data字段的字符串为Document或Bson
                Document dataDocument = null;

                if(StringUtils.isNotBlank(datasetData.getData())) {
                    dataDocument = Document.parse(datasetData.getData());
                }

                // 构建查询条件
                Query query = new Query(Criteria.where(MongoConstant.ID).is(datasetData.getId()));

                // 构建更新操作
                Update update = new Update();
                update.set(MongoConstant.DATA, dataDocument);

                // 执行更新操作
                mongoTemplate.updateFirst(query, update, MongoConstant.COLLECT_NAME + versionId);

            }
        }
    }

    /**
     * 删除指定数据。
     *
     * @param id 文档标识。
     * @param versionId 版本标识。
     * @return 返回受影响的行数。
     */
    @Override
    public Long remove(String id, Long versionId) {
        Query query = new Query(Criteria.where(MongoConstant.ID).is(id));
        return mongoTemplate.remove(query, DatasetData.class,
                MongoConstant.COLLECT_NAME + versionId).getDeletedCount();
    }

    /**
     * 删除整个集合中的文档数据。
     *
     * @param versionId 版本标识。
     * @return 返回受影响的行数。
     */
    @Override
    public void delete(Long versionId) {
        mongoTemplate.dropCollection(MongoConstant.COLLECT_NAME + versionId);
    }

    /**
     * 删除整个集合中的空文档数据集数据。
     *
     * @param versionId 版本标识。
     * @return 返回受影响的行数。
     */
    @Override
    public void deleteByData(Long versionId) {
        Query query = new Query();
        query.addCriteria(Criteria.where(DatasetConstant.DATA).is(DatasetConstant.NULL_STR));
        mongoTemplate.remove(query, MongoConstant.COLLECT_NAME + versionId);
    }
}
