package com.wuban.tron.explore.controller;

import com.github.pagehelper.PageInfo;
import com.wuban.tron.explore.constant.Constant;
import com.wuban.tron.explore.constant.HomeSearchTypeEnum;
import com.wuban.tron.explore.entity.Address;
import com.wuban.tron.explore.entity.BlockDayCensus;
import com.wuban.tron.explore.entity.BlockHeader;
import com.wuban.tron.explore.entity.Transaction;
import com.wuban.tron.explore.entity.example.AddressExample;
import com.wuban.tron.explore.entity.example.BlockDayCensusExample;
import com.wuban.tron.explore.entity.example.BlockHeaderExample;
import com.wuban.tron.explore.entity.example.TransactionExample;
import com.wuban.tron.explore.param.request.PageRequest;
import com.wuban.tron.explore.param.request.SearchRequest;
import com.wuban.tron.explore.param.response.SelfPageInfo;
import com.wuban.tron.explore.param.response.TransactionModel;
import com.wuban.tron.explore.service.AddressService;
import com.wuban.tron.explore.service.BlockDayCensusService;
import com.wuban.tron.explore.service.BlockHeaderService;
import com.wuban.tron.explore.service.TransactionService;
import com.wuban.tron.explore.util.ApiResponse;
import com.wuban.tron.explore.util.ResponseKit;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * <core>API接口</core>
 *
 * @author sky
 * @date 2020/11/02
 */
@Slf4j
@RestController
@RequestMapping("/api/tron")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Deprecated
public class TransactionController {

    private final TransactionService transactionService;

    private final BlockDayCensusService blockDayCensusService;

    private final BlockHeaderService blockHeaderService;

    private final AddressService addressService;


    /**
     * 首页 - 搜索
     *
     * @param reqParam
     * @return
     */
    @RequestMapping(value="index/search", method = RequestMethod.POST)
    public ApiResponse search(@RequestBody SearchRequest reqParam) {
        if (StringUtils.isEmpty(reqParam.getCondition())) {
            return ResponseKit.success();
        }

        TransactionExample example = new TransactionExample();
        String condition = StringUtils.trimAllWhitespace(reqParam.getCondition());

        /*
            块查询
         */
        if (isNumeric(condition)) {
            BlockHeaderExample headerExample = new BlockHeaderExample();
            headerExample.createCriteria().andNumberEqualTo(Long.valueOf(condition));
            BlockHeader blockHeader = this.blockHeaderService.getOneByExample(headerExample);

            example.createCriteria().andNumberEqualTo(Long.valueOf(condition));
            PageInfo<Transaction> pageInfo = this.transactionService.getByPageWithCategory(reqParam.getStartIndex(), reqParam.getPageSize(), example);

            HomeSearchModel<TransactionModel> model = new HomeSearchModel();
            model.setBlock(blockHeader);
            List<TransactionModel> txList = this.transfer(pageInfo);
            model.setTransList(txList);
            model.setT(HomeSearchTypeEnum.BLOCK_INFO.getCode());
            return ResponseKit.success(model);
        }

        /*
            账户地址
         */
        if (condition.length() == Constant.USER_ADDRESS_LEN) {
            HomeSearchModel model = new HomeSearchModel();
            AddressExample addressExample = new AddressExample();
            addressExample.createCriteria().andAddressEqualTo(reqParam.getCondition());
            Address address = this.addressService.selectOneByExample(addressExample);
            PageInfo<Transaction> pageInfo = this.transactionService.selectListByAddress(reqParam.getCondition(), 1, reqParam.getStartIndex(), reqParam.getPageSize());
            List<TransactionModel> txList = this.transfer(pageInfo);
            model.setTransList(txList);
            model.setAddress(address);
            model.setT(HomeSearchTypeEnum.ADDRESS_INFO.getCode());
            return ResponseKit.success(model);
        }

        /*
            交易hash
         */
        if (condition.length()== Constant.TX_ID_LEN) {
            HomeSearchModel<Transaction> model = new HomeSearchModel();
            example.createCriteria().andTxIdEqualTo(condition);
            List<Transaction> txList = this.transactionService.getByExample(example);
            model.setT(HomeSearchTypeEnum.TRANSACTION_INFO.getCode());
            model.setTransList(txList);
            return ResponseKit.success(model);
        }

        return ResponseKit.success();
    }

