import com.red.circle.OtherServiceApplication;
import com.red.circle.common.business.enums.ConsoleAccountStatusEnum;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.app.dto.h5.UserIdentityVO;
import com.red.circle.other.app.service.user.user.AppUserDataViolationService;
import com.red.circle.other.infra.database.rds.entity.sys.Administrator;
import com.red.circle.other.infra.database.rds.service.sys.AdministratorAuthService;
import com.red.circle.other.infra.database.rds.service.sys.AdministratorService;
import com.red.circle.other.inner.endpoint.team.bd.BdTeamInfoClient;
import com.red.circle.other.inner.endpoint.team.bd.BdTeamLeaderClient;
import com.red.circle.other.inner.endpoint.team.target.TeamProfileClient;
import com.red.circle.other.inner.enums.sys.appmanager.RoomRolesEnum;
import com.red.circle.other.inner.enums.team.TeamMemberRole;
import com.red.circle.other.inner.model.cmd.user.ApprovalAccountCmd;
import com.red.circle.other.inner.model.dto.agency.agency.TeamMemberDTO;
import com.red.circle.wallet.inner.endpoint.freight.FreightGoldClient;
import dto.BanResultDTO;
import dto.DeviceFingerprintDTO;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import util.ExcelUtil;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@SpringBootTest(classes = OtherServiceApplication.class)
@RunWith(SpringRunner.class)
public class UserDataViolationTest {

  @Autowired
  private AppUserDataViolationService userDataViolationService;
  @Autowired
  private TeamProfileClient teamProfileClient;
  @Autowired
  private FreightGoldClient freightGoldClient;
  @Autowired
  private BdTeamInfoClient bdTeamInfoClient;
  @Autowired
  private AdministratorService administratorService;
  @Autowired
  private AdministratorAuthService administratorAuthService;
  @Autowired
  private BdTeamLeaderClient bdTeamLeaderClient;

  /**
   * 测试 Excel 导入功能
   * 读取从数据库导出的设备指纹数据
   */
  @Test
  public void testImportDeviceFingerprint() {
    // TODO: 修改为你实际的 Excel 文件路径
    String inputFilePath = "C:\\Users\\Administrator\\Documents\\DataGripSql\\11.11同设备指纹用户统计英文版.xlsx";
    
    try {
      List<DeviceFingerprintDTO> dataList = ExcelUtil.importDeviceFingerprint(inputFilePath);
      
      log.info("==================== 导入测试结果 ====================");
      log.info("总共导入 {} 条设备指纹数据", dataList.size());
      
      // 打印前 5 条数据作为示例
      int displayCount = Math.min(5, dataList.size());
      log.info("显示前 {} 条数据：", displayCount);
      
      for (int i = 0; i < displayCount; i++) {
        DeviceFingerprintDTO dto = dataList.get(i);
        log.info("数据 {}: 设备指纹={}, 用户数={}, 用户IDs={}", 
            i + 1, 
            dto.getDeviceFingerprint(), 
            dto.getUserCount(), 
            dto.getUserIds());
      }
      
      log.info("==================================================");
      
    } catch (Exception e) {
      log.error("导入测试失败", e);
    }
  }

  /**
   * 测试 Excel 导出功能
   * 生成示例封禁结果数据并导出
   */
  @Test
  public void testExportBanResults() {
    // 创建示例数据
    List<BanResultDTO> results = new ArrayList<>();
    
    // 示例1：被封禁的用户
    BanResultDTO banned = new BanResultDTO();
    banned.setUserId(1954059793963393025L);
    banned.setDeviceFingerprint("iOS|iPhone 14|192.168.1.100");
    banned.setUserIdentity("主播");
    banned.setBanned("是");
    banned.setReason("同设备指纹下存在多个主播");
    banned.setStatus("封禁成功");
    banned.setRemark("设备指纹下共2个主播");
    results.add(banned);
    
    // 示例2：不封禁的用户（管理员）
    BanResultDTO notBanned1 = new BanResultDTO();
    notBanned1.setUserId(1000000000000000001L);
    notBanned1.setDeviceFingerprint("Android|Xiaomi 13|192.168.1.101");
    notBanned1.setUserIdentity("超级管理员");
    notBanned1.setBanned("否");
    notBanned1.setReason("管理员身份，不封禁");
    notBanned1.setStatus("跳过");
    notBanned1.setRemark("-");
    results.add(notBanned1);
    
    // 示例3：不封禁的用户（非主播）
    BanResultDTO notBanned2 = new BanResultDTO();
    notBanned2.setUserId(2000000000000000001L);
    notBanned2.setDeviceFingerprint("iOS|iPhone 15|192.168.1.102");
    notBanned2.setUserIdentity("普通用户");
    notBanned2.setBanned("否");
    notBanned2.setReason("非主播身份，不封禁");
    notBanned2.setStatus("跳过");
    notBanned2.setRemark("-");
    results.add(notBanned2);
    
    // TODO: 修改为你想要保存的文件路径
    String outputFilePath = "D:\\ban_results_test.xlsx";
    
    try {
      ExcelUtil.exportBanResults(results, outputFilePath);
      
      log.info("==================== 导出测试结果 ====================");
      log.info("成功导出 {} 条封禁结果数据", results.size());
      log.info("导出文件路径: {}", outputFilePath);
      log.info("请打开 Excel 文件检查导出结果");
      log.info("==================================================");
      
    } catch (Exception e) {
      log.error("导出测试失败", e);
    }
  }

