package com.gree.mall.manager.logic.common;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.commonmapper.AdminMapper;
import com.gree.mall.manager.config.wx.WxConfiguration;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import com.gree.mall.manager.utils.ApplicationContextUtils;
import com.gree.mall.manager.utils.CommonUtils;
import com.gree.mall.manager.utils.RedisUtil;
import com.gree.mall.manager.utils.oss.OSSUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.TreeMap;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class CommonLogic {

    @Value("${spring.profiles.active}")
    private String active;
    @Value("${wechat.payment.notifyUrl}")
    private String notifyUrl;

    @Value("${wechat.keyPath}")
    private String keyPath;

    private final RedisUtil redisUtil;

    private final AdminCompanyWechatService AdminCompanyWechatService;

    private final CommonFileService commonFileService;

    private final RegionService regionService;

    private final AdminUserService adminUserService;

    private final AdminCompanyWechatService adminCompanyWechatService;

    private final AdminMapper adminMapper;

    private final AdminUserPermissionsRelaService adminUserPermissionsRelaService;

    private final WechatLogic wechatLogic;

    private final AdminWebsitService adminWebsitService;

    private final AdminDeptWebsitService adminDeptWebsitService;


    public AdminUserCom getAdminUser() {
        HttpServletRequest request = ApplicationContextUtils.getHttpServletRequest();
        return this.getAdminUser(request);
    }

    /**
     * 获取帐号信息
     */
    public AdminUserCom getAdminUser(HttpServletRequest request) {
        String userId = CommonUtils.getUserId(request);
        //方便测试用
        if (userId == null && !active.equals("prd")) {
            AdminUser admin = adminUserService.lambdaQuery().eq(AdminUser::getUserName, "admin").one();
            AdminUserCom adminUserCom = new AdminUserCom();
            BeanUtils.copyProperties(admin, adminUserCom);
            return adminUserCom;
        }
        AdminUser adminUser = adminUserService.getById(userId);
        if (adminUser == null || !adminUser.getStatus()) {
            throw new RemoteServiceException("帐号不存在或已被禁用");
        }
        AdminUserCom adminUserCom = new AdminUserCom();
        BeanUtils.copyProperties(adminUser, adminUserCom);

        this.queryUserSysRela(adminUserCom);

        if (StringUtils.isNotBlank(adminUser.getWebsitId())) {
            final AdminWebsit adminWebsit = adminWebsitService.getById(adminUser.getAdminUserId());
            adminUserCom.setAdminWebsit(adminWebsit);
        }

        return adminUserCom;
    }

    /**
     * 查询用户系统关系
     */
    public AdminUserCom queryUserSysRela(AdminUserCom adminUserCom) {
        String userId = adminUserCom.getAdminUserId();


        final List<AdminUserPermissionsRela> permissionsRelas = adminUserPermissionsRelaService.lambdaQuery()
                .eq(AdminUserPermissionsRela::getAdminUserId, userId)
                .list();

        // 部门
        final List<String> deptList = permissionsRelas.stream()
                .filter(AdminUserPermissionsRela::getIsDept)
                .map(AdminUserPermissionsRela::getAdminUserPermissionsId)
                .distinct()
                .collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(deptList) && deptList.contains("1")) {
            // 有平台权限，直接返回
            return adminUserCom;
        }

        // 商户
        final List<String> companyList = permissionsRelas.stream()
                .map(AdminUserPermissionsRela::getCompanyId)
                .distinct()
                .collect(Collectors.toList());
        adminUserCom.setAdminCompanyIds(companyList);

        // 商家
        List<String> websitList = permissionsRelas.stream()
                .filter(v -> !v.getIsDept())
                .map(AdminUserPermissionsRela::getAdminUserPermissionsId)
                .distinct()
                .collect(Collectors.toList());
        adminUserCom.setAdminWebsitIds(websitList);

        adminUserCom.setAdminDeptIds(deptList);

        if (CollectionUtil.isNotEmpty(deptList)) {
            // 找出部门下的商家
            for (String deptId : deptList) {
                final List<AdminDeptWebsit> adminDeptWebsits = adminDeptWebsitService.lambdaQuery()
                        .eq(AdminDeptWebsit::getAdminDeptId, deptId)
                        .list();
                final List<String> websitIdList = adminDeptWebsits.stream()
                        .map(AdminDeptWebsit::getWebsitId)
                        .collect(Collectors.toList());
                websitList.addAll(websitIdList);
            }
            adminUserCom.setAdminWebsitIds(websitList.stream().distinct().sorted().collect(Collectors.toList()));
        }

        return adminUserCom;
    }

    /**
     * 获取企业微信配置
     */
    public AdminCompanyWechat getAdminCompanyWechat(String companyWechatId) {
        AdminCompanyWechat adminCompanyWechat = adminCompanyWechatService.getById(companyWechatId);
        return adminCompanyWechat;
    }

    /**
     * 获取所有企业微信配置
     */
    public List<AdminCompanyWechat> getAdminCompanyList() {
        List<AdminCompanyWechat> list = adminCompanyWechatService.list();
        return list;
    }

    /**
     * 刷新微信相关配置
     */
    public void reloadWxConfig() {
        List<AdminCompanyWechat> list = AdminCompanyWechatService.list();
        log.info("【刷新微信配置开始】");
        WxConfiguration.reloadWxConfig(list, redisUtil, keyPath, notifyUrl);
        log.info("【刷新微信配置成功】");
    }

    /**
     * 附件归属绑定
     */
    public void bindFile(String objId, String objType, List<String> fileIds) {
        //先删除后绑定
        commonFileService.lambdaUpdate()
                .eq(CommonFile::getObjId, objId)
                .eq(CommonFile::getObjType, objType)
                .notIn(CommonFile::getId, fileIds).remove();

        for (int i = 0; i < fileIds.size(); i++) {
            //这里分开每次存储的时候，每个图片创建时间加1秒，方便图片排序用
            commonFileService.lambdaUpdate()
                    .set(CommonFile::getObjId, objId)
                    .set(CommonFile::getObjType, objType)
                    .set(CommonFile::getCreateTime, DateUtils.addSeconds(new Date(), i))
                    .eq(CommonFile::getId, fileIds.get(i))
                    .update();
        }
    }

    /**
     * 查询附件列表
     */
    public List<CommonFile> queryFileByObjId(String objId, String objType) {
        return commonFileService.lambdaQuery()
                .eq(CommonFile::getObjId, objId)
                .eq(CommonFile::getObjType, objType)
                .orderByAsc(CommonFile::getCreateTime)
                .list();
    }

    /**
     * 查询附件列表
     */
    public List<String> queryFileUrlsByObjId(String objId, String objType) {
        List<CommonFile> commonFiles = this.queryFileByObjId(objId, objType);
        if (commonFiles.size() == 0) {
            return null;
        }
        return commonFiles.stream().map(CommonFile::getUrl).collect(Collectors.toList());
    }


    /**
     * 上传附件
     *
     * @param file
     * @return
     * @throws IOException
     */
    public CommonFile uploadFile(MultipartFile file) throws IOException, RemoteServiceException {

        if (file == null || file.isEmpty()) {
            return null;
        }
        String uploadFilePath = file.getOriginalFilename().replaceAll("\\\\", "/");
        String uploadFileName = uploadFilePath.substring(
                uploadFilePath.lastIndexOf('/') + 1, uploadFilePath.lastIndexOf('.'));
        String uploadFileSuffix = uploadFilePath.substring(uploadFilePath.lastIndexOf('.') + 1, uploadFilePath.length());
        long currentTime = System.currentTimeMillis();
        BufferedOutputStream bufferedOutputStream = null;

        //限制大小为10m
        if (file.getSize() > 1024 * 1024 * 30) {
            throw new RemoteServiceException("文件大小超出限制");
        }

        try {
            String filePath = OSSUtil.OSS_TYPE_PIC + currentTime + UUID.randomUUID().toString() + "." + uploadFileSuffix;
            if (!OSSUtil.uploadFile(filePath, file.getBytes())) {
                throw new RemoteServiceException("文件同步oss失败");
            }
            String ossUrl = OSSUtil.accessUrl + filePath;

            CommonFile commonFile = new CommonFile();
            commonFile.setUrl(ossUrl);
            commonFile.setName(uploadFileName);
            commonFile.setFileType(uploadFileSuffix);
            commonFile.setFileSize(BigDecimal.valueOf(file.getSize()));
            commonFile.setCreateTime(new Date());
            commonFileService.save(commonFile);
            return commonFile;
        } finally {
            if (bufferedOutputStream != null) {
                bufferedOutputStream.close();
            }
        }
    }


    public List<Region> queryRegionList(Long pid) {
        return regionService.lambdaQuery().eq(Region::getPid, pid).list();
    }

    public String getFile(String key, HttpServletResponse response) throws IOException {
        String url = OSSUtil.getUrlWw(key);
        return url;
    }

    public String getUrlScheme(String query, String companyWechatId) throws IOException, WxErrorException {
        String accessToken = wechatLogic.getMaService(companyWechatId).getAccessToken();
        HttpPost httpPost = new HttpPost("https://api.weixin.qq.com/wxa/generatescheme?access_token=" + accessToken);
        httpPost.setHeader("Content-Type", "application/json; charset=utf-8");
        httpPost.setConfig(RequestConfig.custom().setConnectTimeout(10 * 1000).build());

        TreeMap<String, String> jump_wxa = new TreeMap<>();
        jump_wxa.put("query", query);

        TreeMap<String, Object> treeMap = new TreeMap<>();
        treeMap.put("jump_wxa", jump_wxa);
        treeMap.put("is_expire", true);
        treeMap.put("expire_type", 1);
        treeMap.put("expire_interval", 7);
        httpPost.setEntity(new StringEntity(JSON.toJSONString(treeMap)));

        HttpResponse httpResponse = HttpClientBuilder.create().build().execute(httpPost);
        String s = EntityUtils.toString(httpResponse.getEntity());
        if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
            log.info("调用微信接口失败:" + httpPost.getURI());
            log.info("返回数据：" + s);
            throw new RuntimeException("调用微信接口失败");
        }
        log.info("调用微信接口成功:" + httpPost.getURI());
        log.info("微信接口返回数据：" + s);

        try {
            return JSON.parseObject(s).get("openlink").toString();
        } catch (NullPointerException e) {
            return s;
        }
    }

    public String getFileGet(String key) {
        String url = OSSUtil.getUrlWw(key, null);
        return url;
    }

    /**
     * 批量更新商户名称（冗余字段）
     */
    public void batchUpdateCompanyWechatName(String companyWechatId, String companyWechatName) {
        adminMapper.batchUpdateCompanyWechatName(companyWechatId, companyWechatName);
    }
}
