package com.bizzan.bitrade.controller;

import static com.bizzan.bitrade.constant.SysConstant.SESSION_MEMBER;
import static com.bizzan.bitrade.entity.QMember.member;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;

import com.bizzan.bitrade.constant.PageModel;
import com.bizzan.bitrade.controller.screen.ContractRewardRecordScreen;
import com.bizzan.bitrade.controller.screen.MemberScreen;
import com.bizzan.bitrade.entity.AgentInfo;
import com.bizzan.bitrade.entity.ContractRewardRecord;
import com.bizzan.bitrade.entity.ContractRewardRecordVo;
import com.bizzan.bitrade.entity.Member;
import com.bizzan.bitrade.entity.MemberWeightUpper;
import com.bizzan.bitrade.entity.QContractRewardRecord;
import com.bizzan.bitrade.entity.transform.AuthMember;
import com.bizzan.bitrade.service.AgentInfoService;
import com.bizzan.bitrade.service.ContractOrderEntrustService;
import com.bizzan.bitrade.entity.AgentApply;
import com.bizzan.bitrade.entity.QAgentApply;
import com.bizzan.bitrade.service.AgentApplyService;
import com.bizzan.bitrade.service.ContractRewardRecordService;
import com.bizzan.bitrade.service.LocaleMessageSourceService;
import com.bizzan.bitrade.service.MemberService;
import com.bizzan.bitrade.service.MemberTransactionService;
import com.bizzan.bitrade.service.MemberWeightUpperService;
import com.bizzan.bitrade.constant.TransactionType;
import com.bizzan.bitrade.util.DateUtil;
import com.bizzan.bitrade.util.MessageResult;
import com.bizzan.bitrade.util.PredicateUtils;
import com.bizzan.bitrade.vo.AgentInfoVo;
import com.bizzan.bitrade.vo.AgentStatVo;
import com.bizzan.bitrade.vo.RewardSetOneLevel;
import com.bizzan.bitrade.vo.RewardSetVo;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@Api(value = "AgentController" , tags = "代理商接口")
@RestController
@RequestMapping("/agent")
@Slf4j
public class AgentController extends BaseController {

    @Autowired
    private MemberService memberService;
	@Autowired
    private ContractRewardRecordService contractRewardRecordService;
    @Resource
    private MemberWeightUpperService memberWeightUpperService;
    @Autowired
    private LocaleMessageSourceService messageSourceService;
    @Autowired
    private ContractOrderEntrustService contractOrderEntrustService;
    @Autowired
    private AgentInfoService agentInfoService;
    @Autowired
    private MemberTransactionService memberTransactionService;
	
    @ApiOperation(value="获取下级成员列表", notes="获取下级成员列表")
	//@PostMapping(value = "/member/list")
    @Transactional(rollbackFor = Exception.class)
    public MessageResult memberList(
            PageModel pageModel,
            MemberScreen screen,
            @SessionAttribute(SESSION_MEMBER) AuthMember user) {
        // 检查用户是否是代理商
        Member checkMember = memberService.findOne(user.getId());
        if(!checkMember.getSuperPartner().equals("1")) {
            return error(messageSourceService.getMessage("USER_NOT_AGENT"));
        }
        Predicate predicate = getMemberPredicate(screen, user.getId());
        Page<Member> all = memberService.findAll(predicate, pageModel.getPageable());
        return success(all);
    }
	private Predicate getMemberPredicate(MemberScreen screen, Long userId) {
        ArrayList<BooleanExpression> booleanExpressions = new ArrayList<>();
        if (screen.getStatus() != null) {
            booleanExpressions.add(member.certifiedBusinessStatus.eq(screen.getStatus()));
        }
        if (screen.getStartTime() != null) {
            booleanExpressions.add(member.registrationTime.goe(screen.getStartTime()));
        }
        if (screen.getEndTime() != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(screen.getEndTime());
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            booleanExpressions.add(member.registrationTime.lt(calendar.getTime()));
        }

        if (!StringUtils.isEmpty(screen.getAccount())) {
            booleanExpressions.add(member.username.like("%" + screen.getAccount() + "%")
                    .or(member.mobilePhone.like(screen.getAccount() + "%"))
                    .or(member.email.like(screen.getAccount() + "%"))
                    .or(member.id.eq(Long.valueOf(screen.getAccount())))
                    .or(member.realName.like("%" + screen.getAccount() + "%")));
        }
        // 筛选过滤出我邀请的人
        booleanExpressions.add(member.inviterId.eq(userId));
        if (screen.getCommonStatus() != null) {
            booleanExpressions.add(member.status.eq(screen.getCommonStatus()));
        }
        return PredicateUtils.getPredicate(booleanExpressions);
    }
	
