package com.izouma.nineth.service;

import com.izouma.nineth.domain.*;
import com.izouma.nineth.dto.PageQuery;
import com.izouma.nineth.enums.AssetStatus;
import com.izouma.nineth.enums.MintOrderStatus;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.*;
import com.izouma.nineth.utils.JpaUtils;
import com.izouma.nineth.utils.SecurityUtils;
import lombok.AllArgsConstructor;
import org.opencv.face.Face;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class MintOrderService {

    private MintOrderRepo    mintOrderRepo;
    private UserRepo         userRepo;
    private AssetService     assetService;
    private AssetRepo        assetRepo;
    private MintActivityRepo mintActivityRepo;
    private UserAddressRepo  userAddressRepo;

    public Page<MintOrder> all(PageQuery pageQuery) {
        return mintOrderRepo.findAll(JpaUtils.toSpecification(pageQuery, MintOrder.class), JpaUtils.toPageRequest(pageQuery));
    }

    @Transactional
    public void create(Long userId, List<Long> assetIds) {
        User user = userRepo.findByIdAndDelFalse(userId).orElseThrow(new BusinessException("用户不存在"));
        User blackHole = userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
        if (assetIds.size() != 3) {
            throw new BusinessException("数量不正确，请重新选择");
        }
        List<Asset> assets = assetRepo.findAllByIdInAndUserId(assetIds, userId);
        assets = assets.stream()
                .filter(asset -> asset.getName().contains("尼尔斯") && AssetStatus.NORMAL.equals(asset.getStatus()))
                .collect(Collectors.toList());
        if (assets.size() != 3) {
            throw new BusinessException("有藏品不符合，请重新选择");
        }
        // 铸造资产
        List<MintMaterial> materials = assets.stream().map(asset -> {
            MintMaterial material = new MintMaterial();
            material.setAssetId(asset.getId());
            material.setCollectionId(asset.getCollectionId());
            material.setName(asset.getName());
            return material;
        }).collect(Collectors.toList());

        // 铸造订单
        mintOrderRepo.save(MintOrder.builder()
                .userId(userId)
                .phone(user.getPhone())
                .material(materials)
                .consume(true)
                .status(MintOrderStatus.AIR_DROP)
                .build());

        // 改为转赠
        assets.forEach(asset -> assetService.transfer(asset, asset.getPrice(), blackHole, "转赠", null));

    }

    public void finish(Long id) {
        MintOrder mintOrder = mintOrderRepo.findById(id).orElseThrow(new BusinessException("铸造订单不存在"));
        mintOrder.setStatus(MintOrderStatus.FINISH);
        mintOrderRepo.save(mintOrder);
    }


    /**
     * @param user           用户
     * @param assetId        资产
     * @param mintActivityId 铸造活动
     * @param addressId      地址
     */
    @Transactional
    public void create(User user, List<Long> assetId, Long mintActivityId, Long addressId) {
        // 参加的活动
        MintActivity mintActivity = mintActivityRepo.findByIdAndDelFalse(mintActivityId)
                .orElseThrow(new BusinessException("无此铸造活动"));

        if (mintActivity.getStock() <= 0) {
            throw new BusinessException("铸造活动已无库存");
        }


        if (assetId.size() != mintActivity.getNum()) {
            throw new BusinessException("数量不正确，请重新选择");
        }

        List<Asset> assets = assetRepo.findAllByIdInAndUserId(assetId, user.getId());
        // 资产产品是否符合铸造活动的名称
        assets = assets.stream()
                .filter(asset -> asset.getName()
                        .contains(mintActivity.getCollectionName()) && AssetStatus.NORMAL.equals(asset.getStatus()))
                .collect(Collectors.toList());
        if (assets.size() != 3) {
            throw new BusinessException("有藏品不符合，请重新选择");
        }

        // 铸造特权
        if (!mintActivity.isConsume()) {
            List<Asset> finalAssets = assets;
            assets.forEach(asset -> {
                List<Privilege> privileges = asset.getPrivileges()
                        .stream()
                        .filter(p -> p.getName().equals("铸造"))
                        .collect(Collectors.toList());
                if (privileges.size() == 0) {
                    throw new BusinessException("无铸造特权");
                } else {
                    boolean flag = false;
//                    Privilege result = null;
                    for (Privilege privilege : privileges) {
                        // 打开多次 或者 可打开一次但未使用
                        if (!privilege.isOnce() || (privilege.isOnce() && !privilege
                                .isOpened())) {
                            flag = true;
//                            result = privilege;
                            break;
                        }
                    }
                    if (flag) {
//                        result.setOpened(true);
//                        result.setOpenedBy(user.getId());
//                        result.setOpenTime(LocalDateTime.now());
                    } else {
                        throw new BusinessException("铸造特权已使用");
                    }
                }
                assetRepo.saveAll(finalAssets);
            });
        } else {
            // 消耗改为转赠
            // 转让的用户
            User blackHole = userRepo.findByIdAndDelFalse(1435297L).orElseThrow(new BusinessException("无法铸造"));
//            assets.forEach(asset -> assetService.transfer(asset, asset.getPrice(), blackHole, "转赠", null));
        }

        // 铸造资产
        List<MintMaterial> materials = assets.stream().map(asset -> {
            MintMaterial material = new MintMaterial();
            material.setAssetId(asset.getId());
            material.setCollectionId(asset.getCollectionId());
            material.setName(asset.getName());
            return material;
        }).collect(Collectors.toList());

        UserAddress userAddress = null;
        if (addressId != null) {
            userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
        }

        // 铸造订单
        mintOrderRepo.save(MintOrder.builder()
                .userId(user.getId())
                .phone(user.getPhone())
                .material(materials)
                .consume(mintActivity.isConsume())
                .status(MintOrderStatus.NOT_PAID)
                .gasPrice(mintActivity.getGasPrice())
                .mintActivityId(mintActivityId)
                .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
                .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone).orElse(null))
                .address(Optional.ofNullable(userAddress).map(u ->
                                u.getProvinceId() + " " + u.getCityId() + " " + u.getDistrictId() + " " + u.getAddress())
                        .orElse(null))
                .build());

    }
}
