package com.reyun.controller.manage;

import com.reyun.dic.DownloadStatusEnumType;
import com.reyun.dic.FunctionEnumType;
import com.reyun.dic.LogEnumType;
import com.reyun.dic.OperateObjectEnumType;
import com.reyun.exception.TipException;
import com.reyun.model.Account;
import com.reyun.model.App;
import com.reyun.model.ExportReportInfo;
import com.reyun.security.annotation.CurrentAccount;
import com.reyun.service.AppService;
import com.reyun.service.ExportReportInfoService;
import com.reyun.service.UserLogService;
import com.reyun.util.AwsS3Util;
import com.reyun.util.Constant;
import com.reyun.util.ResultModel;
import com.reyun.util.ResultStatus;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Created by zxy on 27/04/2017.
 * description:
 */
@Controller
@RequestMapping("/mng/export/report/{app}")
public class ExportReportInfoController {
    @Autowired
    private AppService appService;
    @Autowired
    UserLogService userLogService;

    @Autowired
    ExportReportInfoService exportService;


    @RequestMapping(value = "findall", method = RequestMethod.GET)
    @ResponseBody
    public ResultModel findAll(@CurrentAccount Account loginAccount, @PathVariable Long app) {
        return ResultModel.OK(exportService.findByApp(loginAccount, app));
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    public ResultModel delete(@PathVariable Long id) {
        exportService.delete(id);
        return ResultModel.OK();
    }

    /**
     * 漏斗、事件、自定义留存，有id的需要前端将id传过来，以保证文件名的唯一性.
     */
    @RequestMapping(value = "generatefile", method = RequestMethod.POST)
    @ResponseBody
    public ResultModel addExportTask(final HttpServletRequest request, @PathVariable("app") Long app, @RequestBody ExportReportInfo resource, @CurrentAccount Account loginAccount) {

        App appEntity = appService.findById(app);
        if (appEntity == null) {
            throw new TipException("应用不存在");
        }

        if (!exportService.validFileName(resource)) {
            return ResultModel.ERROR(ResultStatus.EXPORT_DATA_EXIST);
        }

        //根据不同的功能类型，存储不同的conditions.funnel,customretention,detailcustomretention,commonretention,event,normal
        if (StringUtils.isEmpty(resource.getConditions())) {
            throw new TipException("导出条件不能为空");
        }
        JSONObject conditions = JSONObject.fromObject(resource.getConditions());

        String timestamp = String.valueOf(new Date().getTime());

        //根据报表类型,生成不同的唯一标示的文件名
        String midFileName = "";
        if (resource.getFunctionType().equals(FunctionEnumType.REPORT.getKey())) {

            midFileName = resource.getReportName() + "_" + timestamp + "_" + (!StringUtils.isEmpty(resource.getSubType()) ? resource.getSubType() : "");
/*            List<Campaign> campaignList = campaignRepository.findAll(app);

            StringBuffer sb = new StringBuffer();
            for(Campaign campaign:campaignList){
                String campaignid = campaign.getCampaignid()+",";
                sb.append(campaignid);
            }
            String campaignidStr = sb.append("_default_").toString();
            conditions.put("campaignid",campaignidStr);*/

        } else if (resource.getFunctionType().equals(FunctionEnumType.FUNNEL.getKey())) {

            midFileName = FunctionEnumType.FUNNEL.getKey() + "_" + timestamp + "_" + (null == resource.getFunctionId() ? String.valueOf(new Date().getTime()) : resource.getFunctionId());

        } else if (resource.getFunctionType().equals(FunctionEnumType.EVENTSTATS.getKey())) {

            midFileName = FunctionEnumType.EVENTSTATS.getKey() + "_" + timestamp + "_" + (null == resource.getFunctionId() ? String.valueOf(new Date().getTime()) : resource.getFunctionId());

        } else if (resource.getFunctionType().equals(FunctionEnumType.COMPLICATED_EVENTS.getKey())) {

            midFileName = FunctionEnumType.COMPLICATED_EVENTS.getKey() + "_" + timestamp + "_" + (null == resource.getFunctionId() ? String.valueOf(new Date().getTime()) : resource.getFunctionId());

        } else if (resource.getFunctionType().equals(FunctionEnumType.CUSTOMRETENTION.getKey())) {

            midFileName = FunctionEnumType.CUSTOMRETENTION.getKey() + "_" + timestamp + "_" + (null == resource.getFunctionId() ? String.valueOf(new Date().getTime()) : resource.getFunctionId());

        } else if (resource.getFunctionType().equals(FunctionEnumType.DETAILCUSTOMRETENTION.getKey())) {

            midFileName = FunctionEnumType.DETAILCUSTOMRETENTION.getKey() + "_" + timestamp + "_" + (null == resource.getFunctionId() ? String.valueOf(new Date().getTime()) : resource.getFunctionId());

        } else if (resource.getFunctionType().equals(FunctionEnumType.COMMONRETENTION.getKey())) {

            midFileName = resource.getReportName();

            //是否按设备
            if (conditions.containsKey("isdevice") && conditions.getBoolean("isdevice")) {
                midFileName = "device_" + midFileName + "_" + timestamp;
            }

            //是否是详情
            if (conditions.containsKey("isdetail") && conditions.getBoolean("isdetail")) {
                midFileName = midFileName + "detail_" + timestamp;
            }
        }

        //注收比日期参数特殊处理
        String startDate = conditions.containsKey("startdate") ? conditions.getString("startdate") : conditions.getString("install_startdate");
        String endDate = conditions.containsKey("enddate") ? conditions.getString("enddate") : conditions.getString("install_enddate");

        String fileName = appEntity.getAppkey() + "_" + midFileName + "_" + startDate + "_" + endDate + ".csv";

        resource.setApp(app);
        resource.setFileName(fileName);
        resource.setAccount(loginAccount.getId());
        resource.setAccountName(loginAccount.getName());
        Date date = new Date();
        resource.setCreateTime(date);
        resource.setModifyTime(date);
        resource.setStatus(DownloadStatusEnumType.INIT.getCode());
        resource.setReportType(conditions.getString("datatype"));
        resource.setStartDate(startDate);
        resource.setEndDate(endDate);
        resource.setConditions(JSONObject.fromObject(conditions).toString());

        return ResultModel.OK(exportService.save(resource));

    }

    @RequestMapping(value = "refresh/{id}", method = RequestMethod.PUT)
    @ResponseBody
    public ResultModel refreshDownload(@PathVariable("app") Long app, @PathVariable Long id, @CurrentAccount Account loginAccount) throws IOException {
        ExportReportInfo info = exportService.findOne(id);
        if (info == null)
            throw new TipException("下载记录不存在");

        return ResultModel.OK(exportService.updateStatus(id, DownloadStatusEnumType.INIT.getCode(), loginAccount.getId()));
    }

    @RequestMapping(value = "download/{id}", method = RequestMethod.GET)
    public void getDownloadResponseEntity(HttpServletRequest request, HttpServletResponse response, @PathVariable("app") Long app, @PathVariable Long id,
                                          @CurrentAccount Account loginAccount) throws IOException {

        ExportReportInfo info = exportService.findOne(id);

        userLogService.insertLog(loginAccount, LogEnumType.DOWNLOAD.getCode(),
                LogEnumType.DOWNLOAD.getName() + "报表下载 ", info,app, OperateObjectEnumType.REPORTDOWN.getCode(), request);

        if (info == null) {
            //无文件时候 返回204
            response.setStatus(HttpServletResponse.SC_NO_CONTENT);
            return;
        }

        App appEntity = this.appService.findById(app);

        String downloadIP = request.getHeader("x-forwarded-for") == null ? request.getRemoteAddr() : request.getHeader("x-forwarded-for");
        String filename = appEntity.getName() + "_" + info.getName() + "_" + info.getStartDate() + "_" + info.getEndDate()
                + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(info.getCreateTime()) + ".csv";

        //为了解决中文名称乱码问题
        filename = new String(filename.getBytes("UTF-8"));
        filename = URLEncoder.encode(filename, "UTF-8");
        //设置结果集的中文
        response.setCharacterEncoding("GB18030");
        response.setHeader("filename", filename);
        response.setHeader("content-disposition", "attachment; filename=" + filename);
        response.setHeader("Content-Type", "text/csv");

        InputStream in = null;
        String content = "";

        try {

            in = AwsS3Util.getInstance().downloadStreamFromS3(Constant.bucket, "trackingio/reportdownload/" + info.getFileName());
            content = IOUtils.toString(in);

            if (content.contains("\t")) {
                content = content.replace("\t", ",");
            }

            response.getWriter().write(content);

        } catch (IOException e) {
            //无文件时候 返回204
            e.printStackTrace();
            response.setStatus(HttpServletResponse.SC_NO_CONTENT);
            return;

        } finally {
            IOUtils.closeQuietly(in);
        }

        //更新下载人和IP
        exportService.updateDownloadInfo(info.getId(), loginAccount, downloadIP);
    }

    @RequestMapping(value = "checkexist/{id}", method = RequestMethod.GET)
    @ResponseBody
    public ResultModel checkFileExist(@PathVariable("app") Long app, @PathVariable Long id, @CurrentAccount Account loginAccount) throws MalformedURLException {

        /*ExportReportInfo info = exportService.findOne(id);
        if (info == null) {
            throw new TipException("下载记录不存在");
        }

        URL url = new URL(Constant.S3_ROOTDIR + File.separator + "reportdownload" + File.separator + URLEncoder.encode(info.getFileName()));
        InputStream in = null;

        try {
            in = url.openStream();
        } catch (IOException e) {
            return ResultModel.OK(false);
        } finally {
            if (in != null) {
                IOUtils.closeQuietly(in);
            }
        }*/
        return ResultModel.OK(true);
    }

}