	@ApiOperation(value="获取返佣记录", notes="获取返佣记录")
	@PostMapping(value = "/reward")
    @Transactional(rollbackFor = Exception.class)
    public MessageResult<Page<ContractRewardRecordVo>> pageQuery(
            PageModel pageModel,
            ContractRewardRecordScreen screen,
            @SessionAttribute(SESSION_MEMBER) AuthMember user) {

        Member checkMember = memberService.findOne(user.getId());
        if(!checkMember.getSuperPartner().equals("1")) {
            return error(messageSourceService.getMessage("USER_NOT_AGENT"));
        }

        if (pageModel.getDirection() == null && pageModel.getProperty() == null) {
            ArrayList<Sort.Direction> directions = new ArrayList<>();
            directions.add(Sort.Direction.DESC);
            pageModel.setDirection(directions);
            List<String> property = new ArrayList<>();
            property.add("createTime");
            pageModel.setProperty(property);
        }
        //获取查询条件
        Predicate predicate = getPredicate(screen,checkMember.getId());

        Page<ContractRewardRecord> results = contractRewardRecordService.findAll(predicate, pageModel.getPageable());
        List<ContractRewardRecordVo> voList = results.getContent().stream().map(x -> ContractRewardRecordVo.builder()
        		.username(x.getFromMember().getUsername())
        		.memberId(x.getFromMember().getId())
        		.num(x.getNum())
        		.createTime(x.getCreateTime())
        		.build()).collect(Collectors.toList());
        
        Page<ContractRewardRecordVo> newResults = new PageImpl<>(voList, pageModel.getPageable(), results.getTotalElements());

        return success(newResults);
    }
	
	private Predicate getPredicate(ContractRewardRecordScreen screen,Long id) {
        ArrayList<BooleanExpression> booleanExpressions = new ArrayList<>();
        QContractRewardRecord qContractRewardRecord = QContractRewardRecord.contractRewardRecord;
        booleanExpressions.add((qContractRewardRecord.member.id.eq(id)));
        if(screen.getMemberId()!=null) {
            booleanExpressions.add((qContractRewardRecord.fromMember.id.eq(screen.getMemberId())));
        }
        if (screen.getStartTime() != null) {
            booleanExpressions.add(qContractRewardRecord.createTime.goe(screen.getStartTime()));
        }
        if (screen.getEndTime() != null){
            booleanExpressions.add(qContractRewardRecord.createTime.lt(DateUtil.dateAddDay(screen.getEndTime(),1)));
        }
        if (screen.getType() != null) {
            booleanExpressions.add(qContractRewardRecord.type.eq(screen.getType()));
        }
        return PredicateUtils.getPredicate(booleanExpressions);
    }
	
