package com.izouma.nineth.service;

import com.github.binarywang.wxpay.exception.WxPayException;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.model.Payment;
import com.izouma.nineth.ApplicationTests;
import com.izouma.nineth.TokenHistory;
import com.izouma.nineth.domain.*;
import com.izouma.nineth.dto.UserBankCard;
import com.izouma.nineth.enums.AssetStatus;
import com.izouma.nineth.enums.AuthStatus;
import com.izouma.nineth.enums.AuthorityName;
import com.izouma.nineth.enums.OrderStatus;
import com.izouma.nineth.repo.*;
import com.izouma.nineth.security.Authority;
import com.izouma.nineth.utils.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.collections.MapUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
public class OrderServiceTest extends ApplicationTests {
    @Autowired
    private OrderService     orderService;
    @Autowired
    private OrderRepo        orderRepo;
    @Autowired
    private AssetRepo        assetRepo;
    @Autowired
    private TokenHistoryRepo tokenHistoryRepo;
    @Autowired
    private AssetService     assetService;
    @Autowired
    private CollectionRepo   collectionRepo;
    @Autowired
    private UserRepo         userRepo;
    @Autowired
    private IdentityAuthRepo identityAuthRepo;
    @Autowired
    private UserBankCardRepo userBankCardRepo;

    @Test
    public void create() throws EncoderException, WxPayException {
        Order order = orderService.create(1110L, 1777L, 1, null, 1896L, null);
        assert order.getStatus() == OrderStatus.FINISH;
    }

    @Test
    public void setNumber() {
        orderService.setNumber();
    }

    @Test
    public void setSales() {
        orderService.setSales();
    }

    @Test
    public void commission() {
        orderService.commission(orderRepo.findById(4437L).get());
    }

    @Test
    public void refund() throws WxPayException {
        orderService.refund(4627L);
    }

    @Test
    public void cancel() {
        orderService.cancel(6721L);
    }

    @Test
    public void fixNotPaid() throws BaseAdaPayException {
        List<Order> errOrders = new ArrayList<>();
        orderRepo.findByStatus(OrderStatus.FINISH).stream().parallel().forEach(order -> {
            if (order.getCreatedAt().isAfter(LocalDateTime.of(2021, 11, 30, 1, 1))) {
                try {
                    Map<String, Object> res = Payment.query(order.getTransactionId());
                    String status = MapUtils.getString(res, "status");
                    String errMsg = MapUtils.getString(res, "error_msg");
                    if (!"succeeded".equals(status) && !"对应支付记录不存在".equals(errMsg)) {
                        System.out.println(order.getId());
                        errOrders.add(order);
                    }
                } catch (Exception e) {
                }
            }
        });

        System.out.println(errOrders.stream().map(o -> o.getId().toString()).collect(Collectors.joining(",")));


        for (Order errOrder : errOrders) {
            Collection collection = collectionRepo.findById(errOrder.getCollectionId()).orElse(null);
            if (collection == null) continue;
            List<Asset> assets = assetRepo.findByOrderId(errOrder.getId());
            for (Asset asset : assets) {
                if (asset.getStatus() == AssetStatus.NORMAL) {
                    if (asset.isPublicShow()) {
                        assetService.cancelPublic(asset);
                    }
                    tokenHistoryRepo.deleteByTokenId(asset.getTokenId());
                    assetRepo.delete(asset);
                }
            }
            orderRepo.delete(errOrder);
            collection.setStock(collection.getStock() + 1);
            collection.setSale(collection.getSale() - 1);
            collectionRepo.save(collection);
        }
    }

    @Test
    public void fixTokenHistory() {
        for (TokenHistory tokenHistory : tokenHistoryRepo.findError()) {
            List<Asset> assets = assetRepo.findByTokenIdOrderByCreatedAt(tokenHistory.getTokenId());
            if (assets.size() == 2) {
                userRepo.findById(assets.get(0).getUserId()).ifPresent(fromUser -> {
                    tokenHistory.setFromUserId(assets.get(0).getUserId());
                    tokenHistory.setFromUser(fromUser.getNickname());
                    tokenHistory.setFromAvatar(fromUser.getAvatar());
                    tokenHistoryRepo.save(tokenHistory);
                });
            }
        }
    }

    @Test
    public void fixPay() {
        String s = "\n订单ID\t金额\t手续费\t版税\t收款用户ID\t收款人\t银行卡号\t银行";
        for (Long orderId : new Long[]{5417L, 5919L, 5923L, 8166L}) {
            try {
                Order order = orderRepo.findById(orderId).get();
                List<Asset> assets = assetRepo.findByTokenIdOrderByCreatedAt(assetRepo.findById(order.getAssetId())
                        .get()
                        .getTokenId());
                Asset asset = assets.stream().filter(a -> a.getStatus() == AssetStatus.TRANSFERRED).findAny().get();
                User user = userRepo.findById(asset.getUserId()).get();
                Optional<IdentityAuth> identityAuth = identityAuthRepo.findByUserIdAndDelFalse(user.getId()).stream()
                        .filter(i -> i.getStatus() == AuthStatus.SUCCESS).findAny();
                Optional<UserBankCard> bankCard = userBankCardRepo.findByUserId(user.getId()).stream().findAny();
                s += "\n"
                        + orderId + "\t"
                        + order.getTotalPrice().subtract(order.getGasPrice()) + "\t"
                        + order.getServiceCharge() + "\t"
                        + order.getRoyalties() + "\t"
                        + user.getId() + "\t"
                        + identityAuth.map(IdentityAuth::getRealName).orElse("") + "\t"
                        + bankCard.map(UserBankCard::getBankNo).orElse("") + "\t"
                        + bankCard.map(UserBankCard::getBankName).orElse("");
            } catch (Exception e) {

            }

        }
        log.info(s);
    }

    @Test
    public void consignmentFix() throws IOException {
        String s = FileUtils.readFile("/Users/drew/Downloads/app.log").replaceAll("</p>\n", "</p>");
        String[] arr = s.split("\n");
        for (int i = 0; i < arr.length; i++) {
            if (arr[i].contains("insert into collection_info")) {
//                arr[i][2]
            }
        }
    }

    @Test
    public void test() {
        userRepo.findByAuthoritiesContains(Authority.get(AuthorityName.ROLE_MINTER));
    }
}