package com.reyun.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.reyun.exception.TipException;
import com.reyun.model.*;
import com.reyun.repository.*;
import com.reyun.service.AppService;
import com.reyun.service.AuthService;
import com.reyun.service.CrowdService;
import com.reyun.service.ReportService;
import com.reyun.task.EmailThread;
import com.reyun.util.*;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;

@Service
public class CrowdServiceImpl implements CrowdService {


    @Autowired
    private ConfigParamRepository configParamRepository;

    @Autowired
    private CrowdRepository crowdRepository;

    @Autowired
    private AccountRepository accountRepository;

    @Autowired
    private AppRepository appRepository;

    @Autowired
    private ReportService reportService;

    @Autowired
    private BlacklistApplicationRepository blacklistApplicationRepository;

    @Autowired
    private BussinessManRepository bussinessManRepository;

    @Autowired
    private AppService appService;

    @Autowired
    private AuthService authService;


    @Override
    public Crowd create(Account account, Crowd source) {
        source.setCreateTime(new Date());
        source.setPayment(0);
        source.setStatus(0);
        source.setRootAccount(account.getRootParent());
        source.setApplyAccount(account.getId());
        String contractCode = requestToBackstage(source);
        if(!"".equals(contractCode)){
            source.setContractCode(contractCode);
        }

        if(source.getAndroidAppKey()!=null){
            App androidApp = appRepository.findByAppkey(source.getAndroidAppKey());
            source.setAndroidAppCreateTime(androidApp.getCreateTime());
        }
        if(source.getIosAppkey()!=null){
            App iosAppApp = appRepository.findByAppkey(source.getIosAppkey());
            source.setIosAppCreateTime(iosAppApp.getCreateTime());
        }

        Crowd crowd = crowdRepository.save(source);
        sendEmail(crowd);
        updateBlackListApplicationTable(crowd);
        return crowd;
    }

    @Override
    public Crowd findDetail(Long id) {
        Crowd crowd = crowdRepository.findOne(id);
        HashMap<String, Object> map = getPriceDetail(crowd);
        crowd.setMap(map);
        return crowd;
    }

    @Override
    public Object findOrders(Long rootParent) {
        List<Crowd> crowds = crowdRepository.findByAccount(rootParent);
        for (Crowd crowd : crowds) {
            HashMap<String, Object> priceDetail = getPriceDetail(crowd);
            long deviceid_cnt = 0;
            double price = 0.0;
            double total = 0.0;
            if (priceDetail.get("value") != null) {
                ArrayList<PriceDetail> values = (ArrayList<PriceDetail>) priceDetail.get("value");
                for (PriceDetail p : values) {
                    deviceid_cnt = deviceid_cnt + p.getDeviceid_cnt();
                    price = p.getPrice();
                    total = total + p.getTotal();
                }
            }

            if(priceDetail.get("special_account")!=null){
                total=total*0.5;
            }

            crowd.setDeviceid_cnt(deviceid_cnt);
            crowd.setPrice(price);
            crowd.setTotal(total);
        }
        return crowds;
    }

