package com.red.circle.console.infra.framework.convert;

import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.inner.endpoint.live.RoomManagerClient;
import com.red.circle.other.inner.model.dto.live.RoomProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.parse.DataTypeUtils;
import com.red.circle.tool.core.regex.RegexConstant;
import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

/**
 * @author pengliang on 2022/8/19
 */
@Component
@RequiredArgsConstructor
public class AccountLongSearchConvert implements Converter<String, Long> {

  private final UserProfileClient userProfileClient;
  private final RoomManagerClient roomManagerClient;

  /**
   * [type:val,sysOrigin:val,accountType:val,content:val]
   */
  @Override
  public Long convert(String source) {
    if (StringUtils.isBlank(source)) {
      return null;
    }

    boolean isAccountSearch = source.startsWith("*") && source.endsWith("*")
        && source.contains("content:");

    if (!isAccountSearch) {
      return DataTypeUtils.toLong(source);
    }

    return getAccountSearchId(source);
  }

  private Long returnNotFound() {
    return -1L;
  }

  private Long getAccountSearchId(String source) {

    Map<String, String> params = convertMap(source.replaceAll("\\*", ""));
    if (CollectionUtils.isEmpty(params)) {
      return returnNotFound();
    }

    String type = params.get("type");
    String sysOrigin = params.get("sysOrigin");
    String accountType = params.get("accountType");
    String content = params.get("content");

    if (StringUtils.isBlanks(type, accountType, content)) {
      return returnNotFound();
    }

    if (Objects.equals(accountType, "SHORT") && StringUtils.isBlank(sysOrigin)) {
      return returnNotFound();
    }

    if (Objects.equals(accountType, "LONG")) {
      if (!content.matches(RegexConstant.NUMBER)) {
        return returnNotFound();
      }
      return Long.parseLong(content);
    }

    if (Objects.equals(type, "USER") && Objects.equals(accountType, "SHORT")) {
      return Optional.ofNullable(userProfileClient.getByAccount(sysOrigin,
              content))
          .map(response -> Objects.nonNull(response.getBody())
              ? response.getBody().getId()
              : null)
          .orElseGet(this::returnNotFound);
    }

    if (Objects.equals(type, "ROOM") && Objects.equals(accountType, "SHORT")) {
      return Optional.ofNullable(userProfileClient.getByAccount(sysOrigin,
              content))
          .map(userResponse -> {

            if (Objects.isNull(userResponse.getBody())) {
              return returnNotFound();
            }

            ResultResponse<RoomProfileDTO> roomResponse = roomManagerClient.getProfileByUserId(
                userResponse.getBody().getId());

            if (Objects.isNull(roomResponse.getBody())) {
              return returnNotFound();
            }

            RoomProfileDTO roomProfile = roomResponse.getBody();
            if (Objects.isNull(roomProfile)) {
              return returnNotFound();
            }

            return roomProfile.getId();
          }).orElseGet(this::returnNotFound);
    }
    return returnNotFound();
  }

  /**
   * 转换map.
   *
   * @param source type:val,sysOrigin:val,accountType:val,content:val
   */
  private Map<String, String> convertMap(String source) {

    if (StringUtils.isBlank(source)) {
      return CollectionUtils.newHashMap();
    }

    List<String> values = Arrays.stream(source.split(",")).filter(StringUtils::isNotBlank)
        .collect(Collectors.toList());

    if (CollectionUtils.isEmpty(values)) {
      return CollectionUtils.newHashMap();
    }

    Map<String, String> result = CollectionUtils.newHashMap();
    for (String value : values) {
      List<String> keyVal = Arrays.stream(value.split(":")).filter(StringUtils::isNotBlank)
          .collect(Collectors.toList());
      if (CollectionUtils.isEmpty(keyVal) || keyVal.size() != 2) {
        continue;
      }
      result.put(keyVal.get(0), keyVal.get(1));
    }
    return result;
  }

}
