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

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.client.admin.common.enums.BannersTargetType;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.BeanUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
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.KylinBannersVo;
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.mongodb.BasicDBObject;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import org.bson.Document;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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 org.springframework.util.StringUtils;

import java.time.LocalDateTime;
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 {

    @Value("${liquidnet.al-oss.imgUrl}")
    private String imgUrl;

    @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 = DateUtil.Formatter.yyyyMMddHHmmss.format(createdAt);
            if (StringUtils.isEmpty(bannersParam.getOnlineStartTime())) {
                bannersParam.setOnlineStartTime(null);
            }
            if (StringUtils.isEmpty(bannersParam.getOnlineEndTime())) {
                bannersParam.setOnlineEndTime(null);
            }
            // 入数据库
            bannersMapper.insert(bannersParam.getFields(bannersId, createdAtString));

            List<String> positionList = bannersParam.getPositionList();
            KylinBannersRelations kylinBannersRelations = new KylinBannersRelations();
            String bannersRelationsId = IDGenerator.nextSnowId().toString();
            kylinBannersRelations.setBannersRelationsId(bannersRelationsId);
            kylinBannersRelations.setBannersId(bannersId);
            kylinBannersRelations.setCreatedAt(createdAtString);
            for (String fieldId : positionList) {
                kylinBannersRelations.setFieldId(fieldId);
                kylinBannersRelations.setFieldIdType(1);
                kylinBannersRelationsMapper.insert(kylinBannersRelations);
            }
            List<String> provincesList = bannersParam.getProvincesList();
            List<String> provincesNameList = bannersParam.getProvincesNameList();
            if (!provincesList.isEmpty()) {
                for (int i = 0; i < provincesList.size(); i++) {
                    kylinBannersRelations.setFieldId(provincesList.get(i));
                    kylinBannersRelations.setFieldIdType(2);
                    kylinBannersRelations.setFieldName(provincesNameList.get(i));
                    kylinBannersRelationsMapper.insert(kylinBannersRelations);
                }
            }

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

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

    public boolean update(BannersParam bannersParam) {
        try {
            // 时间
            String bannersId = bannersParam.getBannersId();
            LocalDateTime updatedAt = LocalDateTime.now();
            String updatedAtString = DateUtil.Formatter.yyyyMMddHHmmss.format(updatedAt);

            KylinBanners params = bannersParam.getFields(null, null);
            params.setUpdatedAt(updatedAtString);
            if (StringUtils.isEmpty(bannersParam.getOnlineStartTime())) {
                params.setOnlineStartTime(null);
            }
            if (StringUtils.isEmpty(bannersParam.getOnlineEndTime())) {
                params.setOnlineEndTime(null);
            }
            // 入数据库
            bannersMapper.update(params, new UpdateWrapper<KylinBanners>().eq("banners_id", bannersId));

            List<String> positionList = bannersParam.getPositionList();
            KylinBannersRelations kylinBannersRelations = new KylinBannersRelations();
            String bannersRelationsId = IDGenerator.nextSnowId().toString();
            kylinBannersRelations.setBannersRelationsId(bannersRelationsId);
            kylinBannersRelations.setBannersId(bannersId);
            kylinBannersRelations.setCreatedAt(updatedAtString);
            // 入数据库 先删除之前的
            kylinBannersRelationsMapper.delete(
                    new UpdateWrapper<KylinBannersRelations>().eq("banners_id", bannersId).eq("field_id_type", 1)
            );
            for (String fieldId : positionList) {
                kylinBannersRelations.setFieldId(fieldId);
                kylinBannersRelations.setFieldIdType(1);
                kylinBannersRelationsMapper.insert(kylinBannersRelations);
            }
            List<String> provincesList = bannersParam.getProvincesList();
            List<String> provincesNameList = bannersParam.getProvincesNameList();
            if (!provincesList.isEmpty()) {
                // 入数据库 先删除之前的
                kylinBannersRelationsMapper.delete(
                        new UpdateWrapper<KylinBannersRelations>().eq("banners_id", bannersId).eq("field_id_type", 2)
                );
                if (!provincesList.isEmpty()) {
                    for (int i = 0; i < provincesList.size(); i++) {
                        kylinBannersRelations.setFieldId(provincesList.get(i));
                        kylinBannersRelations.setFieldIdType(2);
                        kylinBannersRelations.setFieldName(provincesNameList.get(i));
                        kylinBannersRelationsMapper.insert(kylinBannersRelations);
                    }
                }
            }
            // 处理缓存数据
            KylinBannersVo kylinBannersVo = new KylinBannersVo();
            BeanUtils.copyProperties(bannersParam, kylinBannersVo);
            kylinBannersVo.setBannersId(bannersId);
            kylinBannersVo.setUpdatedAt(updatedAtString);
            // 修改缓存
            BasicDBObject object = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinBannersVo)));
            Document doc = mongoTemplate.getCollection(KylinBannersVo.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("bannersId").is(bannersId)).getQueryObject(),
                    object,
                    new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );

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

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

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

            BeanUtils.copyProperties(data, kylinBannersVo);
        } else {
            return null;
        }

        return kylinBannersVo;
    }

    public PageInfo<BannerDetailsListDao> bannerList(BannersSearchParam bannersSearchParam) {
        PageInfo<BannerDetailsListDao> pageInfoTmp = null;
        try {
            PageHelper.startPage(bannersSearchParam.getPageNum(), bannersSearchParam.getPageSize());
            List<BannerDetailsListDao> voList = bannersMapper.searchBannersList(BeanUtil.convertBeanToMap(bannersSearchParam));
            for (BannerDetailsListDao item : voList) {
                item.setIsOnlineName(item.getIsOnline());
                item.setPromotionTypeName(item.getPromotionType());

                String typeName = BannersTargetType.getTypeName(item.getTargetType());
                item.setTargetTypeName(typeName);

                item.setCoverImg(imgUrl + item.getCoverImg());
            }
            pageInfoTmp = new PageInfo(voList);
        } catch (Exception e) {
            return new PageInfo();
        }
        return pageInfoTmp;
    }

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

    public Boolean delete(List<String> bannersId) {
        try {
            LocalDateTime updatedAt = LocalDateTime.now();
            String updatedAtString = DateUtil.Formatter.yyyyMMddHHmmss.format(updatedAt);

            KylinBanners kylinBanners = new KylinBanners();
            kylinBanners.setUpdatedAt(updatedAtString);
            kylinBanners.setIsDeleted(0);
            bannersMapper.update(
                    kylinBanners
                    , new UpdateWrapper<KylinBanners>().in("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(KylinBannersVo.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("bannersId").in(bannersId)).getQueryObject(),
                    object,
                    new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );

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

}