    @Override
    public Map<String, Object> findBlackData(Account account) {
        Account one = accountRepository.findOne(account.getRootParent());
        HashMap<String, String> conditions = new HashMap<>();
        List<App> apps = appService.listAppByAccount(account.getId());
        Map<String, Object> total = new HashMap<>();
        StringBuffer appsStr = new StringBuffer();
        for (App app : apps) {
            appsStr = appsStr.append("\'").append(app.getAppkey()).append("\'").append(",");
        }
        String appids = "";
        if (apps.size() != 0) {
            appids = appsStr.substring(0, appsStr.length() - 1);
        }

        List<Long> channelIdList = authService.getAuthChannelList(account.getId());
        StringBuilder channels = new StringBuilder();
        for(Long l:channelIdList){
            channels.append(l).append(",");
        }
        String substring = channels.substring(0, channels.length() - 1);

        conditions.put("channels",substring);
        conditions.put("appids", appids);
        conditions.put("startdate", DateUtil.getBeforeDays(7));
        conditions.put("enddate", DateUtil.format(new Date()));
        conditions.put("iscache", Constant.iscache);
        conditions.put("datatype", "list");
        try {
            Object response = reportService.report(1218L, "black_click_channel_total", one, conditions);
            ReportListResult reportListResult = new ObjectMapper().convertValue(response, ReportListResult.class);
            if (reportListResult!=null&&reportListResult.getVal()!=null&&reportListResult.getVal().size() > 0) {
                total = reportListResult.getVal().get(0);
            } else {
                total.put("num_install_black_deviceid", 0);
                total.put("num_install", 0);
                total.put("num_click", 0);
                total.put("num_install_black", 0);
                total.put("num_black", 0);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        BlacklistApplication blacklistApplication = blacklistApplicationRepository.findByParentAndPast(account.getRootParent());
        List<Crowd> crowdOrders = crowdRepository.findByAccount(account.getRootParent());
        total.put("blacklistApplication", blacklistApplication);
        total.put("crowdOrders", crowdOrders);
        return total;
    }

    @Override
    public ResponseEntity<byte[]> download(Long id) throws UnsupportedEncodingException {

        Crowd one = crowdRepository.findOne(id);
        String s3key="tkio/tkio_pa_devicetag/"+one.getRootAccount()+"/" +id+".gz";
        String filename = id + ".gz";
        final String encodeFileName = URLEncoder.encode(new String(filename.getBytes("UTF-8")), "UTF-8");

        InputStream in = null;
        byte[] content = new byte[0];
        String fileType = "";
        try {
            final String fileName = URLEncoder.encode(filename);
            in = ObjectStorageUtil.getObjectContentStream(Constant.bucket,s3key);
            fileType = URLConnection.guessContentTypeFromName(fileName);
            content = IOUtils.toByteArray(in);

            HttpHeaders headers = new HttpHeaders();
            headers.set("filename", encodeFileName);
            headers.add("content-disposition", "attachment; filename=" + encodeFileName);
            headers.add("Content-Type", fileType);

            return new ResponseEntity<>(content, headers, HttpStatus.CREATED);
        } catch (IOException e) {
            throw new TipException("文件不存在");
        } finally {
            IOUtils.closeQuietly(in);
        }
    }


    @Override
    public HashMap<String, Object> getPriceDetail(Crowd crowd) {

        HashMap<String, String> conditions = new HashMap<>();
        conditions.put("ryorderid", crowd.getId() + "");
        conditions.put("iscache", "0");

        final String url = Constant.reporturl + "/api/support/crowd/0";
        String responseJson = HttpClientUtil.doHttpPostRequest(url, "support", conditions);

        ArrayList<PriceDetail> priceDetailsList = new ArrayList<>();
        HashMap<String, Object> map = new HashMap<>();
        double totalMoney = 0.00;
        if (ValidateUtil.isValid(responseJson) && responseJson.contains("key")) {
            JSONObject jsonObject = JSONObject.parseObject(responseJson);
            JSONArray name = (JSONArray) jsonObject.get("name");
            JSONArray key = (JSONArray) jsonObject.get("key");
            JSONArray val = (JSONArray) jsonObject.get("val");
            HashMap<String, Object> hashMap = new HashMap<>();
            for (int i = 0; i < key.size(); i++) {
                String appkey1 = (String) key.get(i);
                String appkey=appkey1.substring(1,appkey1.length()-1);
                for (int j = 0; j < name.size(); j++) {
                    String nm = (String) name.get(j);
                    JSONArray values = (JSONArray) val.get(j);
                    Object o = values.get(i);
                    hashMap.put(nm, o);
                }
                hashMap.put("appid", appkey);
                String s = JSON.toJSONString(hashMap);
                PriceDetail priceDetail = JSONObject.parseObject(s, PriceDetail.class);
                App app = appRepository.findByAppkey(priceDetail.getAppid());
                priceDetail.setApp_name(app.getName());
                priceDetail.setProduct_num(1);
                priceDetail.setPlatform(app.getPlatform());
                totalMoney = totalMoney + priceDetail.getTotal();
                priceDetailsList.add(priceDetail);
            }
        }
        map.put("columnTitle", new String[]{"系统", "产品数量", "产品名称", "标签数量", "新旧标识", "设备数量", "单价", "折扣", "总价"});
        map.put("columnName", new String[]{"platform", "product_num", "app_name", "tag_cnt_mark", "new_mark", "deviceid_cnt", "price", "discount", "total"});
        map.put("value", priceDetailsList);
        map.put("totalMoney", totalMoney);

        String[] special_accounts = configParamRepository.findParamsByKey("special_account").split(",");
        for(String s:special_accounts){
            Account account = accountRepository.findAccountByEmail(s);
            Crowd byAccount = crowdRepository.findFirstOrder(crowd.getRootAccount());
            if(account!=null && account.getId().equals(crowd.getRootAccount()) && (DateUtil.parseDate("2018-07-01").getTime()-new Date().getTime()>=0) && (byAccount==null || byAccount.getId().equals(crowd.getId()))){
                map.put("special_account",true);
                map.put("totalMoney", totalMoney*0.5);
            }
        }
        return map;
    }

    @Override
    public Map<String, Object> findArouseData(Account account) {
        HashMap<String, String> conditions = new HashMap<>();
        Map<String, Object> total = new HashMap<>();
        Account one = accountRepository.findOne(account.getRootParent());



        BlacklistApplication blacklistApplication = blacklistApplicationRepository.findByParentAndArouse(account.getRootParent());
        if(blacklistApplication!=null&&blacklistApplication.getStatus()==2){
            String today = DateUtil.getBeforeDays(0);
            int surplusDays=0;
            try {
                surplusDays = DateUtil.daysBetween(today, blacklistApplication.getPastDate());
                total.put("surplusDays", surplusDays);
            }catch (Exception e){
                total.put("surplusDays", null);
            }

            if (surplusDays > 0) {//调起服务状态正常下查询近七天调起数据
                List<App> apps = appService.listAppByAccount(account.getId());
                StringBuffer appsStr = new StringBuffer();
                for (App app : apps) {
                    appsStr = appsStr.append("\'").append(app.getAppkey()).append("\'").append(",");
                }
                String appids = "";
                if (apps.size() != 0) {
                    appids = appsStr.substring(0, appsStr.length() - 1);
                }
                conditions.put("appids", appids);
                conditions.put("startdate", DateUtil.getBeforeDays(7));
                conditions.put("enddate", DateUtil.format(new Date()));
                conditions.put("iscache", Constant.iscache);
                conditions.put("datatype", "list");
                try {
                    if(!appids.equals("")){
                        Object response = reportService.report(1218L, "arouse_total", one, conditions);
                        ReportListResult reportListResult = new ObjectMapper().convertValue(response, ReportListResult.class);
                        if (reportListResult!=null&&reportListResult.getVal()!=null&&reportListResult.getVal().size() > 0) {
                            total.putAll( reportListResult.getVal().get(0));
                        } else {
                            total.put("num_arouse", 0);
                        }
                    }else {
                        total.put("num_arouse", 0);
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        total.put("blacklistApplication", blacklistApplication);
        return total;
    }

    public void sendEmail(Crowd crowd) {
        Account account = accountRepository.findOne(crowd.getRootAccount());
        String subject = "广告监测平台人群分析功能购买申请";
        String phone = account.getPhone() == null ? "" : "联系手机为" + account.getPhone() + ",";
        String contents = "<!doctype html><html><head></head><body> " +
                "Larry:</br>" +
                "在" + DateUtil.format(crowd.getCreateTime()) + "日收到" + (null == account.getCompany() ? "" : account.getCompany()) + " " + account.getEmail() + " " + "提交的人群分析功能购买申请," + phone + "请反馈至销售同学进行后续跟进,\n" +
                "或至Office查看详情 </br>" +
                "<a href=\"" + Constant.adminUrl + "\">" + Constant.adminUrl + "</a>" +
                "</body></html>";
        ArrayList<String> emailList = new ArrayList<>();
        Collections.addAll(emailList, configParamRepository.findParamsByKey("operate_email").split(","));
        try {
            EmailThread emailThread = new EmailThread(subject, contents, emailList);
            emailThread.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void updateBlackListApplicationTable(Crowd crowd) {
        BlacklistApplication application = new BlacklistApplication();
        Account applyAccount = accountRepository.findOne(crowd.getApplyAccount());
        Account rootAccount = accountRepository.findOne(crowd.getRootAccount());

        application.setName(applyAccount.getEmail());
        application.setParentEmail(rootAccount.getEmail());
        application.setCompany(rootAccount.getCompany());
        application.setMenu("crowd");
        application.setParentName(rootAccount.getName());
        application.setTell(rootAccount.getPhone());
        application.setPubDate(crowd.getCreateTime());
        application.setStatus(crowd.getPayment());
        application.setAccountId(crowd.getRootAccount());
        application.setCrowdId(crowd.getId());
        application.setApplyDate(crowd.getCreateTime());
        application.setParentAccount(crowd.getRootAccount());
        application.setPastDate(rootAccount.getPastDate());

        blacklistApplicationRepository.save(application);
    }


    private String requestToBackstage(Crowd crowd) {
        Account rootAccount = accountRepository.findOne(crowd.getRootAccount());
        String salesMan = bussinessManRepository.findEmail(rootAccount.getBussinessman());
        String leader = bussinessManRepository.findLeaderByBussinessMan(rootAccount.getBussinessman());

        HashMap<String, String> conditions = new HashMap<>();
        conditions.put("product", "trackingio");
        conditions.put("myBodyCode", "BJ");
        if("peter@reyun.com".equals(leader)){
            conditions.put("myBodyCode", "HEGS");
        }
        conditions.put("email", rootAccount.getEmail());
        conditions.put("saleName", salesMan);
        conditions.put("priceLevelName", "analysis");

        String url = Constant.backstage + "/api/tkio/contract/build";
        String s2 = JSON.toJSONString(conditions);
        String responseJson = "";

        try {
            responseJson = HttpClientUtil.HttpGetByJson(url, s2);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String contractCode = "";
        if (ValidateUtil.isValid(responseJson)) {
            JSONObject jsonObject = JSONObject.parseObject(responseJson);
            Integer code = (Integer) jsonObject.get("code");
            JSONObject content = (JSONObject) jsonObject.get("content");

            if (code == 200 && content != null) {
                contractCode = (String) content.get("contractCode");
            }
        }
        return contractCode;
    }
}