package com.red.circle.console.infra.database.mongo.admin.service.impl;

import com.mongodb.BasicDBObject;
import com.red.circle.console.infra.database.mongo.admin.entity.BackDashboard;
import com.red.circle.console.infra.database.mongo.admin.entity.BackDashboardNavigation;
import com.red.circle.console.infra.database.mongo.admin.service.BackDashboardService;
import com.red.circle.tool.core.collection.CollectionUtils;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
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.stereotype.Service;

/**
 * @author pengliang on 2022/7/12
 */
@Service
@RequiredArgsConstructor
public class BackDashboardServiceImpl implements BackDashboardService {

  private final MongoTemplate mongoTemplate;

  @Override
  public void addRecentPreviews(Long userId, BackDashboardNavigation navigation) {
    BackDashboard backDashboard = getById(userId);
    if (Objects.nonNull(backDashboard)) {
      List<BackDashboardNavigation> navigations = backDashboard.getRecentPreviews().stream()
          .filter(dashboardNavigation -> !Objects.equals(dashboardNavigation.getId(),
              navigation.getId()))
          .collect(Collectors.toList());
      navigations.add(navigation);
      mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(userId.toString())),
          new Update()
              .set("recentPreviews", getLatestNavigationTop20(navigations)),
          BackDashboard.class);
      return;
    }

    mongoTemplate.save(new BackDashboard()
        .setId(userId.toString())
        .setTheme("auto")
        .setRecentPreviews(List.of(navigation))
        .setCustomNavigations(CollectionUtils.newArrayList())
    );
  }

  @Override
  public void removeRecentPreviews(Long userId, String id) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(userId.toString())),
        new Update()
            .pull("recentPreviews", new BasicDBObject("id",
                new BasicDBObject("$eq", id))),
        BackDashboard.class);
  }

  private List<BackDashboardNavigation> getLatestNavigationTop20(
      List<BackDashboardNavigation> navigations) {
    return navigations.stream()
        .sorted(Comparator.comparing(BackDashboardNavigation::getCreateTime).reversed())
        .limit(20).collect(Collectors.toList());
  }

  @Override
  public void addCustomNavigations(Long userId, BackDashboardNavigation navigation) {
    BackDashboard backDashboard = getById(userId);
    if (Objects.nonNull(backDashboard)) {
      mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(userId.toString())),
          new Update()
              .pull("customNavigations", new BasicDBObject("id",
                  new BasicDBObject("$eq", navigation.getId()))),
          BackDashboard.class);

      mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(userId.toString())),
          new Update()
              .push("customNavigations", navigation),
          BackDashboard.class);
      return;
    }

    mongoTemplate.save(new BackDashboard()
        .setId(userId.toString())
        .setRecentPreviews(CollectionUtils.newArrayList())
        .setCustomNavigations(List.of(navigation))
    );
  }

  @Override
  public void removeCustomNavigations(Long userId, String id) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(userId.toString())),
        new Update()
            .pull("customNavigations", new BasicDBObject("id",
                new BasicDBObject("$eq", id))),
        BackDashboard.class);
  }

  @Override
  public void updateTheme(Long userId, String theme) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(userId.toString())),
        new Update()
            .set("theme", theme),
        BackDashboard.class);
  }

  @Override
  public BackDashboard getById(Long userId) {
    return mongoTemplate.findOne(
        Query.query(Criteria.where("id").is(userId.toString())), BackDashboard.class);
  }

}
