package com.softwarebr.nunu.service.hall.impl;

import com.alibaba.fastjson.JSON;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.OSSObject;
import com.brframework.common.utils.ConvertObjectUtil;
import com.brframework.common.utils.DateTimeUtils;
import com.brframework.commondb.core.AbstractEntityService;
import com.brframework.commondb.core.CommonRepository;
import com.brframework.commondb.core.ControllerPageHandle;
import com.brframework.commonmq.annotation.MQConfig;
import com.brframework.commonmq.core.MQClient;
import com.brframework.commonoss.config.AliYunOSSConfig;
import com.brframework.commonoss.core.AliYunOSSClient;
import com.brframework.commonweb.exception.HandleException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.softwarebr.nunu.dao.hall.InvestDao;
import com.softwarebr.nunu.domain.Attachments;
import com.softwarebr.nunu.domain.VisualizationDate;
import com.softwarebr.nunu.dto.hall.InvestParamDTO;
import com.softwarebr.nunu.dto.hall.TeamParamDTO;
import com.softwarebr.nunu.entity.hall.Invest;
import com.softwarebr.nunu.entity.hall.Team;
import com.softwarebr.nunu.entity.user.Member;
import com.softwarebr.nunu.entity.user.Message;
import com.softwarebr.nunu.globals.MQTopics;
import com.softwarebr.nunu.globals.SystemConst;
import com.softwarebr.nunu.json.admin.visual.InvestProjectResult;
import com.softwarebr.nunu.json.api.hall.InvestDetailsResult;
import com.softwarebr.nunu.service.hall.InvestApplyService;
import com.softwarebr.nunu.service.hall.InvestOrgService;
import com.softwarebr.nunu.service.hall.InvestService;
import com.softwarebr.nunu.service.hall.TeamService;
import com.softwarebr.nunu.service.user.MemberService;
import com.softwarebr.nunu.service.user.MessageService;
import com.softwarebr.nunu.util.VisualizationUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import retrofit2.http.Url;

import javax.servlet.http.HttpServletResponse;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @date 2020-02-25 12:03:51
 * @author lilin
 */

@Slf4j
@Service
@MQConfig
public class InvestServiceImpl extends AbstractEntityService<Invest, Long, Object> implements InvestService {

	@Autowired
	private InvestDao investDao;

	@Autowired
	private TeamService teamService;

	@Autowired
	private MemberService memberService;

	@Autowired
	private InvestOrgService investOrgService;

	@Autowired
	private InvestApplyService investApplyService;

    @Autowired
    private MQClient mqClient;

    @Autowired
    private MessageService messageService;

	@Autowired
	private AliYunOSSConfig aliYunOSSConfig;

