package com.bizzan.bitrade.controller.authno;

import com.bizzan.bitrade.constant.MemberLevelEnum;
import com.bizzan.bitrade.entity.Country;
import com.bizzan.bitrade.entity.Location;
import com.bizzan.bitrade.entity.Member;
import com.bizzan.bitrade.event.MemberEvent;
import com.bizzan.bitrade.service.MemberService;
import com.bizzan.bitrade.service.FollowWalletService;
import com.bizzan.bitrade.util.IdWorkByTwitter;
import com.bizzan.bitrade.util.Md5;
import com.bizzan.bitrade.util.MessageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 批量注册测试会员（无需登录），仅用于跟单交易测试
 */
@RestController
@RequestMapping("noauth/batch-register")
@Slf4j
public class BatchRegisterController {

    @Autowired
    private MemberService memberService;

    @Autowired
    private MemberEvent memberEvent;

    @Autowired
    private IdWorkByTwitter idWorkByTwitter;

    @Autowired
    private FollowWalletService followWalletService;

    @Value("${member.default.avatar-url:}")
    private String defaultAvatarUrl;

    /**
     * 批量注册会员
     *
     * @param prefix      用户名/邮箱前缀，如 "test" 生成 test001@domain, test002@domain...
     * @param count       生成数量，最大 200
     * @param password    统一登录密码（明文，返回结果中也会回显）
     * @param emailDomain 邮箱域名，默认 test.com
     * @param promotionCode 邀请人推广码（可选）
     */
    @PostMapping("create")
    public MessageResult create(
            @RequestParam String prefix,
            @RequestParam(defaultValue = "10") int count,
            @RequestParam String password,
            @RequestParam(defaultValue = "test.com") String emailDomain,
            @RequestParam(required = false) String promotionCode
    ) {
        if (count < 1 || count > 2000) {
            return MessageResult.error("count 范围 1~2000");
        }
        if (prefix == null || prefix.trim().isEmpty()) {
            return MessageResult.error("prefix 不能为空");
        }
        prefix = prefix.trim().toLowerCase();

        // 验证邀请人推广码
        String inviterPromoCode = null;
        if (promotionCode != null && !promotionCode.trim().isEmpty()) {
            Member inviter = memberService.findMemberByPromotionCode(promotionCode.trim());
            if (inviter == null) {
                return MessageResult.error("邀请人推广码不存在: " + promotionCode);
            }
            inviterPromoCode = inviter.getPromotionCode();
        }

        List<Map<String, Object>> created = new ArrayList<>();
        List<String> skipped = new ArrayList<>();
        Random random = new Random();

        for (int i = 1; i <= count; i++) {
            String seq = String.format("%03d", i);
            String username = prefix + seq;
            String email = username + "@" + emailDomain;

            if (memberService.usernameIsExist(email)) {
                skipped.add(email);
                continue;
            }

            try {
                String loginNo = String.valueOf(idWorkByTwitter.nextId());
                String credentialsSalt = ByteSource.Util.bytes(loginNo).toHex();
                String encryptedPassword = Md5.md5Digest(password + credentialsSalt).toLowerCase();

                Member member = new Member();
                member.setMemberLevel(MemberLevelEnum.GENERAL);
                Location location = new Location();
                location.setCountry("中国");
                member.setLocation(location);
                Country country = new Country();
                country.setZhName("中国");
                member.setCountry(country);
                member.setUsername(email);
                member.setPassword(encryptedPassword);
                member.setEmail(email);
                member.setSalt(credentialsSalt);
                member.setAvatar(defaultAvatarUrl);
                member.setPromotionCode(generateUniquePromotionCode());

                Member saved = memberService.save(member);
                memberEvent.onRegisterSuccess(saved, inviterPromoCode);

                BigDecimal rechargeAmount = BigDecimal.valueOf(1000 + random.nextInt(3001));
                followWalletService.findOne(saved.getId());
                followWalletService.increaseBalance(saved.getId(), rechargeAmount);

                Map<String, Object> info = new HashMap<>();
                info.put("id", saved.getId());
                info.put("username", email);
                info.put("email", email);
                info.put("password", password);
                info.put("promotionCode", saved.getPromotionCode());
                info.put("followBalance", rechargeAmount);
                created.add(info);

                log.info("批量注册：创建会员 {}", email);
            } catch (Exception e) {
                log.error("批量注册：创建会员 {} 失败", email, e);
                skipped.add(email + "(error: " + e.getMessage() + ")");
            }
        }

        Map<String, Object> result = new HashMap<>();
        result.put("created", created);
        result.put("createdCount", created.size());
        result.put("skipped", skipped);
        result.put("skippedCount", skipped.size());

        return MessageResult.success("批量注册完成", result);
    }

    private String generateUniquePromotionCode() {
        String seed = "0123456789AB";
        Random random = new Random();
        for (int attempt = 0; attempt < 100; attempt++) {
            StringBuilder code = new StringBuilder();
            for (int i = 0; i < 4; i++) {
                code.append(seed.charAt(random.nextInt(10)));
            }
            String candidate = code.toString();
            if (memberService.findMemberByPromotionCode(candidate) == null) {
                return candidate;
            }
        }
        // fallback: use timestamp suffix
        return String.valueOf(System.currentTimeMillis() % 10000);
    }
}
