package cn.reghao.tnb.user.app.service;

import cn.reghao.jutil.jdk.web.db.PageList;
import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
import cn.reghao.tnb.auth.api.dto.AccountInfo;
import cn.reghao.tnb.auth.api.iface.AccountQuery;
import cn.reghao.tnb.auth.api.iface.AdminAccountService;
import cn.reghao.tnb.user.api.dto.UserInfo;
import cn.reghao.tnb.user.api.dto.UserSearch;
import cn.reghao.tnb.user.api.dto.VipPlanInfo;
import cn.reghao.tnb.user.api.dto.WalletChargeDto;
import cn.reghao.tnb.user.api.iface.UserWalletService;
import cn.reghao.tnb.user.app.db.mapper.UserProfileMapper;
import cn.reghao.tnb.user.app.model.po.UserProfile;
import cn.reghao.tnb.user.app.model.vo.VipPlan;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2024-07-06 11:22:17
 */
@Service
public class AdminUserService {
    @DubboReference(check = false, timeout = 60_000)
    private AdminAccountService adminAccountService;
    @DubboReference(check = false, retries = 0)
    private AccountQuery accountQuery;

    private int pageSize = 100;
    private final ExecutorService threadPool = ThreadPoolWrapper.threadPool("approve-charge-task", 1);
    private final UserWalletService userWalletService;
    private final UserVipService userVipService;
    private final UserProfileMapper userProfileMapper;

    public AdminUserService(UserWalletService userWalletService, UserVipService userVipService,
                            UserProfileMapper userProfileMapper) {
        this.userWalletService = userWalletService;
        this.userVipService = userVipService;
        this.userProfileMapper = userProfileMapper;
    }

    public Page<AccountInfo> getUserAccounts(String searchKey, PageRequest pageRequest) {
        int pageNumber = pageRequest.getPageNumber()+1;
        int pageSize = pageRequest.getPageSize();
        PageList<AccountInfo> pageList = adminAccountService.getByScreenName(searchKey, pageNumber, pageSize);
        return new PageImpl<>(pageList.getList(), pageRequest, pageList.getTotalSize());
    }

    public PageList<UserInfo> getUserList(UserSearch userSearch) {
        return PageList.empty();
    }

    public PageList<UserInfo> getUserList(int nextId) {
        int total = userProfileMapper.countAll();
        List<UserProfile> userProfileList = userProfileMapper.findAllById(pageSize, nextId);
        List<UserInfo> list = userProfileList.stream().map(this::getUserInfo).collect(Collectors.toList());
        if (!userProfileList.isEmpty()) {
            nextId = userProfileList.get(userProfileList.size()-1).getId();
        }

        return PageList.pageList(""+nextId, list);
    }

    private UserInfo getUserInfo(UserProfile userProfile) {
        long userId = userProfile.getUserId();
        AccountInfo accountInfo = accountQuery.getAccountInfo(userId);
        int gender = userProfile.getGender();
        String signature = userProfile.getSignature();
        int following = userProfile.getFollowing();
        int follower = userProfile.getFollower();
        boolean vip = userVipService.isVip(userId);
        String userIdStr = accountQuery.getUserIdStr(userId);
        UserInfo userInfo = new UserInfo(accountInfo, userIdStr, gender, signature, following, follower, vip);
        String username = accountInfo.getUsername();
        if (username.startsWith("bilibili_")) {
            long biliUserId = Long.parseLong(username.replace("bilibili_", ""));
            userInfo.setBiliUserId(biliUserId);
        }

        return userInfo;
    }

    public List<VipPlanInfo> getVipPlans() {
        List<VipPlan> list = userVipService.getVipPlans();
        return list.stream().map(this::getVipPlanInfo).collect(Collectors.toList());
    }

    private VipPlanInfo getVipPlanInfo(VipPlan vipPlan) {
        int planId = vipPlan.getPlanId();
        String name = vipPlan.getName();
        double price = vipPlan.getPrice();
        int duration = vipPlan.getDuration();
        return new VipPlanInfo(planId, name, price, duration);
    }

    public Long getUserId(String username) {
        AccountInfo accountInfo = accountQuery.getByUsername(username);
        if (accountInfo != null) {
            long userId = accountInfo.getUserId();
            return userId;
        }

        return null;
    }

    public List<WalletChargeDto> getChargeReqs() {
        return userWalletService.getChargeReqs();
    }

    public void approve(long chargeId) {
        userWalletService.approveCharge(chargeId);
    }

    public void approveAll() {
        threadPool.submit(new ApproveTask());
    }

    public void decline(long chargeId) {
        userWalletService.declineCharge(chargeId);
    }

    class ApproveTask implements Runnable {
        @Override
        public void run() {
            userWalletService.approveAllCharges();
        }
    }
}
