package com.reyun.saas.mob.user.service.impl;

import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.reyun.saas.common.constants.WorkOrderExportEnum;
import com.reyun.saas.common.framework.component.AwsS3Component;
import com.reyun.saas.common.model.Constant;
import com.reyun.saas.common.restResult.PageParam;
import com.reyun.saas.common.restResult.RestResult;
import com.reyun.saas.common.restResult.ResultCode;
import com.reyun.saas.common.restResult.ResultGenerator;
import com.reyun.saas.common.util.CommonUtil;
import com.reyun.saas.common.util.IPUtils;
import com.reyun.saas.mob.user.dao.AppMapper;
import com.reyun.saas.mob.user.dao.UserMapper;
import com.reyun.saas.mob.user.dao.WorkOrderMapper;
import com.reyun.saas.mob.user.domain.App;
import com.reyun.saas.mob.user.domain.User;
import com.reyun.saas.mob.user.domain.WorkOrderExport;
import com.reyun.saas.mob.user.dto.user.WorkOrderLogDTO;
import com.reyun.saas.mob.user.service.AuthService;
import com.reyun.saas.mob.user.service.WorkOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class WorkOrderServiceImpl implements WorkOrderService {


    /**
     * s3上日志文件的后缀
     */
    private static final String LOGFILE = "%s.tar.gz";

    /**
     * s3上报表文件的后缀
     */
    private static final String REPORTFILE = "%s.csv";

    private static final String APP = "app";

    private static final String CREATE_USER = "createUser";


    @Resource
    private UserMapper userMapper;

    @Resource
    private WorkOrderMapper workOrderMapper;

    @Resource
    private AppMapper appMapper;

    @Resource
    private AwsS3Component awsS3Component;

    @Resource
    private AuthService authService;


    @Override
    public RestResult list(Map<String, Object> map, Long loginUserId) {
        //获取筛选条件
        String appkey = (String) map.get("appkey");
        String type = (String) map.get("type");
        String model = (String) map.get("model");
        String createUser = (String) map.get("createUser");

        //获取分页对象
        PageParam pageParam = CommonUtil.getPageParam(map,"DESC","createDate");

        User loginUser = userMapper.selectByPrimaryKey(loginUserId);

        if (loginUser == null) {
            return ResultGenerator.genResult(ResultCode.USER_NOT_EXIST);
        }

        List<App> apps = authService.getAppByUserIncludeDel(loginUser);
        if (CollectionUtils.isEmpty(apps)) {
            return ResultGenerator.genSuccessResult();
        }

        Example example = new Example(WorkOrderExport.class);
        Map<String, App> appkeyAndApp = apps.stream().collect(Collectors.toMap(App::getAppkey, v -> v, (v1, v2) -> v1));

        if (!StringUtils.isEmpty(appkey)) {
            example.and().andEqualTo("appkey", appkey);
        }else{
            example.and().andIn("appkey",appkeyAndApp.keySet());
        }
        if (!StringUtils.isEmpty(type)) {
            //类型
            example.and().andEqualTo("type", type);
        }
        if (!StringUtils.isEmpty(model)) {
            //所属模块
            example.and().andEqualTo("model", model);
        }
        if (!StringUtils.isEmpty(createUser)) {
            //创建人  注意昵称可以重复
            Example userExample = new Example(User.class);
            userExample.and().andEqualTo("actualName",createUser);
            List<User> createUserOne = userMapper.selectByExample(userExample);
            List<Long> createIds = null;
            if (CollectionUtils.isEmpty(createUserOne)) {
                createIds =  new ArrayList<Long>(){{add(-1L);}};
            }else{
                createIds = createUserOne.stream().map(User::getId).collect(Collectors.toList());
            }
            example.and().andIn("createUserId", createIds);
        }
        example.and().andEqualTo("delFlag", false);

        //插件分页  默认排序为创建时间倒序
        PageHelper.startPage(pageParam.getPage(),pageParam.getSize(),pageParam.getOrderBy());
        List<WorkOrderExport> workOrderExports = workOrderMapper.selectByExample(example);

        //设置app名称 创建人名称  下载人名称
        if(!CollectionUtils.isEmpty(workOrderExports)){
            Set<Long> userIds = workOrderExports.stream().filter(v -> v.getCreateUserId()!=null).map(WorkOrderExport::getCreateUserId).collect(Collectors.toSet());
            Set<Long> downloadUserIds = workOrderExports.stream().filter(v -> v.getDownloadUserId()!=null).map(WorkOrderExport::getDownloadUserId).collect(Collectors.toSet());
            userIds.addAll(downloadUserIds);

            Example userExample = new Example(User.class);
            userExample.and().andIn("id",userIds);
            List<User> users = userMapper.selectByExample(userExample);
            Map<Long, User> idAndUser = users.stream().collect(Collectors.toMap(User::getId, v -> v, (v1, v2) -> v1));

            for (WorkOrderExport workOrderExport : workOrderExports) {
                App app = appkeyAndApp.get(workOrderExport.getAppkey());
                User createUserTemp = idAndUser.get(workOrderExport.getCreateUserId());
                User downloadUserTemp = idAndUser.get(workOrderExport.getDownloadUserId());

                //设置app名称
                workOrderExport.setAppName(app != null ?app.getAppName():"-");
                //设置创建人下载人名称
                workOrderExport.setCreateUser(createUserTemp != null?createUserTemp.getActualName():"-");
                workOrderExport.setDownloadUser(downloadUserTemp != null?downloadUserTemp.getActualName():"-");
            }
        }

        PageInfo<WorkOrderExport> pageInfo = new PageInfo<WorkOrderExport>(workOrderExports);

        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @Override
    public RestResult create(WorkOrderLogDTO source, Long logUserId) {
        User user = userMapper.selectByPrimaryKey(logUserId);
        if (user == null) {
            return ResultGenerator.genResult(ResultCode.USER_NOT_EXIST);
        }
        String sourceJson = null;

        if(WorkOrderExportEnum.TYPE_REPORT.getCode().equals(source.getWorkOrderType())){
            sourceJson = JSONUtil.toJsonStr(source.getReportParams());
        }else{
            Map<String,Object> map = new HashMap<>();
            String os = source.getOs();
            os = "1".equals(os)?"iOS":os;
            os = "2".equals(os)?"Android":os;
            map.put("os",os);
            map.put("cid",source.getCids());
            sourceJson = JSONUtil.toJsonStr(map);
        }

        Example example = new Example(App.class);
        example.and().andEqualTo("appkey", source.getAppkey());
        App app = appMapper.selectOneByExample(example);
        if(app == null){
            return ResultGenerator.genFailResult("app不存在");
        }

        //todo 后续添加其他角色注意这里
        WorkOrderExport workOrderExport = WorkOrderExport.builder()
                .appkey(source.getAppkey())
                .createUserId(user.getId())
                .createDate(new Date())
                .delFlag(false)
                .status(WorkOrderExportEnum.EXPORT_INIT.getCode())
                //todo 日志的所属模块后续可能要改
                .model(source.getWorkOrderModel())
                .beginDate(source.getBeginDate())
                .endDate(source.getEndDate())
                .msg(WorkOrderExportEnum.EXPORT_INIT.getName())
                .source(sourceJson)
                .type(source.getWorkOrderType())
                .reportName(source.getReportName())
                .workOrderName(getWorkOrderName(source, app)).build();

        workOrderMapper.insert(workOrderExport);

        return ResultGenerator.genSuccessResult(workOrderExport);
    }

    @Override
    public RestResult download(HttpServletRequest request,Long wordOrderId, Long loginUserId) {

        User user = userMapper.selectByPrimaryKey(loginUserId);
        WorkOrderExport workOrderExport = workOrderMapper.selectByPrimaryKey(wordOrderId);

        //todo 校验当前用户是否拥操作该工单的权限  如果后续有更细的权限注意这里
        if (!authService.checkUserAppAuth(user, workOrderExport.getAppkey())) {
            return ResultGenerator.genResult(ResultCode.FORBID_OPERATION);
        }

        String key = formatKey(workOrderExport.getType(),workOrderExport.getWorkOrderName());
        String downloadIP = IPUtils.getIpAddr(request);

        String url = null;
        if (awsS3Component.doesObjectExist(key)) {
            url = awsS3Component.generatePresignedUrl(key, 10 * 1000).toString();
        }

        if(url == null){
            return ResultGenerator.genFailResult("文件不存在");
        }else{
            //修改工单状态
            workOrderExport.setDownloadDate(new Date());
            workOrderExport.setDownloadUserId(user.getId());
            workOrderExport.setDownloadip(downloadIP);
            workOrderMapper.updateByPrimaryKeySelective(workOrderExport);

            Map<String,Object> result = new HashMap<>();
            result.put("url",url.toString());
            return ResultGenerator.genSuccessResult(result);
        }
    }

    @Override
    public RestResult retry(Long wordOrderId, Long loginUserId) {

        User user = userMapper.selectByPrimaryKey(loginUserId);
        WorkOrderExport workOrderExport = workOrderMapper.selectByPrimaryKey(wordOrderId);

        if (!WorkOrderExportEnum.EXPORT_FAILED.getCode().equals(workOrderExport.getStatus())) {
            return ResultGenerator.genFailResult("该工单状态正常 无法重试");
        }

        //todo 校验当前用户是否拥操作该工单的权限  如果后续有更细的权限注意这里
        if (!authService.checkUserAppAuth(user, workOrderExport.getAppkey())) {
            return ResultGenerator.genResult(ResultCode.FORBID_OPERATION);
        }

        WorkOrderExport build = WorkOrderExport.builder()
                .id(workOrderExport.getId())
                .status(WorkOrderExportEnum.EXPORT_INIT.getCode())
                .build();

        workOrderMapper.updateByPrimaryKeySelective(build);

        return ResultGenerator.genSuccessResult();
    }

    @Override
    public RestResult delete(Long wordOrderId, Long loginUserId) {
        User user = userMapper.selectByPrimaryKey(loginUserId);
        WorkOrderExport workOrderExport = workOrderMapper.selectByPrimaryKey(wordOrderId);

        //todo 校验当前用户是否拥操作该工单的权限  如果后续有更细的权限注意这里
        if (!authService.checkUserAppAuth(user, workOrderExport.getAppkey())) {
            return ResultGenerator.genResult(ResultCode.FORBID_OPERATION);
        }

        WorkOrderExport build = WorkOrderExport.builder()
                .id(workOrderExport.getId())
                .delFlag(true)
                .build();

        workOrderMapper.updateByPrimaryKeySelective(build);
        return ResultGenerator.genSuccessResult();
    }

    @Override
    public RestResult screening(String key, String os, Long loginUserId) {
        String platform = !StringUtils.isEmpty(os) && os.equals("1")? Constant.OS_IOS:Constant.OS_ANDROID;
        User loginUser = userMapper.selectByPrimaryKey(loginUserId);

        if (loginUser == null) {
            return ResultGenerator.genResult(ResultCode.USER_NOT_EXIST);
        }

        List<App> apps = authService.getAppByUserIncludeDel(loginUser);
        if(!StringUtils.isEmpty(os)){
            apps = apps.stream().filter(v -> v.getOs().equals(platform)).collect(Collectors.toList());
        }
        if(CollectionUtils.isEmpty(apps)){
            return ResultGenerator.genSuccessResult();
        }
        List<String> appkeys = apps.stream().map(App::getAppkey).collect(Collectors.toList());

        List<Map<String, Object>> result = new ArrayList<>();
        if (APP.equals(key)) {
            //工单app下拉筛选列表
            List<App> appByAppkeyLinkWorkOrder = appMapper.findAppByAppkeyLinkWorkOrder(appkeys);
            result = appByAppkeyLinkWorkOrder.stream().map(v -> {
                Map<String,Object> temp = new LinkedHashMap<>();
                temp.put("app_name",v.getAppName());
                temp.put("appkey",v.getAppkey());
                return temp;
            }).collect(Collectors.toList());
        } else if (CREATE_USER.equals(key)) {
            //工单创建人下拉筛选列表
            List<Map<String,Object>> createUserNames = workOrderMapper.findCreateUser(appkeys);
            result = createUserNames.stream().map(v -> {
                Map<String,Object> temp = new LinkedHashMap<>();
                temp.put("text",v.get("createUser"));
                temp.put("value",v.get("createUser"));
                return temp;
            }).collect(Collectors.toList());
        }

        return ResultGenerator.genSuccessResult(result);
    }


    //【操作系统】_【BundleID】_【所属模块】_【时间范围-起始时间】_【时间范围-结束时间】_【时间戳】
    private static String getWorkOrderName(WorkOrderLogDTO source, App app) {
        //1为IOS  2为Android
        String os = source.getOs();
        os = "1".equals(os)?"iOS":os;
        os = "2".equals(os)?"Android":os;

        String bid = app.getBid();
        StringBuffer stringBuffer = new StringBuffer();
        String reportName = WorkOrderExportEnum.getNameByCode(source.getReportName())==null?"":WorkOrderExportEnum.getNameByCode(source.getReportName())+"_";
        stringBuffer.append(os).append("_").append(bid).append("_")
                .append(WorkOrderExportEnum.getNameByCode(source.getWorkOrderModel())).append("_").append(reportName).append(source.getBeginDate()).append("_")
                .append(source.getEndDate()).append("_").append(System.currentTimeMillis());
        return stringBuffer.toString();
    }

    /**
     * 获取s3中工单文件名称
     * @param type 工单类型  日志 / 报表
     * @param filename 文件名称
     * @return s3全路径
     */
    private String formatKey(String type,String filename) {

        if ("log".equals(type)) {
            filename = String.format(LOGFILE,filename);

        }else if("report".equals(type)){
            filename = String.format(REPORTFILE,filename);
        }

        return "work_order" + "/"+type+"/" + filename;
    }

}
