package com.red.circle.other.app.common.invite;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.red.circle.other.infra.config.InviteCampaignGoConfig;
import java.util.Objects;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@RequiredArgsConstructor
public class InviteCampaignGoClient {

  private final InviteCampaignGoConfig inviteCampaignGoConfig;

  public RegisterBindCodeResponse bindRegisterCode(RegisterBindCodeRequest request) {
    if (!inviteCampaignGoConfig.isEnabled()) {
      return null;
    }

    String baseUrl = Objects.toString(inviteCampaignGoConfig.getBaseUrl(), "").trim();
    if (baseUrl.isEmpty()) {
      log.warn("Invite campaign go baseUrl is blank, skip register bind. userId={}",
          request.getInviteeUserId());
      return null;
    }

    HttpResponse response = HttpUtil.createPost(trimRightSlash(baseUrl)
            + "/internal/invite-campaign/register-bind-code")
        .header("Content-Type", "application/json")
        .header("Accept", "application/json")
        .header("X-Internal-Token", Objects.toString(inviteCampaignGoConfig.getInternalToken(), ""))
        .timeout(Objects.requireNonNullElse(inviteCampaignGoConfig.getTimeoutMillis(), 10000))
        .body(JSON.toJSONString(request))
        .execute();

    String responseBody = response.body();
    if (response.getStatus() < 200 || response.getStatus() >= 300) {
      throw new IllegalStateException("Invite campaign go http error, status=" + response.getStatus()
          + ", body=" + responseBody);
    }
    if (responseBody == null || responseBody.trim().isEmpty()) {
      throw new IllegalStateException("Invite campaign go response is empty");
    }

    JSONObject root = JSON.parseObject(responseBody);
    if (root == null) {
      throw new IllegalStateException("Invite campaign go response is invalid");
    }
    if (root.containsKey("status") && !root.getBooleanValue("status")) {
      throw new IllegalStateException("Invite campaign go business error: " + root.getString("message"));
    }

    JSONObject body = root.getJSONObject("body");
    return Objects.nonNull(body)
        ? body.toJavaObject(RegisterBindCodeResponse.class)
        : root.toJavaObject(RegisterBindCodeResponse.class);
  }

  private String trimRightSlash(String value) {
    while (value.endsWith("/")) {
      value = value.substring(0, value.length() - 1);
    }
    return value;
  }

  @Data
  @Accessors(chain = true)
  public static class RegisterBindCodeRequest {
    private String inviteCode;
    private String sysOrigin;
    private Long inviteeUserId;
    private String clientIp;
    private String deviceFingerprint;
  }

  @Data
  @Accessors(chain = true)
  public static class RegisterBindCodeResponse {
    private Long relationId;
    private Boolean eligible;
    private String blockReason;
    private Long inviterUserId;
    private String inviteCode;
  }
}
