package com.izouma.nineth;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.huifu.adapay.model.Refund;
import com.izouma.nineth.domain.Asset;
import com.izouma.nineth.domain.Collection;
import com.izouma.nineth.domain.Order;
import com.izouma.nineth.domain.TokenHistory;
import com.izouma.nineth.enums.AssetStatus;
import com.izouma.nineth.enums.CollectionSource;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.AssetRepo;
import com.izouma.nineth.repo.CollectionRepo;
import com.izouma.nineth.repo.OrderRepo;
import com.izouma.nineth.repo.TokenHistoryRepo;
import com.izouma.nineth.utils.SnowflakeIdWorker;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.io.IOException;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class FixOverSale extends ApplicationTests {
    @Autowired
    private OrderRepo         orderRepo;
    @Autowired
    private AssetRepo         assetRepo;
    @Autowired
    private TokenHistoryRepo  tokenHistoryRepo;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private CollectionRepo    collectionRepo;

    @Test
    public void fix() throws IOException {
        List<Asset> assets = assetRepo.findOverNumber();
        List<Order> successOrders = new ArrayList<>();
        List<Asset> successAssets = new ArrayList<>();
        List<TokenHistory> successHistory = new ArrayList<>();
        List<Order> error = new ArrayList<>();
        assets.parallelStream().forEach(asset -> {
            Order order = null;
            if (asset.getOrderId() != null) {
                order = orderRepo.findById(asset.getOrderId()).orElse(null);
            }
            if (order != null && order.getSource() == CollectionSource.OFFICIAL
                    && asset.getStatus() == AssetStatus.NORMAL) {
                System.out.println(order.getTransactionId());
                try {
                    Map<String, Object> refundParams = new HashMap<>();
                    refundParams.put("refund_amt", order.getTotalPrice()
                            .setScale(2, RoundingMode.HALF_UP)
                            .toPlainString());
                    refundParams.put("refund_order_no", snowflakeIdWorker.nextId() + "");
                    Map<String, Object> response = Refund.create(order.getTransactionId(), refundParams);
                    System.out.println(JSON.toJSONString(response, SerializerFeature.PrettyFormat));
                    if (StringUtils.isEmpty(MapUtils.getString(response, "id"))) {
                        throw new BusinessException("err");
                    }
                    successOrders.add(order);
                    successAssets.add(asset);
                    successHistory.addAll(tokenHistoryRepo.findByTokenIdOrderByCreatedAtDesc(asset.getTokenId()));
                    collectionRepo.deleteByAssetId(asset.getId());
                    assetRepo.delete(asset);
                    orderRepo.delete(order);
                    tokenHistoryRepo.deleteByTokenId(asset.getTokenId());
                } catch (Exception e) {
                    error.add(order);
                }
            }
        });
        FileUtils.write(new File("/Users/drew/Desktop/0301Fix/success_orders.json"),
                JSON.toJSONString(successOrders, SerializerFeature.PrettyFormat), StandardCharsets.UTF_8);
        FileUtils.write(new File("/Users/drew/Desktop/0301Fix/success_assets.json"),
                JSON.toJSONString(successAssets, SerializerFeature.PrettyFormat), StandardCharsets.UTF_8);
        FileUtils.write(new File("/Users/drew/Desktop/0301Fix/success_history.json"),
                JSON.toJSONString(successHistory, SerializerFeature.PrettyFormat), StandardCharsets.UTF_8);
        FileUtils.write(new File("/Users/drew/Desktop/0301Fix/error.json"),
                JSON.toJSONString(error, SerializerFeature.PrettyFormat), StandardCharsets.UTF_8);
    }


    @Test
    public void verify() throws IOException {
        List<Order> errors = new ArrayList<>();
        JSON.parseArray(FileUtils.readFileToString(new File("/Users/drew/Desktop/0301Fix/error.json"), StandardCharsets.UTF_8), Order.class)
                .parallelStream().forEach(order -> {
                    try {
                        Map<String, Object> refundParams = new HashMap<>(2);
                        refundParams.put("payment_id", order.getTransactionId());
                        Map<String, Object> refund = Refund.query(refundParams);
                        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(refund));
                        if ("S".equals(jsonObject.getJSONArray("refunds")
                                .getJSONObject(jsonObject.getJSONArray("refunds").size() - 1)
                                .getString("trans_status"))) {

                            Asset asset = assetRepo.findByOrderId(order.getId()).stream().findAny().orElse(null);
                            if (asset != null) {
                                tokenHistoryRepo.findByTokenIdOrderByCreatedAtDesc(asset.getTokenId());
                                collectionRepo.deleteByAssetId(asset.getId());
                                assetRepo.delete(asset);
                                orderRepo.delete(order);
                                tokenHistoryRepo.deleteByTokenId(asset.getTokenId());
                            } else {
                                errors.add(order);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        errors.add(order);
                    }
                });
        FileUtils.write(new File("/Users/drew/Desktop/0301Fix/verify_error.json"),
                JSON.toJSONString(errors, SerializerFeature.PrettyFormat), StandardCharsets.UTF_8);

    }

    @Test
    public void fixOverNumber() throws IOException {
        List<Asset> list = assetRepo.findOverNumber();
        System.out.println(list.size());
        StringBuilder builder = new StringBuilder();
        list.stream().collect(Collectors.groupingBy(asset -> asset.getCollectionId()))
                .forEach((collectionId, assets) -> {
                    Collection collection = collectionRepo.findById(collectionId).orElse(null);
                    if (collection != null) {
                        List<Asset> coldAssets = assetRepo.findColdAsset(collection.getName(), collection.getTotal());
                        System.out.println(collection.getTotal() + " " + collection.getName() + " " + assets.size() + " " + coldAssets.size());
                        for (int i = 0; i < Math.min(assets.size(), coldAssets.size()); i++) {
                            Asset asset = assets.get(i);
                            Asset cold = coldAssets.get(i);
                            String s = asset.getId() + "," + asset.getName() + "," + asset.getNumber() + "->" + cold.getNumber();
                            builder.append(s).append("\n");

                            asset.setNumber(cold.getNumber());
                            assetRepo.save(asset);

                            for (Long aLong : collectionRepo.findAllByAssetId(asset.getId())) {
                                collectionRepo.findById(aLong).ifPresent(c -> {
                                    c.setNumber(cold.getNumber());
                                    collectionRepo.save(c);
                                });
                            }
                        }
                    }
                });
        FileUtils.write(new File("/Users/drew/Desktop/改编号.txt"), builder.toString(), StandardCharsets.UTF_8);
    }
}
