package com.red.circle.live.app.scheduler;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.red.circle.component.redis.service.RedisService;
import java.lang.reflect.Proxy;
import org.junit.Test;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

public class AgoraMicStateReconcileTaskRtcProviderTest {

  @Test
  public void trtcRoomShouldSkipAgoraReconcile() {
    assertFalse(task("TRTC").shouldReconcileAgoraRoom(1001026L));
  }

  @Test
  public void agoraRoomShouldKeepAgoraReconcile() {
    assertTrue(task("AGORA").shouldReconcileAgoraRoom(1001026L));
  }

  @Test
  public void unknownRoomProviderShouldKeepAgoraReconcile() {
    assertTrue(task(null).shouldReconcileAgoraRoom(1001026L));
  }

  private static AgoraMicStateReconcileTask task(String provider) {
    return new AgoraMicStateReconcileTask(
        redisService(provider),
        null,
        null,
        null,
        null,
        null);
  }

  private static RedisService redisService(String provider) {
    return new RedisService(new RedisTemplate<>() {
      @Override
      public ValueOperations<String, Object> opsForValue() {
        return valueOperations(provider);
      }
    });
  }

  @SuppressWarnings("unchecked")
  private static ValueOperations<String, Object> valueOperations(String provider) {
    return (ValueOperations<String, Object>) Proxy.newProxyInstance(
        ValueOperations.class.getClassLoader(),
        new Class<?>[] {ValueOperations.class},
        (proxy, method, args) -> {
          if ("get".equals(method.getName())) {
            return provider;
          }
          if ("toString".equals(method.getName())) {
            return "ValueOperations(" + provider + ")";
          }
          if ("hashCode".equals(method.getName())) {
            return System.identityHashCode(proxy);
          }
          if ("equals".equals(method.getName())) {
            return proxy == args[0];
          }
          throw new UnsupportedOperationException(method.getName());
        });
  }
}