	@Override
	public CommonRepository<Long, Invest> getRepository() {
		return investDao;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Invest saveInvest(Long memberId, InvestParamDTO investParamDTO, List<TeamParamDTO> teamParamDTOS){
		Invest invest = ControllerPageHandle.convertTo(investParamDTO, Invest.class);
		invest.setCreateDate(LocalDateTime.now());
		invest.setUpperStatus(SystemConst.STATUS_LOWER_SHELF);
		invest.setIndexType(SystemConst.INDEX_TYPE_NO);
		if(memberId>0){
			invest.setVerify(SystemConst.VERIFY_AWAIT);
		}else{
			invest.setVerify(SystemConst.VERIFY_ADOPT);
		}
		invest.setPublisher(memberId);
		invest.setTeamNumber(teamParamDTOS.size());
		invest = investDao.save(invest);
		for (TeamParamDTO teamParamDTO : teamParamDTOS){
			Team team = ControllerPageHandle.convertTo(teamParamDTO, Team.class);
			team.setInvestId(invest.getId());
			team.setCreateDate(LocalDateTime.now());
			teamService.save(team);
		}
		return invest;
	}


	@Transactional(rollbackFor = Exception.class)
	@Override
	public void updateInvest(Long investId, InvestParamDTO investParamDTO, List<TeamParamDTO> teamParamDTOS){
		Invest invest = accessObject(investId);
		invest = ConvertObjectUtil.convertJavaBean(invest, investParamDTO,  true);
		investDao.save(invest);
		for (TeamParamDTO teamParamDTO : teamParamDTOS){
			Team team = ControllerPageHandle.convertTo(teamParamDTO, Team.class);
			team.setInvestId(investId);
			teamService.save(team);
		}
	}

	@Override
	public Map<Integer, String> investStateMap(){
		Map<Integer, String> map = Maps.newHashMap();
		map.put(1, "种子轮");
		map.put(2, "天使轮");
		map.put(3, "A轮");
		map.put(4, "B轮");
		map.put(5, "C轮");
		map.put(6, "C轮后");
		return map;
	}

	@Override
	public Map<Integer, String> industryMap(){
		Map<Integer, String> map = Maps.newHashMap();
		map.put(1, "互联网");
		map.put(2, "新材料");
		map.put(3, "新能源");
		map.put(4, "环保技术");
		map.put(5, "先进制造");
		map.put(6, "高端装备");
		map.put(7, "新一代信息技术");
		map.put(8, "生物医药");
		map.put(9, "大健康");
		map.put(10, "电子商务");
		map.put(11, "其它");
		return map;
	}

	@Override
	public List<String> detailImagesUrisHandle(String detailImagesUri){
		List<String> detailImagesUris = Lists.newArrayList();
		if(detailImagesUri.isEmpty()){
			return detailImagesUris;
		}
		detailImagesUris = Lists.newArrayList(detailImagesUri.split(","));
		return detailImagesUris;
	}

	@Override
	public InvestDetailsResult getInvestDetails(Long investId, Long memberId){
		Member member = memberService.accessObject(memberId);
		Invest invest = accessObject(investId);
		if(member.getIdentityType().equals(Member.IDENTITY_TYPE_MEMBER) && !invest.getPublisher().equals(memberId)){
			throw new HandleException("该用户当前身份为个人普通用户身份，不可查看");
		}
		if(!invest.getPublisher().equals(memberId)){
			investOrgService.checkInvestOrgVerify(memberId);
		}
		InvestDetailsResult detailsResult = ControllerPageHandle.convertTo(invest, InvestDetailsResult.class);
		if(!invest.getPublicity().equals(SystemConst.PUBLICITY_PUBLIC) && !invest.getPublisher().equals(memberId)){
			boolean verify = investApplyService.checkApplyVerify(memberId, investId);
			if(!verify){
				detailsResult.setEmail("");
				detailsResult.setContact("");
				detailsResult.setContactPhone("");
				detailsResult.setDisplay(false);
			}else{
				detailsResult.setDetailImagesUris(detailImagesUrisHandle(invest.getDetailImagesUri()));
				detailsResult.setAttachments(JSON.parseArray(invest.getAttachment(), Attachments.class));
			}
		}else{
			detailsResult.setDetailImagesUris(detailImagesUrisHandle(invest.getDetailImagesUri()));
			detailsResult.setAttachments(JSON.parseArray(invest.getAttachment(), Attachments.class));
		}
		return detailsResult;
	}

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void investVerify(Long id, Integer verify, String verifyRemark) {
        Invest invest = accessObject(id);
        invest.setVerify(verify);
        invest.setVerifyDate(LocalDateTime.now());
        String description;
        if(verify.equals(SystemConst.VERIFY_REJECT)){
            invest.setVerifyRemark(verifyRemark);
            description = String.format("您的项目 %s 审核不通过，点击查看详情跳转相应审核结果页", invest.getName());
        }else{
            description = String.format("您的项目 %s 审核通过，点击查看详情跳转相应审核结果页", invest.getName());
        }
		investDao.save(invest);
		if (invest.getPublisher() > 0) {
			mqClient.publish(MQTopics.MEMBER_SEND_MESSAGE, messageService.sendMessageJSON(invest.getPublisher(), Message.MESSAGE_TYPE_VERIFY,
					"项目入驻审核提醒", description, Message.MESSAGE_TARGET_TYPE_ONE_INVEST, invest.getId().toString()));
		}
    }

    @Override
    public InvestProjectResult getInvestProjectTotal(String minDateTime, String maxDateTime, Long days){
		VisualizationDate visual = VisualizationUtil.visualDateHandle(minDateTime, maxDateTime, days);
		InvestProjectResult investProjectResult = new InvestProjectResult();
		List<InvestProjectResult> projectDays = Lists.newArrayList();
		Long projectTotal = 0L;
		for (long i = 0; i <= visual.getDays(); i++) {
			InvestProjectResult projectResult = new InvestProjectResult();
			LocalDateTime startDate = visual.getMaxDate().minusDays(i).with(LocalTime.MIN);
			LocalDateTime endDate = visual.getMaxDate().minusDays(i).with(LocalTime.MAX);
			projectResult.setProjectTotal(investDao.countByCreateDateBetween(startDate, endDate));
			projectResult.setVisualDate(visual.getMaxDate().minusDays(i).format(DateTimeUtils.FORMATTER_DEFAULT_YMD));
			projectTotal = projectTotal + projectResult.getProjectTotal();
			projectDays.add(projectResult);
		}
		investProjectResult.setProjectTotal(projectTotal);
		investProjectResult.setProjectDays(projectDays);
		return investProjectResult;
	}

	@Override
	public void downLoadFile(String filePath, HttpServletResponse response) throws IOException {
		URL url = new URL(aliYunOSSConfig.getDefaultCDNDomain()+"/"+filePath);
		HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
		urlCon.setConnectTimeout(6000);
		urlCon.setReadTimeout(6000);
		int code = urlCon.getResponseCode();
		if (code != HttpURLConnection.HTTP_OK) {
			throw new HandleException("文件读取失败");
		}
		// 读文件流
		DataInputStream in = new DataInputStream(urlCon.getInputStream());
		response.setContentType("application/pdf;charset=UTF-8");
		OutputStream out = response.getOutputStream();

		byte[] b = new byte[1024];
		int read;
		while ((read = in.read(b)) != -1) {
			out.write(b, 0, read);
		}
		in.close();
		out.flush();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void investUpperShelf(Long investId) {
		Invest invest = accessObject(investId);
		if (invest.getUpperStatus().equals(SystemConst.STATUS_UPPER_SHELF)) {
			throw new HandleException("项目已上架，请勿重复操作");
		}
		invest.setUpperStatus(SystemConst.STATUS_UPPER_SHELF);
		investDao.save(invest);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void investLowerShelf(Long investId) {
		Invest invest = accessObject(investId);
		if (invest.getUpperStatus().equals(SystemConst.STATUS_LOWER_SHELF)) {
			throw new HandleException("项目已下架，请勿重复操作");
		}
		invest.setUpperStatus(SystemConst.STATUS_LOWER_SHELF);
		investDao.save(invest);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void investIndexYes(Long investId) {
		Invest invest = accessObject(investId);
		if (invest.getIndexType().equals(SystemConst.INDEX_TYPE_YES)) {
			throw new HandleException("项目已推荐至首页，请勿重复操作");
		}
		invest.setIndexType(SystemConst.INDEX_TYPE_YES);
		investDao.save(invest);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void investIndexNo(Long investId) {
		Invest invest = accessObject(investId);
		if (invest.getIndexType().equals(SystemConst.INDEX_TYPE_NO)) {
			throw new HandleException("项目已取消推荐至首页，请勿重复操作");
		}
		invest.setIndexType(SystemConst.INDEX_TYPE_NO);
		investDao.save(invest);
	}

}