  @Test
  public void testUnBanUsers() {
    String inputFilePath = "C:\\Users\\Administrator\\Documents\\DataGripSql\\11.11同设备指纹用户统计英文版 - 副本.xlsx";
    String outputFilePath = "D:\\ban_results_" + System.currentTimeMillis() + ".xlsx";
    List<DeviceFingerprintDTO> deviceData = ExcelUtil.importDeviceFingerprint(inputFilePath);

    for (DeviceFingerprintDTO device : deviceData) {
      List<Long> userIds = parseUserIds(device.getUserIds());
      for (Long userId : userIds) {

        if (userId == 1963790037740466178L) {
          System.out.println();
        }
        // 执行解封
        ApprovalAccountCmd cmd = new ApprovalAccountCmd();
        cmd.setAccountStatusEnum(ConsoleAccountStatusEnum.UNTIE_DEVICE_AND_ACCOUNT);
        cmd.setDescription("1");
        cmd.setBeApprovalUserId(userId);
        cmd.setReqUserId(userId);

        userDataViolationService.updateAccountStatus(cmd);
      }
    }

  }

  /**
   * 批量用户封禁（完整流程）
   * 1. 导入设备指纹数据
   * 2. 判断用户身份
   * 3. 执行封禁操作
   * 4. 导出封禁结果
   */
  @Test
  public void batchBanUsers() {
    // TODO: 修改为你实际的文件路径
    String inputFilePath = "C:\\Users\\Administrator\\Documents\\DataGripSql\\11.11同设备指纹用户统计英文版.xlsx";
    String outputFilePath = "D:\\ban_results_" + System.currentTimeMillis() + ".xlsx";
    
    try {
      log.info("==================== 开始批量封禁流程 ====================");
      
      // 步骤1: 导入设备指纹数据
      log.info("步骤1: 导入设备指纹数据...");
      List<DeviceFingerprintDTO> deviceData = ExcelUtil.importDeviceFingerprint(inputFilePath);
      log.info("成功导入 {} 条设备指纹数据", deviceData.size());
      
      // 步骤2: 处理每个设备指纹的用户
      log.info("步骤2: 开始处理用户封禁逻辑...");
      List<BanResultDTO> allResults = new ArrayList<>();
      
      int processedCount = 0;
      for (DeviceFingerprintDTO device : deviceData) {
        processedCount++;
        log.info("处理进度: {}/{} - 设备指纹: {}", processedCount, deviceData.size(), device.getDeviceFingerprint());
        
        // 解析用户ID列表
        List<Long> userIds = parseUserIds(device.getUserIds());
        log.info("  该设备指纹下有 {} 个用户", userIds.size());
        
        // 判断该设备指纹下的主播数量
        List<Long> anchorUserIds = new ArrayList<>();
        Map<Long, UserIdentityVO> identityMap = new HashMap<>();
        
        for (Long userId : userIds) {
          try {
            UserIdentityVO identity = getUserIdentity(userId);
            identityMap.put(userId, identity);
            
            // 如果是主播，加入主播列表
            if (Boolean.TRUE.equals(identity.getAnchor())) {
              anchorUserIds.add(userId);
            }
          } catch (Exception e) {
            log.error("  获取用户 {} 身份失败", userId, e);
          }
        }
        
        log.info("  该设备指纹下有 {} 个主播", anchorUserIds.size());
        
        // 处理每个用户
        for (Long userId : userIds) {
          BanResultDTO result = processUser(userId, device, identityMap.get(userId), anchorUserIds.size());
          allResults.add(result);
        }
      }
      
      // 步骤3: 导出结果
      log.info("步骤3: 导出封禁结果...");
      ExcelUtil.exportBanResults(allResults, outputFilePath);
      
      // 步骤4: 统计结果
      log.info("==================== 封禁流程完成 ====================");
      long bannedCount = allResults.stream().filter(r -> "是".equals(r.getBanned())).count();
      long skippedCount = allResults.stream().filter(r -> "否".equals(r.getBanned())).count();
      long successCount = allResults.stream().filter(r -> "封禁成功".equals(r.getStatus())).count();
      long failedCount = allResults.stream().filter(r -> "封禁失败".equals(r.getStatus())).count();
      
      log.info("总处理用户数: {}", allResults.size());
      log.info("封禁用户数: {}", bannedCount);
      log.info("跳过用户数: {}", skippedCount);
      log.info("封禁成功数: {}", successCount);
      log.info("封禁失败数: {}", failedCount);
      log.info("结果文件路径: {}", outputFilePath);
      log.info("====================================================");
      
    } catch (Exception e) {
      log.error("批量封禁流程失败", e);
    }
  }

