package com.red.circle.console.app.service.app.sys;

import com.red.circle.console.infra.database.rds.service.admin.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @author pengliang
 * @since 2020/3/6 15:53
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SysPushServiceImpl implements SysPushService {

  private final UserService userService;
  /*private final ISysPushTaskService sysPushTaskService;
  private final IUserBaseInfoService userBaseInfoService;
  private final ISysPushRecordLogService sysPushRecordLogService;
  private final GoogleFirebasePushService googleFirebasePushService;
  private final ISysPushUserRecordLogService sysPushUserRecordLogService;
  private final IUserLatestMobileDeviceService userLatestMobileDeviceService;

  @Override
  public void create(CreateRecordCmd createRecordParam) {

    if (StringUtils.isBlank(createRecordParam.getSysOrigin())) {
      return;
    }

    if (createRecordParam.isGoogleDevice()) {

      pushGoogle(createRecordParam);
    }
  }

  @Override
  public PageResult<SysPushRecordLogCO> pageLogs(SysPushRecordLogQryCmd query) {

    IPage<SysPushRecordLog> sysPushRecordLogPage = sysPushRecordLogService.query()
        .eq(StringUtils.isNotBlank(query.getBusinessScene()), SysPushRecordLog::getBusinessScene,
            query.getBusinessScene())
        .eq(StringUtils.isNotBlank(query.getPlatform()), SysPushRecordLog::getPlatform,
            query.getPlatform())
        .eq(StringUtils.isNotBlank(query.getDeviceType()), SysPushRecordLog::getDeviceType,
            query.getDeviceType())
        .eq(StringUtils.isNotBlank(query.getSysOrigin()), SysPushRecordLog::getSysOrigin,
            query.getSysOrigin())
        .ge(Objects.nonNull(query.getStartCreateDate()), SysPushRecordLog::getCreateTime,
            query.getStartCreateDate())
        .le(Objects.nonNull(query.getEndCreateDate()), SysPushRecordLog::getCreateTime,
            query.getEndCreateDate())
        .eq(Objects.nonNull(query.getPushStatus()) && query.isSuccess(),
            SysPushRecordLog::getPushStatus, ResultStatusEnum.SUCCESS)
        .in(Objects.nonNull(query.getPushStatus()) && !query.isSuccess(),
            SysPushRecordLog::getPushStatus, ResultStatusEnum.getFailKeys())
        .orderByDesc(SysPushRecordLog::getId)
        .page(query);

    if (CollectionUtil.isEmpty(sysPushRecordLogPage.getRecords())) {
      return sysPushRecordLogPage
          .convert(sysPushRecordLog -> sysPushRecordLog.convert(SysPushRecordLogCO.class));
    }

    Map<Long, User> userMap = userService.mapBackUser(getBackUserIds(sysPushRecordLogPage));
    Map<Long, UserBaseInfo> userBaseInfoMap = userBaseInfoService
        .mapByIds(getAppUserIds(sysPushRecordLogPage));

    return sysPushRecordLogPage.convert(sysPushRecordLog -> {
      SysPushRecordLogCO sysPushRecordLogVO = sysPushRecordLog.convert(SysPushRecordLogCO.class);
      sysPushRecordLogVO
          .setBusinessScene(MessageBusinessSceneEnum.getDesc(sysPushRecordLog.getBusinessScene()));
      sysPushRecordLogVO.setPushStatus(ResultStatusEnum.getDesc(sysPushRecordLog.getPushStatus()));

      if (PushOriginEnum.isBack(sysPushRecordLog.getOrigin())) {
        User user = userMap.get(sysPushRecordLog.getCreateUser());
        if (Objects.nonNull(user)) {
          sysPushRecordLogVO.setSendUserName(user.getNickname());
        }
        return sysPushRecordLogVO;
      }

      UserBaseInfo userBaseInfo = userBaseInfoMap.get(sysPushRecordLog.getCreateUser());
      if (Objects.nonNull(userBaseInfo)) {
        sysPushRecordLogVO.setSendUserName(userBaseInfo.getUserNickname());
      }
      return sysPushRecordLogVO;
    });
  }

  @Override
  public PageResult<SysPushTaskCO> pageTask(SysPushTaskQryCmd query) {
    return sysPushTaskService.pageTask(query);
  }

  @Override
  public void saveTask(SysPushTaskCmd param) {
    sysPushTaskService.saveTask(param);
  }


  @Override
  public void deletePushTask(Long id) {
    sysPushTaskService.deletePushTask(id);
  }

  private List<Long> getBackUserIds(PageResult<SysPushRecordLogCO> sysPushRecordLogPage) {
    return sysPushRecordLogPage.getRecords().stream().filter(sysPushRecordLog ->
        PushOriginEnum.isBack(sysPushRecordLog.getOrigin()) && sysPushRecordLog.getCreateUser() > 0
    ).map(SysPushRecordLog::getCreateUser).collect(Collectors.toList());
  }

  private Set<Long> getAppUserIds(IPage<SysPushRecordLog> sysPushRecordLogPage) {
    return sysPushRecordLogPage.getRecords().stream().filter(sysPushRecordLog ->
        PushOriginEnum.isApp(sysPushRecordLog.getOrigin()) && sysPushRecordLog.getCreateUser() > 0
    ).map(SysPushRecordLog::getCreateUser).collect(Collectors.toSet());
  }


  *//**
   * 推送谷歌
   *//*
  private void pushGoogle(CreateRecordCmd createRecordParam) {

    List<UserLatestMobileDevicePushDTO> users = userLatestMobileDeviceService
        .listPushUserByCondition(createRecordParam);

    if (CollectionUtils.isEmpty(users)) {
      return;
    }

    ThreadPoolManager.getInstance().execute("pushGoogle", () -> {

      List<String> deviceIds = users.stream().map(UserLatestMobileDevicePushDTO::getDeviceId)
          .collect(Collectors.toList());

      //推送并处理结果
      processPush(createRecordParam, users, googleFirebasePushService.sendMulticast(
          PushParam.builder()
              .sysOrigin(SysOriginPlatformEnum.valueOf(createRecordParam.getSysOrigin()))
              .androidDevices(deviceIds)
              .title(createRecordParam.getTitle())
              .body(createRecordParam.getContent())
              .build()
      ));
    });
  }

  private void processPush(CreateRecordCmd createRecordParam,
      List<UserLatestMobileDevicePushDTO> users,
      FirebaseResponses responses) {

    if (Objects.isNull(responses) || Objects.equals(responses.getFailCount(), users.size())) {
      //全部失败
      allPushFail(createRecordParam, users);
      return;
    }

    createRecordParam.setPushStatus(ResultStatusEnum.SUCCESS.name());
    createRecordParam.setFailQuantity(responses.getFailCount());
    createRecordParam.setSuccessQuantity(responses.getSuccessCount());
    addPushLog(createRecordParam);
    //处理成功或失败
    processPushResult(createRecordParam.getId(), users, responses);
  }

  private void processPushResult(Long pushId, List<UserLatestMobileDevicePushDTO> users,
      FirebaseResponses responses) {

    List<String> successTokens = responses.getSuccessDevicesString();
    List<String> failTokens = responses.getFailDevicesString();

    List<SysPushUserRecordLog> saveData = Lists.newArrayList();
    Timestamp date = TimestampUtils.now();

    for (UserLatestMobileDevicePushDTO user : users) {

      SysPushUserRecordLog pushUserRecord = new SysPushUserRecordLog();
      pushUserRecord.setId(IdWorkerUtils.getId());
      pushUserRecord.setPushId(pushId);
      pushUserRecord.setPushToken(user.getDeviceId());
      pushUserRecord.setUserId(user.getUserId());
      pushUserRecord.setCreateTime(date);
      pushUserRecord.setUpdateTime(date);

      Boolean isSuccess = isSuccess(successTokens, failTokens, user);
      if (Objects.isNull(isSuccess)) {
        continue;
      }

      pushUserRecord.setSuccess(isSuccess);
      saveData.add(pushUserRecord);
    }

    List<List<SysPushUserRecordLog>> logList = Lists.partition(saveData, 200);
    logList.forEach(sysPushUserRecordLogService::saveBatch);
  }

  private Boolean isSuccess(List<String> successTokens, List<String> failTokens,
      UserLatestMobileDevicePushDTO user) {

    for (String successToken : successTokens) {
      if (Objects.equals(user.getDeviceId(), successToken)) {
        return Boolean.TRUE;
      }
    }

    for (String failToken : failTokens) {
      if (Objects.equals(user.getDeviceId(), failToken)) {
        return Boolean.FALSE;
      }
    }

    return null;
  }

  private void allPushFail(CreateRecordCmd createRecordParam,
      List<UserLatestMobileDevicePushDTO> users) {

    createRecordParam.setPushStatus(ResultStatusEnum.FAIL.name());
    createRecordParam.setFailQuantity(users.size());
    createRecordParam.setSuccessQuantity(0);
    addPushLog(createRecordParam);

    Timestamp date = TimestampUtils.now();

    List<SysPushUserRecordLog> logs = users.stream().map(user -> {

      SysPushUserRecordLog pushUserRecord = new SysPushUserRecordLog();
      pushUserRecord.setPushId(createRecordParam.getId());
      pushUserRecord.setPushToken(user.getDeviceId());
      pushUserRecord.setUserId(user.getUserId());
      pushUserRecord.setSuccess(Boolean.FALSE);
      pushUserRecord.setCreateTime(date);
      pushUserRecord.setUpdateTime(date);
      pushUserRecord.setCreateUser(createRecordParam.getCreateUser());
      return pushUserRecord;

    }).collect(Collectors.toList());

    List<List<SysPushUserRecordLog>> logList = Lists.partition(logs, 200);
    logList.forEach(sysPushUserRecordLogService::saveBatch);
  }

  private void addPushLog(CreateRecordCmd newPushDTO) {
    SysPushRecordLog sysPushRecordLog = newPushDTO.convert(SysPushRecordLog.class);
    sysPushRecordLog.setOrigin(PushOriginEnum.BACK.name());
    sysPushRecordLogService.save(sysPushRecordLog);
    newPushDTO.setId(sysPushRecordLog.getId());
  }

*/

}