	@ApiOperation(value="设置返佣比率", notes="设置返佣比率")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "id",value = "用户ID",required = true,dataType = "int"),
    		@ApiImplicitParam(name = "rate",value = "合约比率",required = true,dataType = "int"),
    		@ApiImplicitParam(name = "followRate",value = "跟单比率",required = false,dataType = "int")
    })
	@PostMapping(value = "/reward/set")
    public MessageResult set(
            @SessionAttribute(SESSION_MEMBER) AuthMember user,
            @RequestParam("id") Long memberId,
            Integer rate,
            Integer followRate,
            Integer wcRate
            ) {
        if(memberId == null){
            return error("设置用户的id不能为空！");
        }
        if(rate == null && followRate == null){
            return error("设置用户的比例不能为空！");
        }
        if(rate != null && (rate.intValue() < 0 || rate.intValue() > 100)){
            return error(messageSourceService.getMessage("AGENT_IN_RANGE"));
        }
        if(followRate != null && (followRate.intValue() < 0 || followRate.intValue() > 100)){
            return error(messageSourceService.getMessage("AGENT_IN_RANGE"));
        }
        if(wcRate != null 
        		&& (wcRate.intValue()!=0&&wcRate.intValue()!=2&&wcRate.intValue()!=4&&wcRate.intValue()!=6&&wcRate.intValue()!=8)){
            return error("设置用户的比例不合法！");
        }
        Member checkMember = memberService.findOne(user.getId());
        if(!"1".equals(checkMember.getSuperPartner())) {
            return error(messageSourceService.getMessage("USER_NOT_AGENT"));
        }
        Member setMember = memberService.findOne(memberId);
        MemberWeightUpper upperMemberId = memberWeightUpperService.findMemberWeightUpperByMemberId(setMember.getInviterId());
        
        /*Member upperMember = memberService.findOne(setMember.getInviterId());
        if("1".equals(upperMember.getSuperPartner())){
            if (rate.intValue() >= 100) {
                return error("设置比例应小于此用户上级推荐人的比例！");
            }
        }else {*/
        if (rate != null && rate.intValue() >= upperMemberId.getRate().intValue()) {
            return error(messageSourceService.getMessage("AGENT_LOWER_THAN_UPPER"));
        }
        if (followRate != null && followRate.intValue() >= upperMemberId.getFollowRate().intValue()) {
            return error(messageSourceService.getMessage("AGENT_LOWER_THAN_UPPER"));
        }
        if(wcRate != null && (upperMemberId.getWcRate()==null || wcRate.intValue() >= upperMemberId.getWcRate().intValue())) {
        	return error(messageSourceService.getMessage("AGENT_LOWER_THAN_UPPER"));
        }
        //}
        
        
        List<MemberWeightUpper> lowMemberWeightUpper = memberWeightUpperService.findAllByUpper(memberId);
        for (MemberWeightUpper memberWeightUpper:lowMemberWeightUpper) {
            if(rate != null && rate.intValue() <= memberWeightUpper.getRate().intValue()){
                return error(messageSourceService.getMessage("AGENT_GREATER_THAN_SUB"));
            }
            if(followRate != null && followRate.intValue() <= memberWeightUpper.getFollowRate().intValue()){
                return error(messageSourceService.getMessage("AGENT_GREATER_THAN_SUB"));
            }
            
            if(wcRate != null && memberWeightUpper.getWcRate()!=null && wcRate.intValue() <= memberWeightUpper.getWcRate().intValue()) {
            	return error(messageSourceService.getMessage("AGENT_GREATER_THAN_SUB"));
            }
        }
        MemberWeightUpper memberWeightUpper = memberWeightUpperService.findMemberWeightUpperByMemberId(memberId);
        if(rate != null && rate.intValue() < memberWeightUpper.getRate()) {
        	return error(messageSourceService.getMessage("AGENT_LOWER_THAN_LAST"));
        }
        if(followRate != null && followRate.intValue() < memberWeightUpper.getFollowRate()) {
        	return error(messageSourceService.getMessage("AGENT_LOWER_THAN_LAST"));
        }
        
        if(memberWeightUpper.getAllUppers().indexOf(String.valueOf(user.getId()))<0)
        	return error("illegal operation");
        log.info("memberWeightUpper.getUpper()={}", memberWeightUpper.getUpper());
        /*if(memberWeightUpper.getUpper()!=null) {
	        List<Member> allByIds = memberService.findAllByIds(memberWeightUpper.getUpper());
	        Optional<Member> firstSuperPartner = allByIds.stream().filter(e -> "1".equals(e.getSuperPartner())).findFirst();
	        if(firstSuperPartner.isPresent()){
	            if (!firstSuperPartner.get().getId().equals(checkMember.getId())){
	                return error("不能设置下级代理商的直推用户！");
	            }
	        }
        }*/
        if(rate != null)
        	memberWeightUpper.setRate(rate);
        //memberWeightUpper.setWcRate(wcRate);
        if(followRate != null)
        	memberWeightUpper.setFollowRate(followRate);
        memberWeightUpperService.save(memberWeightUpper);
        return success();
    }
	
	@ApiOperation(value="获取代理商信息", notes="获取代理商信息")
	@PostMapping(value = "info")
    public MessageResult agentInfo(
            @SessionAttribute(SESSION_MEMBER) AuthMember user) {
    	Member member = memberService.findOne(user.getId());
    	AgentInfo agentInfo = agentInfoService.findOne(member.getId());
    	AgentInfoVo vo = new AgentInfoVo();
    	BeanUtils.copyProperties(agentInfo, vo);
    	vo.setUsername(member.getUsername());
    	String[] todayTimeStr = DateUtil.getTodayRealSartAndEndDateStr();
    	BigDecimal todayContractAward = memberTransactionService.sumAmountByMemberIdAndTypeAndTime(todayTimeStr[0], todayTimeStr[1], member.getId(), TransactionType.CONTRACT_AWARD);
    	BigDecimal todayFollowAward = memberTransactionService.sumAmountByMemberIdAndTypeAndTime(todayTimeStr[0], todayTimeStr[1], member.getId(), TransactionType.FOLLOW_AWARD);
    	vo.setTodayAward(todayContractAward.add(todayFollowAward));
    	List<Long> subIds = memberWeightUpperService.findMemberIdListByAllUppers(member.getId());
    	subIds.add(member.getId());
    	Date[] todayDateArr = DateUtil.getTodayRealSartAndEndDate();
    	int todayNewUserCount = memberWeightUpperService.countRegisteredMembersByMemberIdsAndTime(subIds, todayDateArr[0], todayDateArr[1]);
    	vo.setTodayNewUserCount(todayNewUserCount);
    	Long[] todayTime = DateUtil.getRealStartAndEndDate(0);
    	int todayOrderUserCount = contractOrderEntrustService.countActiveMembersByMemberIdsAndTime(todayTime[0], todayTime[1], subIds);
    	vo.setTodayOrderUserCount(todayOrderUserCount);
    	MemberWeightUpper memberWeightUpper = memberWeightUpperService.findMemberWeightUpperByMemberId(member.getId());
    	vo.setRate(memberWeightUpper.getRate());
    	vo.setFollowRate(memberWeightUpper.getFollowRate());
    	MessageResult result = MessageResult.success();
    	result.setData(vo);
    	return result;
    }
	
	@ApiOperation(value="保存代理商信息", notes="保存代理商信息")
	@PostMapping(value = "save-info")
    public MessageResult saveInfo(
            @SessionAttribute(SESSION_MEMBER) AuthMember user, AgentInfo agentInfo) {
		if(StringUtils.isEmpty(agentInfo.getName())) {
			return error(messageSourceService.getMessage("MISSING_REAL_NAME"));
		}
		if(StringUtils.isEmpty(agentInfo.getPhone())) {
			return error(messageSourceService.getMessage("MISSING_PHONE"));
		}
		if(StringUtils.isEmpty(agentInfo.getAddress())) {
			return error(messageSourceService.getMessage("WRONG_ADDRESS"));
		}
		agentInfo.setId(user.getId());
		agentInfoService.save(agentInfo);
		return MessageResult.success();
	}
	
	@ApiOperation(value="获取返佣设置列表", notes="获取返佣设置列表")
	@PostMapping(value = "/reward/set/list")
    public MessageResult setList(
            @SessionAttribute(SESSION_MEMBER) AuthMember user) {
		Member checkMember = memberService.findOne(user.getId());
        if(!checkMember.getSuperPartner().equals("1")) {
            return error(messageSourceService.getMessage("USER_NOT_AGENT"));
        }
        List<RewardSetOneLevel> children = contractRewardRecordService.findChildren(user.getId());
        return success(children);
	}
	
	@ApiOperation(value="获取代理商统计信息", notes="获取代理商统计信息")
    @RequestMapping(value = "/stat", method= {RequestMethod.GET, RequestMethod.POST})
    @Transactional(rollbackFor = Exception.class)
    public MessageResult<AgentStatVo> stat(@SessionAttribute(SESSION_MEMBER) AuthMember user,String startDate,String endDate) throws ParseException {
    	String balanceEndDate = null;
    	if(startDate == null)
        	startDate = "1970-1-1";
        if(endDate == null) {
        	endDate = DateUtil.getDate();
        	endDate = endDate + " 23:59:59";
        	balanceEndDate = endDate;
        } else {
        	endDate = endDate + " 23:59:59";
        	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date endDateDate = sdf.parse(endDate);
            long balanceEndDateLong = endDateDate.getTime()-endDateDate.getDay()*24*60*60000 - 60*60000;
            balanceEndDate = sdf.format(new Date(balanceEndDateLong));
            log.info("balanceEndDate={}", balanceEndDate);
        }
        
        
    	
        Member member = memberService.findOne(user.getId());
        if(!member.getSuperPartner().equals("1")) {
            return error(messageSourceService.getMessage("USER_NOT_AGENT"));
        }
        List<MemberWeightUpper> subList = memberWeightUpperService.findAllByAllUppers(user.getId());
        List<Long> subIds = new ArrayList<Long>();
        for(MemberWeightUpper upper: subList)
        	subIds.add(upper.getMemberId());
        subIds.add(user.getId());
        log.info("subIds={}", subIds);
        AgentStatVo vo = new AgentStatVo();
        vo.setId(user.getId());
        
        //BigDecimal balance = memberTransactionService.sumAmountByMemberIdsAndTime("1970-1-1", endDate, subIds);
        BigDecimal timestampBalance = memberTransactionService.sumAmountByMemberIdsAndTime("1970-1-1", balanceEndDate, subIds);
        if (timestampBalance == null) timestampBalance = BigDecimal.ZERO;
        
        vo.setTimeStampBalance(timestampBalance);
        vo.setTotalBalance(timestampBalance);
        return success(vo);
    }

    @Autowired
    private AgentApplyService agentApplyService;

    /**
     * 提交经纪商申请，自动从会员信息中取姓名、手机号、邮箱
     *
     * @param user 当前登录用户
     * @return 操作结果
     */
    @ApiOperation(value = "提交经纪商申请", notes = "无需填写资料，自动从会员信息中获取")
    @PostMapping("/apply/submit")
    public MessageResult applySubmit(@SessionAttribute(SESSION_MEMBER) AuthMember user) {
        Member applyMember = memberService.findOne(user.getId());

        // 已经是经纪商，无需申请
        if ("1".equals(applyMember.getSuperPartner())) {
            return error(messageSourceService.getMessage("AGENT_ALREADY_BROKER"));
        }

        // 存在在途申请，不允许重复提交
        if (agentApplyService.hasPendingApply(user.getId())) {
            return error(messageSourceService.getMessage("AGENT_APPLY_PENDING"));
        }

        AgentApply agentApply = buildAgentApply(applyMember);
        agentApplyService.save(agentApply);
        return success(messageSourceService.getMessage("AGENT_APPLY_SUCCESS"));
    }

    /**
     * 分页查询当前用户的代理商申请记录
     *
     * @param user      当前登录用户
     * @param pageModel 分页参数
     * @return 分页结果
     */
    @ApiOperation(value = "查询我的代理商申请记录", notes = "分页查询当前登录用户提交的代理商申请记录")
    @PostMapping("/apply/my-list")
    public MessageResult applyMyList(
            @SessionAttribute(SESSION_MEMBER) AuthMember user,
            PageModel pageModel) {
        // 1. 构建仅查询当前用户的条件
        List<BooleanExpression> expressions = new ArrayList<>();
        expressions.add(QAgentApply.agentApply.memberId.eq(user.getId()));
        Predicate predicate = PredicateUtils.getPredicate(expressions);

        // 2. 执行分页查询
        return success(agentApplyService.findAll(predicate, pageModel.getPageable()));
    }

    /**
     * 从 Member 信息构建代理商申请实体
     *
     * @param applyMember 会员信息
     * @return AgentApply
     */
    private AgentApply buildAgentApply(Member applyMember) {
        AgentApply agentApply = new AgentApply();
        agentApply.setMemberId(applyMember.getId());
        agentApply.setRealName(applyMember.getRealName());
        agentApply.setPhone(applyMember.getMobilePhone());
        agentApply.setEmail(applyMember.getEmail());
        return agentApply;
    }
}
