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

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.gree.mall.miniapp.bean.user.CurrentCompanyWechat;
import com.gree.mall.miniapp.constant.Constant;
import com.gree.mall.miniapp.exception.RemoteServiceException;
import com.gree.mall.miniapp.plus.entity.*;
import com.gree.mall.miniapp.plus.service.*;
import com.gree.mall.miniapp.utils.ApplicationContextUtils;
import com.gree.mall.miniapp.utils.CommonUtils;
import com.gree.mall.miniapp.utils.HttpUtils;
import com.gree.mall.miniapp.utils.RedisUtil;
import com.gree.mall.miniapp.utils.oss.OSSUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class CommonLogic {

    @Autowired
    OSSUtil ossUtil;
    @Autowired
    CommonFileService commonFileService;
    @Autowired
    WxSceneService wxSceneService;
    @Autowired
    WxSceneDetailService wxSceneDetailService;
    @Autowired
    RegionService regionService;
    @Autowired
    UserService userService;
    @Autowired
    AdminCompanyWechatService adminCompanyWechatService;
    @Autowired
    AdminCompanyWechatOtherService adminCompanyWechatOtherService;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    UserWaitService userWaitService;
    @Value("${spring.profiles.active}")
    private String profiles;
    @Value("${inf.url}")
    private String infUrl;
    @Value("${inf.token.appid}")
    private String clientId;
    @Value("${inf.token.appSecret}")
    private String clientSecret;

    //高德的webkey
    private final String mapWebKey = "428a7111e02ea8367a3b34804eaa025b";

    public CurrentCompanyWechat getCurrentCompanyWechat() {
        HttpServletRequest request = ApplicationContextUtils.getHttpServletRequest();
        return getCurrentCompanyWechat(request);
    }

    /**
     * 获取当前用户
     */
    public CurrentCompanyWechat getCurrentCompanyWechat(HttpServletRequest request) {

        String appid = CommonUtils.getAPPID(request);
        String userId = CommonUtils.getUserId(request);
        String device = request.getHeader("device");
        String token = CommonUtils.getToken(request);
        if (StringUtils.isBlank(token)) {
            token = request.getParameter("token");
        }
        if (StringUtils.isBlank(token)) {
            token = request.getParameter("x-token");
        }

        if (StringUtils.isBlank(device) && StringUtils.isBlank(appid)) {
            throw new RemoteServiceException("非法请求，缺少必须的参数");
        }
        AdminCompanyWechat adminCompanyWechat;
        User user = null;
        if (StringUtils.isBlank(device)) {
            adminCompanyWechat = adminCompanyWechatService.lambdaQuery()
                    .eq(AdminCompanyWechat::getSubAppId, appid)
//                .or()
//                .eq(AdminCompanyWechat::getPubAppId,appid)
                    .one();
            if (adminCompanyWechat == null) {
                throw new RemoteServiceException("非法请求，请联系管理员配置必要的参数:" + appid);
            }

            user = userService.getById(userId);
        } else {
            adminCompanyWechat = adminCompanyWechatService.lambdaQuery()
                    .last("limit 1")
                    .one();
            if (StringUtils.isNotBlank(token)) {
                Object result = redisUtil.get(Constant.RedisPrefix.TOKEN_APP_USER + token);
                if (Objects.isNull(result)) {
                    throw new RemoteServiceException("非法请求，登录信息不存在");
                }
                user = (User) result;
            }
        }

        CurrentCompanyWechat currentCompanyWechat = new CurrentCompanyWechat();
        BeanUtils.copyProperties(adminCompanyWechat, currentCompanyWechat);
        if (Objects.nonNull(user)) {
            currentCompanyWechat.setCurrentCompanyWechatId(adminCompanyWechat.getCompanyWechatId());
            currentCompanyWechat.setCurrentCompanyName(adminCompanyWechat.getCompanyName());
            currentCompanyWechat.setUserId(user.getUserId());
            currentCompanyWechat.setUser(user);
        }
        return currentCompanyWechat;

    }

    /**
     * 获取当前企业
     */
    public AdminCompanyWechat getAdminCompanyWechat(String companyWechatId) {
        AdminCompanyWechat adminCompanyWechat = adminCompanyWechatService.getById(companyWechatId);
        return adminCompanyWechat;
    }

    /**
     * 微信scene
     */
    public String getSceneValue(String wxSceneId) {
        WxScene wxScene = this.getScene(wxSceneId);
        return wxScene == null ? "" : wxScene.getParam();
    }

    /**
     * 微信scene
     */
    public WxScene getScene(String wxSceneId) {
        WxScene wxScene = wxSceneService.getById(wxSceneId);
        if (!wxScene.getStatus()) {
            throw new RemoteServiceException("链接无效");
        }
        if (wxScene.getEndTime().getTime() < new Date().getTime()) {
            throw new RemoteServiceException("链接已过期");
        }
        return wxScene;
    }

    /**
     * 获取来源
     */
    public String getSource() {
        HttpServletRequest request = ApplicationContextUtils.getHttpServletRequest();
        String token = request.getHeader("source");
        return token;
    }

    /**
     * 获取来源
     */
    public String getMiniOpenId() {
        HttpServletRequest request = ApplicationContextUtils.getHttpServletRequest();
        String token = request.getHeader("miniOpenId");
        return token;
    }


    /**
     * 微信scene详情
     */
    public List<WxSceneDetail> getSceneDetail(String wxSceneId) {
        List<WxSceneDetail> list = wxSceneDetailService.lambdaQuery().eq(WxSceneDetail::getWxSceneId, wxSceneId).list();
        return list;
    }

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

        commonFileService.lambdaUpdate()
                .set(CommonFile::getObjId, objId)
                .set(CommonFile::getObjType, objType)
                .in(CommonFile::getId, fileIds).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<Map> street(String province, String city, String area) {
        List<Map> street = getStreet(province, area);
        if (street.size() == 0) {
            Map map = new HashMap();
            map.put("name", area);
            street.add(map);
        }
        return street;
    }


    public Map<String, String> getOSSConfig() throws UnsupportedEncodingException {
        Map<String, String> config = ossUtil.getConfig();
        return config;
    }

    public String getFile(String key) throws IOException {
        String url = ossUtil.getUrlWw(key);
        return url;
    }

    /**
     * 获取高德行政地址
     */
    public List<Map> getStreet(String province, String area) {
        try {
            String s = HttpUtil.get("https://restapi.amap.com/v3/config/district?keywords=" + province + "&subdistrict=1&key=" + mapWebKey);
            JSONObject jsonObject = JSONObject.parseObject(s);
            String status = (String) jsonObject.get("status");
            if (status.equals("1")) {
                List<Object> districts = (List<Object>) jsonObject.get("districts");
                String adcode = (String) ((Map<String, Object>) districts.get(0)).get("adcode");

                String street = HttpUtil.get("https://restapi.amap.com/v3/config/district?keywords=" + area + "&subdistrict=1&key=" + mapWebKey + "&adcode=" + adcode);
                Object districts1 = JSONObject.parseObject(street).get("districts");
                List<Map> maps = JSONArray.parseArray(JSONObject.toJSONString(districts1), Map.class);

                List<Map> districts2 = JSONArray.parseArray(JSONObject.toJSONString(maps.get(0).get("districts")), Map.class);
                return districts2;
            }
        } catch (Exception e) {
            return new ArrayList<>();
        }
        return new ArrayList<>();
    }

    /**
     * 上传附件
     *
     * @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());
        if (StringUtils.isNotBlank(uploadFileSuffix) && uploadFileSuffix.equals("quicktime")) {
            uploadFileSuffix = "mp4";
        }
        long currentTime = System.currentTimeMillis();
        BufferedOutputStream bufferedOutputStream = null;

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

        try {
            String filePath = ossUtil.getFilePath() + "/" + currentTime + UUID.randomUUID().toString() + "." + uploadFileSuffix;
            if (!ossUtil.uploadFile(filePath, file.getBytes())) {
                throw new RemoteServiceException("文件同步oss失败");
            }
            String ossUrl = ossUtil.getAccessUrl() + 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();
            }
        }

    }

    /**
     * 生成订单号
     *
     * @param start     前缀
     * @param orderType 订单类型
     * @param length    一般13 位
     * @return
     */
    public String generateNo(String start, String orderType, int length) {
        String dayFmt = DateUtil.format(new Date(), "yyMMdd");
        String tNumKey = Constant.RedisPrefix.ORDER_NUM + orderType + dayFmt;
        StringBuffer number = new StringBuffer();
        number.append(start);
        number.append(dayFmt);
        int ramainLen = length - number.toString().length();
        //自增 填充位数
        Object value = redisUtil.incr(tNumKey, 1);
        redisUtil.expire(tNumKey, 24 * 60 * 60);
        number.append(String.format("%0" + ramainLen + "d", Integer.parseInt(value.toString())));
        return number.toString();
    }

    public List<Region> getRegion(String parentId) {
        List<Region> list = regionService.lambdaQuery()
                .eq(StringUtils.isBlank(parentId), Region::getPid, "0")
                .eq(StringUtils.isNotBlank(parentId), Region::getPid, parentId).list();
        return list;
    }

    /**
     * 生成辅材编号
     *
     * @param companyId 商户编号
     * @param start     前缀
     * @param orderType 订单类型
     * @param length    一般13 位
     * @return
     */
    public String generateMaterialNo(String companyId, String start, String orderType, int length) {
        String dayFmt = DateUtil.format(new Date(), "yyyyMMdd");
        String tNumKey = Constant.RedisPrefix.ORDER_NUM + dayFmt + orderType + companyId;
        StringBuilder number = new StringBuilder();
        number.append(start);
        number.append(dayFmt);
        int ramainLen = length - number.toString().length();
        //自增 填充位数
        Object value = redisUtil.incr(tNumKey, 1);
        redisUtil.expire(tNumKey, 24 * 60 * 60);
        number.append(String.format("%0" + ramainLen + "d", Integer.parseInt(value.toString())));
        return number.toString();
    }

    public String getInfToken() throws RemoteServiceException {
        Object token = redisUtil.get(Constant.RedisPrefix.INF_TOKEN);

        if (token != null) {
            return token.toString();
        }
        //过期就重新获取
        return this.deleteAndAddInfToken();
    }

    public String deleteAndAddInfToken() throws RemoteServiceException {
        HashMap<String, String> params = new HashMap();
        params.put("clientId", this.clientId);
        params.put("clientSecret", this.clientSecret);
        String content = HttpUtils.requestGet(this.infUrl + "/com/token/get", params, null);
        Map<String, Object> resMap = JSON.parseObject(content, new TypeReference<HashMap<String, Object>>() {
        });

        int code = (int) resMap.get("code");
        if (code == 1) {
            String token = (String) resMap.get("data");
            redisUtil.set(Constant.RedisPrefix.INF_TOKEN, token, (2 * 60 * 60) - 30);//2小时过期
            return token;
        }
        return null;
    }

    public String getInfUrl() {
        return infUrl;
    }

}