  /**
   * 处理单个用户
   */
  private BanResultDTO processUser(Long userId, DeviceFingerprintDTO device, 
                                    UserIdentityVO identity, int anchorCount) {
    BanResultDTO result = new BanResultDTO();
    result.setUserId(userId);
    result.setDeviceFingerprint(device.getDeviceFingerprint());
    
    // 如果获取身份失败
    if (identity == null) {
      result.setUserIdentity("未知");
      result.setBanned("否");
      result.setReason("获取用户身份失败");
      result.setStatus("跳过");
      result.setRemark("身份查询异常");
      return result;
    }
    
    // 设置用户身份描述
    result.setUserIdentity(buildIdentityDescription(identity));
    
    // 判断是否需要封禁
    boolean shouldBan = shouldBanUser(identity, anchorCount);
    
    if (!shouldBan) {
      result.setBanned("否");
      result.setReason(getSkipReason(identity, anchorCount));
      result.setStatus("跳过");
      result.setRemark(String.format("设备指纹下共%d个用户，%d个主播", device.getUserCount(), anchorCount));
      return result;
    }
    
    // 需要封禁，执行封禁操作
    result.setBanned("是");
    result.setReason(String.format("设备指纹下存在%d个主播，符合封禁条件", anchorCount));
    result.setRemark(String.format("设备指纹下共%d个用户，%d个主播", device.getUserCount(), anchorCount));
    
    try {
      // 执行封禁
      ApprovalAccountCmd cmd = new ApprovalAccountCmd();
      cmd.setAccountStatusEnum(ConsoleAccountStatusEnum.ARCHIVE);
      cmd.setDescription("Multi-device fingerprint blocking");
      cmd.setBeApprovalUserId(userId);
      cmd.setReqUserId(userId);
      cmd.setDays(365);
      
      userDataViolationService.updateAccountStatus(cmd);
      
      result.setStatus("封禁成功");
      log.info("  用户 {} 封禁成功", userId);
      
    } catch (Exception e) {
      result.setStatus("封禁失败");
      result.setRemark(result.getRemark() + " | 错误: " + e.getMessage());
      log.error("  用户 {} 封禁失败", userId, e);
    }
    
    return result;
  }

  /**
   * 判断是否应该封禁用户
   * 封禁条件：同设备指纹下存在2个及以上主播，且该用户是主播
   * 不封禁条件：
   * 1. 超级管理员
   * 2. 管理员
   * 3. BD Leader
   * 4. BD
   * 5. 金币代理（FreightAgent）
   * 6. 不是主播
   */
  private boolean shouldBanUser(UserIdentityVO identity, int anchorCount) {
    // 条件1: 设备指纹下必须有2个及以上主播
    if (anchorCount < 2) {
      return false;
    }
    
    // 条件2: 该用户必须是主播
    if (!Boolean.TRUE.equals(identity.getAnchor())) {
      return false;
    }
    
    // 条件3: 排除特殊身份用户
    if (Boolean.TRUE.equals(identity.getSuperAdmin())) {
      return false; // 超级管理员不封禁
    }
    
    if (Boolean.TRUE.equals(identity.getAdmin())) {
      return false; // 管理员不封禁
    }
    
    if (Boolean.TRUE.equals(identity.getBdLeader())) {
      return false; // BD Leader 不封禁
    }
    
    if (Boolean.TRUE.equals(identity.getBd())) {
      return false; // BD 不封禁
    }
    
    if (Boolean.TRUE.equals(identity.getFreightAgent()) || Boolean.TRUE.equals(identity.getSuperFreightAgent())) {
      return false; // 金币代理不封禁
    }
    
    // 通过所有检查，应该封禁
    return true;
  }

