package com.bizzan.bitrade.service;

import com.bizzan.bitrade.constant.PageModel;
import com.bizzan.bitrade.dao.MemberDepositDao;
import com.bizzan.bitrade.entity.MemberDeposit;
import com.bizzan.bitrade.entity.QMember;
import com.bizzan.bitrade.entity.QMemberDeposit;
import com.bizzan.bitrade.pagination.Criteria;
import com.bizzan.bitrade.pagination.Restrictions;
import com.bizzan.bitrade.service.Base.BaseService;
import com.bizzan.bitrade.service.Base.TopBaseService;
import com.bizzan.bitrade.util.PredicateUtils;
import com.bizzan.bitrade.vo.DepositControlVo;
import com.bizzan.bitrade.vo.DepositTransferControlVo;
import com.bizzan.bitrade.vo.MemberDepositVO;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
public class MemberDepositService extends BaseService<MemberDeposit> {

    @Autowired
    private MemberDepositDao memberDepositDao ;

    public Page<MemberDepositVO> page(List<BooleanExpression> predicates,PageModel pageModel){
        JPAQuery<MemberDepositVO> query = queryFactory.select(Projections.fields(MemberDepositVO.class,
                QMemberDeposit.memberDeposit.id.as("id"),
                QMember.member.username,
                QMember.member.id.as("memberId"),
                QMemberDeposit.memberDeposit.address,
                QMemberDeposit.memberDeposit.amount,
                QMemberDeposit.memberDeposit.createTime.as("createTime"),
                QMemberDeposit.memberDeposit.unit)).from(QMember.member,QMemberDeposit.memberDeposit)
                .where(predicates.toArray(new BooleanExpression[predicates.size()]));
        List<OrderSpecifier> orderSpecifiers = pageModel.getOrderSpecifiers();
        query.orderBy(orderSpecifiers.toArray(new OrderSpecifier[orderSpecifiers.size()])) ;
        long total = query.fetchCount() ;
        query.offset(pageModel.getPageSize()*(pageModel.getPageNo()-1)).limit(pageModel.getPageSize());
        List<MemberDepositVO> list = query.fetch() ;
        return new PageImpl<MemberDepositVO>(list,pageModel.getPageable(),total);
    }

    public Long getMaxId() {
    	return memberDepositDao.getMaxId();
    }
    
    public BigDecimal getMaxAmountByMemberId() {
    	BigDecimal maxAmount = memberDepositDao.getMaxAmountByMemberId(getMaxId());
    	if(maxAmount == null)
    		return BigDecimal.ZERO;
    	else
    		return maxAmount;
    }
    
    public Page<MemberDepositVO> queryByMemberId(Long memberId, Integer pageNo, Integer pageSize){
    	Criteria<MemberDeposit> specification = new Criteria<MemberDeposit>();
    	specification.add(Restrictions.eq("memberId", memberId, false));
    	JPAQuery<MemberDepositVO> query = queryFactory.select(Projections.fields(MemberDepositVO.class,
                QMemberDeposit.memberDeposit.id.as("id"),
                QMember.member.username,
                QMember.member.id.as("memberId"),
                QMemberDeposit.memberDeposit.address,
                QMemberDeposit.memberDeposit.txid,
                QMemberDeposit.memberDeposit.amount,
                QMemberDeposit.memberDeposit.createTime.as("createTime"),
                QMemberDeposit.memberDeposit.unit)).from(QMember.member,QMemberDeposit.memberDeposit)
                .where(QMemberDeposit.memberDeposit.memberId.eq(memberId))
                .where(QMember.member.id.eq(QMemberDeposit.memberDeposit.memberId))
                .orderBy(new OrderSpecifier(Order.DESC, ExpressionUtils.path(Path.class,"createTime")));
    	Sort orders = Criteria.sortStatic("createTime.desc");
    	PageRequest pageRequest = new PageRequest(pageNo-1, pageSize, orders);
    	long total = query.fetchCount() ;
        query.offset(pageSize*(pageNo-1)).limit(pageSize);
        List<MemberDepositVO> list = query.fetch() ;
    	return new PageImpl<MemberDepositVO>(list,pageRequest,total);
    }
    
    public MemberDeposit findLatestByMemberId(Long memberId) {
    	return memberDepositDao.findLatestByMemberId(memberId);
    }
    
    public List<DepositControlVo> statControl(String startTime, String endTime) {
    	List<DepositControlVo> list = new ArrayList<>();
    	Object[][] objArray = memberDepositDao.statControl(startTime, endTime);
    	for (Object[] obj : objArray) {
    		DepositControlVo vo = new DepositControlVo();
        	if(obj[0]!=null)
        		vo.setMemberId(Long.parseLong(obj[0].toString()));
        	if(obj[1]!=null)
        		vo.setSmallCount(Integer.parseInt(obj[1].toString()));
        	if(obj[2]!=null)
        		vo.setSmallAmount(BigDecimal.valueOf(Double.parseDouble(obj[2].toString())));
        	list.add(vo);
    	}
    	return list;
    }
    
    public List<DepositTransferControlVo> statTransferControl(String startTime, String endTime) {
    	List<DepositTransferControlVo> list = new ArrayList<>();
    	Object[][] objArray = memberDepositDao.statTransferControl(startTime, endTime);
    	for (Object[] obj : objArray) {
    		DepositTransferControlVo vo = new DepositTransferControlVo();
        	if(obj[0]!=null)
        		vo.setMemberId(Long.parseLong(obj[0].toString()));
        	if(obj[1]!=null)
        		vo.setInterval(Integer.parseInt(obj[1].toString()));
        	if(obj[2]!=null)
        		vo.setAmount(BigDecimal.valueOf(Double.parseDouble(obj[2].toString())));
        	if(obj[3]!=null)
        		vo.setTargetMemberId(Long.parseLong(obj[3].toString()));
        	list.add(vo);
    	}
    	return list;
    }
    
}
