package com.liquidnet.service.kylin.service.impl.admin;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.BeanUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dao.BannerDetailsListDao;
import com.liquidnet.service.kylin.dto.param.BannersParam;
import com.liquidnet.service.kylin.dto.param.BannersSearchParam;
import com.liquidnet.service.kylin.dto.vo.BannersVo;
import com.liquidnet.service.kylin.entity.KylinBanners;
import com.liquidnet.service.kylin.entity.KylinBannersRelations;
import com.liquidnet.service.kylin.mapper.KylinBannersMapper;
import com.liquidnet.service.kylin.mapper.KylinBannersRelationsMapper;
import com.liquidnet.service.kylin.service.admin.IKylinBannersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mysql.cj.util.StringUtils;
import org.bson.Document;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 轮播图 服务实现类
 * </p>
 *
 * @author jiangxiulong
 * @since 2021-05-02
 */
@Service
public class KylinBannersServiceImpl extends ServiceImpl<KylinBannersMapper, KylinBanners> implements IKylinBannersService {

    @Autowired
    private KylinBannersMapper bannersMapper;

    @Autowired
    private KylinBannersRelationsMapper kylinBannersRelationsMapper;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    private MongoConverter mongoConverter;

    @Autowired
    RedisUtil redisUtil;

    public boolean create(BannersParam bannersParam) {
        try {
            // 时间
            String bannersId = IDGenerator.nextSnowId().toString();
            LocalDateTime createdAt = LocalDateTime.now();
            String createdAtString = createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            // 入数据库
            bannersMapper.insert(bannersParam.getFields(bannersId, createdAtString));

            List<String> positionList = bannersParam.getPositionList();
            KylinBannersRelations kylinBannersRelations = new KylinBannersRelations();
            for (String fieldId : positionList) {
                KylinBannersRelations relations = kylinBannersRelations.newData(bannersId, fieldId, 1, createdAtString);
                kylinBannersRelationsMapper.insert(relations);

                mongoTemplate.insert(kylinBannersRelations, KylinBannersRelations.class.getSimpleName());
                redisUtil.hset(KylinRedisConst.BANNERSRELATIONS, kylinBannersRelations.getBannersRelationsId(), kylinBannersRelations);
            }
            List<String> provincesList = bannersParam.getProvincesList();
            if (!provincesList.isEmpty()) {
                for (String fieldId : provincesList) {
                    KylinBannersRelations relations = kylinBannersRelations.newData(bannersId, fieldId, 2, createdAtString);
                    kylinBannersRelationsMapper.insert(relations);

                    mongoTemplate.insert(kylinBannersRelations, KylinBannersRelations.class.getSimpleName());
                    redisUtil.hset(KylinRedisConst.BANNERSRELATIONS, kylinBannersRelations.getBannersRelationsId(), kylinBannersRelations);
                }
            }

            // 处理缓存数据
            BannersVo bannersVo = new BannersVo();
            BeanUtils.copyProperties(bannersParam, bannersVo);
            bannersVo.setBannersId(bannersId);
            bannersVo.setCreatedAt(createdAtString);
            // 处理基础数据 防止缓存中无字段
            bannersVo.setIsDeleted(1);
            bannersVo.setUpdatedAt("");
            if (StringUtils.isNullOrEmpty(bannersParam.getTargetObj())) {
                bannersVo.setTargetObj("");
            }
            if (StringUtils.isNullOrEmpty(bannersParam.getOnlineStartTime())) {
                bannersVo.setOnlineEndTime("");
            }
            if (StringUtils.isNullOrEmpty(bannersParam.getOnlineEndTime())) {
                bannersVo.setOnlineEndTime("");
            }
            if (null == bannersParam.getBannersSort()) {
                bannersVo.setBannersSort(0);
            }
            if (StringUtils.isNullOrEmpty(bannersParam.getRemarks())) {
                bannersVo.setRemarks("");
            }
            // 入缓存
            mongoTemplate.insert(bannersVo, BannersVo.class.getSimpleName());

            redisUtil.hset(KylinRedisConst.BANNERS, bannersId, bannersVo);

            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public boolean update(BannersParam bannersParam) {
        try {
            // 时间
            String bannersId = bannersParam.getBannersId();
            LocalDateTime updatedAt = LocalDateTime.now();
            String updatedAtString = updatedAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

            KylinBanners params = bannersParam.getFields(null, null);
            params.setUpdatedAt(updatedAtString);
            // 入数据库
            bannersMapper.update(params, new UpdateWrapper<KylinBanners>().eq("banners_id", bannersId));

            List<String> positionList = bannersParam.getPositionList();
            // 删除之前的再添加
            List<String> relationsIds = kylinBannersRelationsMapper.getBannersRelationsField("banners_relations_id",bannersId, 1);
            kylinBannersRelationsMapper.delete(
                    new UpdateWrapper<KylinBannersRelations>().eq("banners_id", bannersId).eq("field_id_type", 1)
            );
            mongoTemplate.remove(
                    Query.query(Criteria.where("bannersId").is(bannersId).and("fieldIdType").is(1)),
                    KylinBannersRelations.class.getSimpleName()
            );
            for (String relationsId : relationsIds) {
                redisUtil.hdel(KylinRedisConst.BANNERSRELATIONS, relationsId);
            }
            KylinBannersRelations kylinBannersRelations = new KylinBannersRelations();
            for (String fieldId : positionList) {
                KylinBannersRelations relations = kylinBannersRelations.newData(bannersId, fieldId, 1, updatedAtString);
                kylinBannersRelationsMapper.insert(relations);

                mongoTemplate.insert(relations, KylinBannersRelations.class.getSimpleName());
                redisUtil.hset(KylinRedisConst.BANNERSRELATIONS, relations.getBannersRelationsId(), relations);
            }
            List<String> provincesList = bannersParam.getProvincesList();
            if (!provincesList.isEmpty()) {
                // 删除之前的再添加
                List<String> relationsIdss = kylinBannersRelationsMapper.getBannersRelationsField("banners_relations_id",bannersId, 2);
                kylinBannersRelationsMapper.delete(
                        new UpdateWrapper<KylinBannersRelations>().eq("banners_id", bannersId).eq("field_id_type", 2)
                );
                mongoTemplate.remove(
                        Query.query(Criteria.where("bannersId").is(bannersId).and("fieldIdType").is(2)),
                        KylinBannersRelations.class.getSimpleName()
                );
                for (String relationsId : relationsIdss) {
                    redisUtil.hdel(KylinRedisConst.BANNERSRELATIONS, relationsId);
                }
                for (String fieldId : provincesList) {
                    KylinBannersRelations relations = kylinBannersRelations.newData(bannersId, fieldId, 2, updatedAtString);
                    kylinBannersRelationsMapper.insert(relations);

                    mongoTemplate.insert(relations, KylinBannersRelations.class.getSimpleName());

                    redisUtil.hset(KylinRedisConst.BANNERSRELATIONS, relations.getBannersRelationsId(), relations);
                }
            }
            // 处理缓存数据
            BannersVo bannersVo = new BannersVo();
            BeanUtils.copyProperties(bannersParam, bannersVo);
            bannersVo.setBannersId(bannersId);
            bannersVo.setUpdatedAt(updatedAtString);
            // 修改缓存
            BasicDBObject object = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(bannersVo)));
            Document doc = mongoTemplate.getCollection(BannersVo.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("bannersId").is(bannersId)).getQueryObject(),
                    object,
                    new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );

            redisUtil.hset(KylinRedisConst.BANNERS, bannersId, JsonUtils.fromJson(doc.toJson(), BannersVo.class));

            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public KylinBanners detail(String bannersId) {
        KylinBanners data = bannersMapper.selectOne(new UpdateWrapper<KylinBanners>().eq("banners_id", bannersId).eq("is_deleted", 1));
        List<String> positionList = kylinBannersRelationsMapper.getBannersRelationsField("field_id", bannersId, 1);
        List<String> provincesList = kylinBannersRelationsMapper.getBannersRelationsField("field_id", bannersId, 2);

        data.setPositionList(positionList);
        data.setProvincesList(provincesList);

        return data;
    }

    public List<BannerDetailsListDao> bannerList(BannersSearchParam bannersSearchParam) {
        try {
            bannersSearchParam.setPage((bannersSearchParam.getPage() - 1) * bannersSearchParam.getSize());

            List<BannerDetailsListDao> data = bannersMapper.searchBannersList(BeanUtil.convertBeanToMap(bannersSearchParam));
            return data;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return new ArrayList<>();
        }
    }

    public Long bannerListCount(BannersSearchParam bannersSearchParam) {
        try {
            Long count = bannersMapper.searchBannersCount(BeanUtil.convertBeanToMap(bannersSearchParam));
            return count;
        } catch (Exception e) {
            return 0L;
        }
    }

    public Boolean delete(String bannersId) {
        try {
            LocalDateTime updatedAt = LocalDateTime.now();
            String updatedAtString = updatedAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

            KylinBanners kylinBanners = new KylinBanners();
            kylinBanners.setUpdatedAt(updatedAtString);
            kylinBanners.setIsDeleted(0);
            bannersMapper.update(kylinBanners
                    , new UpdateWrapper<KylinBanners>().eq("banners_id", bannersId));

            // mongo 操作
            HashMap<String, Object> map = new HashMap<>();
            map.put("updatedAt", updatedAtString);
            map.put("isDeleted", 0);

            BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(map));
            Document doc = mongoTemplate.getCollection(BannersVo.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("bannersId").is(bannersId)).getQueryObject(),
                    object,
                    new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );

            // redis 操作
            redisUtil.hset(KylinRedisConst.BANNERS, bannersId, JsonUtils.fromJson(doc.toJson(), BannersVo.class));

            return true;
        } catch (Exception e) {
            return false;
        }
    }

}