  /**
   * 获取跳过原因
   */
  private String getSkipReason(UserIdentityVO identity, int anchorCount) {
    if (anchorCount < 2) {
      return "设备指纹下主播数量不足2个";
    }
    
    if (!Boolean.TRUE.equals(identity.getAnchor())) {
      return "用户不是主播";
    }
    
    if (Boolean.TRUE.equals(identity.getSuperAdmin())) {
      return "超级管理员身份，不封禁";
    }
    
    if (Boolean.TRUE.equals(identity.getAdmin())) {
      return "管理员身份，不封禁";
    }
    
    if (Boolean.TRUE.equals(identity.getBdLeader())) {
      return "BD Leader 身份，不封禁";
    }
    
    if (Boolean.TRUE.equals(identity.getBd())) {
      return "BD 身份，不封禁";
    }
    
    if (Boolean.TRUE.equals(identity.getFreightAgent()) || Boolean.TRUE.equals(identity.getSuperFreightAgent())) {
      return "金币代理身份，不封禁";
    }
    
    return "其他原因";
  }

  /**
   * 构建用户身份描述
   */
  private String buildIdentityDescription(UserIdentityVO identity) {
    List<String> identities = new ArrayList<>();
    
    if (Boolean.TRUE.equals(identity.getSuperAdmin())) {
      identities.add("超级管理员");
    }
    if (Boolean.TRUE.equals(identity.getAdmin())) {
      identities.add("管理员");
    }
    if (Boolean.TRUE.equals(identity.getManager())) {
      identities.add("经理");
    }
    if (Boolean.TRUE.equals(identity.getBdLeader())) {
      identities.add("BD Leader");
    }
    if (Boolean.TRUE.equals(identity.getBd())) {
      identities.add("BD");
    }
    if (Boolean.TRUE.equals(identity.getAgent())) {
      identities.add("代理");
    }
    if (Boolean.TRUE.equals(identity.getAnchor())) {
      identities.add("主播");
    }
    if (Boolean.TRUE.equals(identity.getSuperFreightAgent())) {
      identities.add("超级金币代理");
    }
    if (Boolean.TRUE.equals(identity.getFreightAgent())) {
      identities.add("金币代理");
    }
    
    if (identities.isEmpty()) {
      return "普通用户";
    }
    
    return String.join(", ", identities);
  }

  /**
   * 解析用户ID字符串（逗号分隔）
   */
  private List<Long> parseUserIds(String userIdsStr) {
    if (userIdsStr == null || userIdsStr.trim().isEmpty()) {
      return new ArrayList<>();
    }
    
    return Arrays.stream(userIdsStr.split(","))
        .map(String::trim)
        .filter(s -> !s.isEmpty())
        .map(Long::parseLong)
        .collect(Collectors.toList());
  }

  /**
   * 单个用户封禁测试
   */
  @Test
  public void updateUserDataViolation() {
    Long userId = 1954059793963393025L;
    ApprovalAccountCmd cmd = new ApprovalAccountCmd();
    cmd.setAccountStatusEnum(ConsoleAccountStatusEnum.ARCHIVE_DEVICE);
    cmd.setDescription("Multi-device fingerprint blocking");
    cmd.setBeApprovalUserId(userId);
    cmd.setReqUserId(userId);
    userDataViolationService.updateAccountStatus(cmd);
  }

  /**
   * 获取用户身份信息
   */
  public UserIdentityVO getUserIdentity(Long userId) {
    TeamMemberDTO teamMember = ResponseAssert.requiredSuccess(
        teamProfileClient.getByMemberId(userId));

    Administrator administrator = administratorService.getByUserId(userId);
    boolean isValidAdmin = administrator != null && Boolean.TRUE.equals(administrator.getStatus());

    boolean isSuperAdmin = isValidAdmin && Optional.of(administrator)
        .map(e -> RoomRolesEnum.MANAGER.eq(e.getRoles()) || RoomRolesEnum.SUPER_ADMIN.eq(e.getRoles()))
        .orElse(Boolean.FALSE);
    boolean isManager = isValidAdmin && Optional.of(administrator)
        .map(e -> RoomRolesEnum.MANAGER.eq(e.getRoles()))
        .orElse(Boolean.FALSE);

    return new UserIdentityVO()
        .setAgent(Objects.nonNull(teamMember) && TeamMemberRole.OWN.eq(teamMember.getRole()))
        .setAnchor(Objects.nonNull(teamMember))
        .setBd(ResponseAssert.requiredSuccess(bdTeamInfoClient.check(userId)))
        .setFreightAgent(ResponseAssert.requiredSuccess(freightGoldClient.checkFreightAgent(userId)))
        .setSuperFreightAgent(ResponseAssert.requiredSuccess(freightGoldClient.checkSuperFreightAgent(userId)))
        .setSuperAdmin(isSuperAdmin)
        .setAdmin(isValidAdmin)
        .setBdLeader(ResponseAssert.requiredSuccess(bdTeamLeaderClient.check(userId)))
        .setManager(isManager)
        ;
  }

}