    /**
     * 首页 - Latest Blocks
     *
     * @param reqParam
     * @return
     */
    @RequestMapping(value="index/block", method = RequestMethod.POST)
    public ApiResponse lastBlockList(@RequestBody PageRequest reqParam) {
        PageInfo<BlockDayCensus> pageInfo = this.blockDayCensusService.getByPageWithCategory(reqParam.getStartIndex(), reqParam.getPageSize(), new BlockDayCensusExample());

        SelfPageInfo<BlockDayCensus> selfPageInfo = new SelfPageInfo<>();
        selfPageInfo.setTotalPages(pageInfo.getPages());
        selfPageInfo.setTotalItems(pageInfo.getTotal());
        if (pageInfo.getList() != null) {
            selfPageInfo.setList(pageInfo.getList());
        }
        return ResponseKit.success(selfPageInfo);
    }

    /**
     * 首页 - Latest Transactions
     *
     * @param reqParam
     * @return
     */
    @RequestMapping(value="index/trans", method = RequestMethod.POST)
    public ApiResponse lastTransList(@RequestBody PageRequest reqParam) {
        PageInfo<Transaction> pageInfo = this.transactionService.getByPageWithCategory(reqParam.getStartIndex(), reqParam.getPageSize(), new TransactionExample());

        SelfPageInfo<TransactionModel> selfPageInfo = new SelfPageInfo<>();
        selfPageInfo.setTotalPages(pageInfo.getPages());
        selfPageInfo.setTotalItems(pageInfo.getTotal());
        if (pageInfo.getList() != null) {
            List<TransactionModel> modelList = new ArrayList<>();
            pageInfo.getList().forEach(o->{
                TransactionModel model = new TransactionModel();
                model.setFrom(o.getOwnerAddress());
                model.setNumber(o.getNumber());
                model.setTxId(o.getTxId());
                if (!StringUtils.isEmpty(o.getContractAddress())) {
                    model.setTo(o.getContractAddress());
                }
                if (!StringUtils.isEmpty(o.getToAddress())) {
                    model.setTo(o.getToAddress());
                }
                if (o.getAmount() == null) {
                    model.setAmount(0L);
                }
                modelList.add(model);
            });
            selfPageInfo.setList(modelList);
        }
        return ResponseKit.success(selfPageInfo);
    }

    /**
     * 首页 - 根据区块高度获取交易列表
     *
     * @param reqParam
     * @return
     */
    @RequestMapping(value="index/block/trans", method = RequestMethod.POST)
    public ApiResponse transByBlock(@RequestBody SearchRequest reqParam) {
        if (StringUtils.isEmpty(reqParam.getCondition())) {
            return ResponseKit.success();
        }

        String condition = StringUtils.trimAllWhitespace(reqParam.getCondition());
        BlockHeaderExample headerExample = new BlockHeaderExample();
        headerExample.createCriteria().andNumberEqualTo(Long.valueOf(condition));
        BlockHeader blockHeader = this.blockHeaderService.getOneByExample(headerExample);

        TransactionExample example = new TransactionExample();
        example.createCriteria().andNumberEqualTo(Long.valueOf(condition));
        PageInfo<Transaction> pageInfo = this.transactionService.getByPageWithCategory(reqParam.getStartIndex(), reqParam.getPageSize(), example);

        HomeSearchModel<TransactionModel> model = new HomeSearchModel();
        model.setBlock(blockHeader);
        List<TransactionModel> txList = this.transfer(pageInfo);
        model.setTransList(txList);
        model.setT(HomeSearchTypeEnum.BLOCK_INFO.getCode());
        return ResponseKit.success(model);
    }


    /**
     * 首页 - TRANSACTION HISTORY IN 14 DAYS
     *
     * @param reqParam
     * @return
     */
    @RequestMapping(value="index/trans/census", method = RequestMethod.POST)
    public ApiResponse transCensusLast(@RequestBody PageRequest reqParam) {
        PageInfo<BlockDayCensus> pageInfo = this.blockDayCensusService.getByPageWithCategory(reqParam.getStartIndex(), reqParam.getPageSize(), new BlockDayCensusExample());
        return ResponseKit.success(pageInfo.getList());
    }

    /**
     * Daily Transactions Chart Data.
     *
     * @return
     */
    @RequestMapping(value="index/trans/census/all", method = RequestMethod.POST)
    public ApiResponse transCensusLast() {
        List<BlockDayCensus> list = this.blockDayCensusService.getByExample(new BlockDayCensusExample());
        return ResponseKit.success(list);
    }

    /**
     * 根据用户地址查看用户交易信息
     *
     * @return
     */
    @RequestMapping(value="/user/trans", method = RequestMethod.POST)
    public ApiResponse userTrans(@RequestBody SearchRequest reqParam) {
        HomeSearchModel model = new HomeSearchModel();
        AddressExample addressExample = new AddressExample();
        addressExample.createCriteria().andAddressEqualTo(reqParam.getCondition());
        Address address = this.addressService.selectOneByExample(addressExample);
        PageInfo<Transaction> pageInfo = this.transactionService.selectListByAddress(reqParam.getCondition(), reqParam.getType(), reqParam.getStartIndex(), reqParam.getPageSize());
        List<TransactionModel> txList = this.transfer(pageInfo);
        model.setTransList(txList);
        model.setAddress(address);
        return ResponseKit.success(model);
    }

    /**
     * 用户余额排行榜
     *
     * @return
     */
    @RequestMapping(value="/user/balance/top", method = RequestMethod.POST)
    public ApiResponse userBalanceTop(@RequestBody PageRequest reqParam) {
        AddressExample example = new AddressExample();
        example.setOrderByClause("balance desc");
        PageInfo<Address> pageInfo = this.addressService.selectByPager(reqParam.getStartIndex(), reqParam.getPageSize(), example);

        SelfPageInfo<Address> selfPageInfo = new SelfPageInfo<>();
        selfPageInfo.setList(pageInfo.getList());
        selfPageInfo.setTotalItems(pageInfo.getTotal());
        selfPageInfo.setTotalPages(pageInfo.getPages());
        return ResponseKit.success(selfPageInfo);
    }

    /**
     * 交易详情
     *
     * @return
     */
    @RequestMapping(value="/trans/info", method = RequestMethod.GET)
    public ApiResponse userTrans(String hash) {
        if (StringUtils.isEmpty(hash)) {
            return ResponseKit.success();
        }

        TransactionExample example = new TransactionExample();
        example.createCriteria().andTxIdEqualTo(hash);
        List<Transaction> txList = this.transactionService.getByExample(example);
        if (!CollectionUtils.isEmpty(txList)) {
            return ResponseKit.success(txList.get(0));
        }

        return ResponseKit.success();
    }

    private List<TransactionModel> transfer(PageInfo<Transaction> pageInfo) {
        List<TransactionModel> txList = new ArrayList<>();
        if (CollectionUtils.isEmpty(pageInfo.getList())) {
            return txList;
        }

        pageInfo.getList().forEach(o -> {
            TransactionModel txModel = new TransactionModel();
            txModel.setTxId(o.getTxId());
            txModel.setAmount(o.getAmount());
            txModel.setNumber(o.getNumber());
            txModel.setFrom(o.getOwnerAddress());
            if (!StringUtils.isEmpty(o.getToAddress())) {
                txModel.setTo(o.getToAddress());
            }
            if (!StringUtils.isEmpty(o.getContractAddress())) {
                txModel.setTo(o.getContractAddress());
            }
            txList.add(txModel);
        });

        return txList;
    }

    public final static boolean isNumeric(String s) {
        if (s != null && !"".equals(s.trim())) {
            return s.matches("^[0-9]*$");
        } else {
            return false;
        }
    }

}

@Data
class HomeSearchModel<T> {
    private BlockHeader block;
    private List<T> transList;
    private Address address;
    private int t;
}
