package org.jeecg.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.api.bean.FansPageBean;
import org.jeecg.api.bean.PageBean;
import org.jeecg.api.service.AppletInfoService;
import org.jeecg.api.service.AppletLoginService;
import org.jeecg.api.wxUtils.HttpClientUtil;
import org.jeecg.api.wxUtils.WxQrCodeVo;
import org.jeecg.common.api.vo.Result;
import org.jeecg.config.shiro.ShiroRealm;
import org.jeecg.modules.commonAddress.entity.CommonAddress;
import org.jeecg.modules.commonAddress.service.ICommonAddressService;
import org.jeecg.modules.commonConfig.entity.CommonConfig;
import org.jeecg.modules.commonConfig.service.ICommonConfigService;
import org.jeecg.modules.commonHelp.entity.CommonHelp;
import org.jeecg.modules.commonHelp.service.ICommonHelpService;
import org.jeecg.modules.commonMoneyLog.entity.CommonMoneyLog;
import org.jeecg.modules.commonMoneyLog.mapper.CommonMoneyLogMapper;
import org.jeecg.modules.commonMoneyLog.service.ICommonMoneyLogService;
import org.jeecg.modules.commonOrder.entity.CommonOrder;
import org.jeecg.modules.commonOrder.service.ICommonOrderService;
import org.jeecg.modules.hanHaiMember.entity.HanHaiMember;
import org.jeecg.modules.hanHaiMember.service.IHanHaiMemberService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.nio.file.Files;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AppletInfoServiceImpl implements AppletInfoService {
    //权限验证
    @Resource
    private ShiroRealm shiroRealm;
    @Resource
    private IHanHaiMemberService hanHaiMemberService;
    @Resource
    private ICommonAddressService commonAddressService;
    @Resource
    private ICommonOrderService commonOrderService;
    @Resource
    private ICommonMoneyLogService  commonMoneyLogService;
    @Resource
    private CommonMoneyLogMapper commonMoneyLogMapper;
    @Resource
    private ICommonConfigService commonConfigService;
    @Resource
    private ICommonHelpService commonHelpService;



    @Value("${wechat.mpAppId}")
    private String appid;
    @Value("${wechat.mpAppSecret}")
    private String secret;
    @Value("${jeecg.oss.endpoint}")
    private String endpoint;
    @Value("${jeecg.oss.accessKey}")
    private String accessKey;
    @Value("${jeecg.oss.secretKey}")
    private String secretKey;
    @Value("${jeecg.oss.bucketName}")
    private String bucketName;


    //修改个人信息接口
    @Override
    public Result<?> updateUserInfo(String token, String nickName, String headImage, String phone){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        hanHaiMember.setNickName(nickName);
        hanHaiMember.setHeadImage(headImage);
        hanHaiMember.setPhone(phone);
        hanHaiMemberService.updateById(hanHaiMember);
        return Result.OK("个人信息修改成功");
    }


    //查看个人信息接口
    @Override
    public Result<?> getUserInfo(String token){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        List<BigDecimal> moneyList = commonMoneyLogMapper.selectObjs(
                        new LambdaQueryWrapper<CommonMoneyLog>()
                                .eq(CommonMoneyLog::getUserId, hanHaiMember.getId())
                                .select(CommonMoneyLog::getMoney)
                ).stream()
                .filter(obj -> obj != null)
                .map(obj -> new BigDecimal(obj.toString()))
                .collect(Collectors.toList());

        BigDecimal money = moneyList.stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        hanHaiMember.setPrice(money);
        return Result.OK("个人信息查询成功",hanHaiMember);
    }


    //查询地址信息列表带分页
    @Override
    public Result<?> getAddressList(String token, PageBean pageBean){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        Page<CommonAddress> page = new Page<CommonAddress>(pageBean.getPageNo(), pageBean.getPageSize());
        Page<CommonAddress> page1 = commonAddressService.lambdaQuery()
                .eq(CommonAddress::getUserId, hanHaiMember.getId())
                .orderByDesc(CommonAddress::getDefaultFlag)
                .orderByDesc(CommonAddress::getCreateTime)
                .page(page);
        return Result.OK("地址信息查询成功",page1);
    }


    //查询地址信息详情
    @Override
    public Result<?> getAddressInfo(String token,String id){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        CommonAddress commonAddress = commonAddressService.getById(id);
        return Result.OK("地址信息详情查询成功",commonAddress);
    }


    //增加或修改地址信息
    @Override
    public Result<?> saveOrUpdateAddress(String token, CommonAddress commonAddress){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        commonAddress.setUserId(hanHaiMember.getId());
        commonAddressService.saveOrUpdate(commonAddress);
        return Result.OK("保存成功");
    }


    //修改默认地址
    @Override
    public Result<?> updateDefaultAddress(String token,String id){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        //查到当前用户是否有默认地址给他修改成否
        List<CommonAddress> commonAddressList = commonAddressService.lambdaQuery()
                .eq(CommonAddress::getUserId, hanHaiMember.getId())
                .eq(CommonAddress::getDefaultFlag, "1")
                .list();
        if(commonAddressList.size() > 0){
            for (CommonAddress commonAddress : commonAddressList) {
                commonAddress.setDefaultFlag("0");
                commonAddressService.updateById(commonAddress);
            }
        }
        //查询当前地址是否是默认地址
        CommonAddress commonAddress = commonAddressService.getById(id);
        if(commonAddress.getDefaultFlag().equals("0")){
            commonAddress.setDefaultFlag("1");
            commonAddressService.updateById(commonAddress);
        }else if(commonAddress.getDefaultFlag().equals("1")){
            commonAddress.setDefaultFlag("0");
            commonAddressService.updateById(commonAddress);
        }
        return Result.OK("修改成功");
    }

    //删除地址信息
    @Override
    public Result<?> deleteAddress(String token,String id){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        commonAddressService.removeById(id);
        return Result.OK("删除成功");
    }


    //我的团队相关信息列表带分页
    @Override
    public Result<?> getTeamList(String token,Integer state, PageBean pageBean){

        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        Page<HanHaiMember> page = new Page<HanHaiMember>(pageBean.getPageNo(), pageBean.getPageSize());
        Page<HanHaiMember> pageList = hanHaiMemberService.lambdaQuery()
                .eq(HanHaiMember::getShareId,hanHaiMember.getId())
                .page(page);
        if(state == 0){
            pageList = hanHaiMemberService.lambdaQuery()
                    .eq(HanHaiMember::getShareId,hanHaiMember.getId())
                    .page(page);
        }else{
            pageList = hanHaiMemberService.lambdaQuery()
                    .eq(HanHaiMember::getVid,hanHaiMember.getId())
                    .page(page);
        }



        //创建一个新的集合
        Page<FansPageBean> pageListFans = new Page<>();
        List<FansPageBean> fansPageBean = new ArrayList<>();
        pageList.getRecords().forEach(item->{
            //创建一个新的对象
            FansPageBean fansPageBean1 = new FansPageBean();
            fansPageBean1.setPhone(item.getPhone());
            fansPageBean1.setHeadImage(item.getHeadImage());
            fansPageBean1.setNickName(item.getNickName());
            //查询该用户的订单数量,count中的state>0

            int count = commonOrderService.lambdaQuery()
                    .in(CommonOrder::getStatus,1,2,3)
                    .eq(CommonOrder::getUserId,item.getId())
                    .count().intValue();
            fansPageBean1.setOrderNum(count);

            //查询该用户的佣金之和
            BigDecimal commission = new BigDecimal(0);

            fansPageBean1.setCommission(commission);
            fansPageBean1.setCreateTime(item.getCreateTime());
            fansPageBean.add(fansPageBean1);
        });
        pageListFans.setRecords(fansPageBean);


        return Result.OK(pageListFans);

    }



    //获取团队头部信息
    @Override
    public Result<?> getTeamHeader(String token){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        Map<String,Object> map = new HashMap();
        map.put("money",hanHaiMember.getMoney());
        map.put("role",0);
        map.put("lj_money",100);//
        map.put("lj_price",0);//总佣金

        return Result.OK("团队头部信息查询成功",map);
    }

    //提现
    @Override
    public Result<?> openMoney (String token, BigDecimal money){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        if(money.compareTo(hanHaiMember.getMoney()) == 1){
            return Result.error("提现金额不能大于余额");
        }
        //增加提现流水
        CommonMoneyLog commonMoneyLog = new CommonMoneyLog();
        commonMoneyLog.setCreateTime(new Date());
        commonMoneyLog.setTitle("提现");
        commonMoneyLog.setUserId(hanHaiMember.getId());
        commonMoneyLog.setMoney(money);
        commonMoneyLog.setOldMoney(hanHaiMember.getMoney());
        commonMoneyLog.setType(1);
        commonMoneyLog.setState(0);
        commonMoneyLogService.save(commonMoneyLog);

        //修改用户余额
        BigDecimal money1 = hanHaiMember.getMoney().subtract(money);
        hanHaiMember.setMoney(money1);
        hanHaiMemberService.updateById(hanHaiMember);
        return Result.OK("提现成功");
    }


    //流水记录带分页搜索
    @Override
    public Result<?> getLogList(String token,String timeDate,PageBean pageBean){
        HanHaiMember hanHaiMember = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        Page<CommonMoneyLog> page = new Page<CommonMoneyLog>(pageBean.getPageNo(), pageBean.getPageSize());
        Page<CommonMoneyLog> pageList = commonMoneyLogService.lambdaQuery()
                .eq(CommonMoneyLog::getUserId,hanHaiMember.getId())
                .orderByDesc(CommonMoneyLog::getCreateTime)
                .page(page);
        return Result.OK("流水记录查询成功",pageList);
    }


    //生成邀请二维码
    @Override
    public Result<?> createQrCode(String token){
        HanHaiMember member = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);

        CommonConfig vsion = commonConfigService.lambdaQuery()
                .eq(CommonConfig::getKeyName, "v_sion")
                .one();
        Integer vsionStr = Integer.parseInt(vsion.getKeyContent());
        String trial = "release";
        if(vsionStr == 0){
            trial= "release";
        }else if(vsionStr == 1){
            trial= "trial";
        }else{
            trial= "develop";
        }

//        WxQrCodeVo o = (WxQrCodeVo)redisUtil.get("CodeImage::" + trial+ member.getId());
//        if(o!=null){
//
//
//            o.setName("瑶都万能墙欢迎您的加入");
//            return Result.OK(o);
//        }

        Map<String, Object> param = new HashMap<>();

        CommonConfig xcxSharePage = commonConfigService.lambdaQuery()
                .eq(CommonConfig::getKeyName, "xcxSharePage")
                .one();





        String key = "shareId=" + member.getId();

        param.put("path", xcxSharePage.getKeyContent() + "?" + key); //跳转页面
        String accessToken = this.getAccessToken();
        RestTemplate rest = new RestTemplate();
        InputStream inputStream = null;
        OutputStream outputStream = null;
        File file = null;

//        LambdaQueryWrapper<DbConf> configImg = new LambdaQueryWrapper<>();
//        configImg.eq(DbConf::getIsDel,0).eq(DbConf::getKeyValue,"codeImg");
//        DbConf oneImg = confService.getOne(configImg);

        CommonConfig oneImage = commonConfigService.lambdaQuery()
                .eq(CommonConfig::getKeyName, "codeImg")
                .one();

        //获取二维码背景图
        CommonConfig qr_code = commonConfigService.lambdaQuery()
                .eq(CommonConfig::getKeyName, "qr_code")
                .one();


        String codeImg = oneImage.getKeyContent();
        try{
            String url = "https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken;
            param.put("scene", member.getId());
            param.put("width", 150);
            param.put("auto_color", false);
            param.put("env_version", trial);
            Map<String, Object> line_color = new HashMap<>();
            line_color.put("r", 0);
            line_color.put("g", 0);
            line_color.put("b", 0);
            param.put("line_color", line_color);



            MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
            org.springframework.http.HttpEntity requestEntity = new org.springframework.http.HttpEntity(JSON.toJSONString(param), headers);
            ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
            byte[] result = entity.getBody();

            //返回图片下载地址
            WxQrCodeVo wxCodeVo = new WxQrCodeVo();

            CommonConfig image_go_url = commonConfigService.lambdaQuery()
                    .eq(CommonConfig::getKeyName, "image_go_url")
                    .one();

            String qrCodeImageUrl = image_go_url.getKeyContent()+ this.uploadAliYunOss(result, file.getName());
            String backgroundImageUrl = qr_code.getKeyContent();
            String outputFilePath = "combined_image_code";
//            String s = this.generateAndCombineImagesFromUrl2(qrCodeImageUrl, backgroundImageUrl, outputFilePath);
            wxCodeVo.setUrl(null);
            wxCodeVo.setName("陌美人珠宝欢迎您");


//            redisUtil.set("CodeImage::"+trial+member.getId(),wxCodeVo);
            return Result.OK(wxCodeVo);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //删除文件
            if (file.exists()) {
                file.delete();
            }
        }
        return null;

    }


    //获取推广二维码 2
    @Override
    public byte[] getInviteCode2(String token){
        HanHaiMember member = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);

        // 获取环境配置
        CommonConfig vsion = commonConfigService.lambdaQuery()
                .eq(CommonConfig::getKeyName, "v_sion")
                .one();
        Integer vsionStr = Integer.parseInt(vsion.getKeyContent());
        String trial = "release";
        if(vsionStr == 0){
            trial= "release";
        }else if(vsionStr == 1){
            trial= "trial";
        }else{
            trial= "develop";
        }

        // 获取必要的配置信息
        CommonConfig xcxSharePage = commonConfigService.lambdaQuery()
                .eq(CommonConfig::getKeyName, "xcxSharePage")
                .one();

        CommonConfig oneImage = commonConfigService.lambdaQuery()
                .eq(CommonConfig::getKeyName, "codeImg")
                .one();

        CommonConfig qr_code = commonConfigService.lambdaQuery()
                .eq(CommonConfig::getKeyName, "qr_code")
                .one();

        CommonConfig image_go_url = commonConfigService.lambdaQuery()
                .eq(CommonConfig::getKeyName, "image_go_url")
                .one();

        String backgroundImageUrl = qr_code.getKeyContent();

        // 尝试从缓存获取二维码
        String cacheKey = "CodeImage::" + trial + member.getId();
        WxQrCodeVo wxCodeVo = new WxQrCodeVo();

        wxCodeVo.setName("陌美人珠宝欢迎您");

        // 如果启用了Redis缓存，可以取消下面注释
//         String cachedQrCode = (String) redisUtil.get(cacheKey);
//         if(cachedQrCode != null){
//             String combinedImageUrl = this.generateAndCombineImagesFromUrl(cachedQrCode, backgroundImageUrl, "combined_image_code");
//             wxCodeVo.setUrl(combinedImageUrl);
//             return Result.OK(wxCodeVo);
//         }

        try {

            // 准备微信API请求参数
            String key = "shareId=" + member.getId();
            Map<String, Object> param = new HashMap<>();
            param.put("path", xcxSharePage.getKeyContent() + "?" + key);
            param.put("scene", member.getId());
            param.put("width", 150);
            param.put("auto_color", false);
            param.put("env_version", trial);

//            Map<String, Object> line_color = new HashMap<>();
//            line_color.put("r", 0);
//            line_color.put("g", 0);
//            line_color.put("b", 0);
//            param.put("line_color", line_color);


            param.put("is_hyaline", true);

            // 获取微信小程序码
            String accessToken = this.getAccessToken();
            String url = "https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken;

            // 请求微信API获取二维码图片数据
            RestTemplate rest = new RestTemplate();
            MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
            org.springframework.http.HttpEntity requestEntity = new org.springframework.http.HttpEntity(JSON.toJSONString(param), headers);
            ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
            byte[] qrCodeBytes = entity.getBody();

            // 直接将二维码图片转为MultipartFile，避免写入临时文件
//            MultipartFile qrCodeFile = createMultipartFile(qrCodeBytes, "qrcode.jpg");

            // 上传二维码到阿里云并获取URL
//            String qrCodeImageUrl = image_go_url.getKeyContent() + this.uploadAliYunOss(qrCodeFile);

            // 合并图片并上传
//            String combinedImageUrl = this.generateAndCombineImagesFromUrl2(qrCodeBytes, backgroundImageUrl);

            // 设置返回数据

            // 如果启用了Redis缓存，可以取消下面注释
            //redisUtil.set(cacheKey, qrCodeImageUrl, 3600); // 缓存一小时

            return this.generateAndCombineImagesFromUrl2(qrCodeBytes, backgroundImageUrl);
        } catch (Exception e) {
            e.printStackTrace();

            return null;
        }
    }


    public byte[] generateAndCombineImagesFromUrl2(byte[] qrCodeImageByte, String backgroundUrl) {
        File file = null;
        try {
            // 从字节数组加载小程序码图像
            BufferedImage qrCodeImage = ImageIO.read(new ByteArrayInputStream(qrCodeImageByte));

            // 从URL加载背景图像
            URL backgroundImageUrl = new URL(backgroundUrl);
            BufferedImage backgroundImage = ImageIO.read(backgroundImageUrl);

            // 创建一个新的BufferedImage来保存合并后的图像
            Graphics2D g2d = backgroundImage.createGraphics();

            int wh = backgroundImage.getWidth() / 3;

            // 计算小程序码放置的位置（这里以中心位置为例）
            int qrCodeX = (backgroundImage.getWidth() - wh) / 2;
            int qrCodeY = (int) ((backgroundImage.getHeight() - wh) * 0.6);

            // 绘制小程序码图像
            g2d.drawImage(qrCodeImage, qrCodeX, qrCodeY, wh, wh, null);

            // 释放Graphics2D资源
            g2d.dispose();

            // 将合并后的图像保存到临时文件
            file = File.createTempFile("combined_", ".png");
            ImageIO.write(backgroundImage, "png", file);

            // 上传到阿里云OSS
//            return this.uploadAliYunOss(Files.readAllBytes(file.toPath()), file.getName());
            return Files.readAllBytes(file.toPath());
        } catch (Exception e) {
            log.error("生成合并图片失败", e);
            throw new RuntimeException("生成合并图片失败", e);
        } finally {
            // 删除临时文件
            if (file != null && file.exists()) {
                file.delete();
            }
        }
    }


    /**
     * 获取令牌
     *
     * @return
     */
    private String getAccessToken() {
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
        String doGet2 = HttpClientUtil.doGet2(requestUrl);
        Map<String, String> map = JSON.parseObject(doGet2, new TypeReference<Map<String, String>>() {
        });
        return map.get("access_token");
    }
    /**
     * 上传文件至阿里云oss - 优化版
     * 直接使用字节数组上传，减少文件IO操作
     *
     * @return 上传后的文件路径
     */
    private String uploadAliYunOss(byte[] content, String fileName) throws Exception {
        String uploadFile = "WxCodeFile";
        String dbpath = uploadFile + "/" + fileName;

        // 创建OSSClient实例
        OSS ossClient = null;
        try {
            // 直接获取文件字节数组，避免额外的IO操作

            // 创建OSS客户端
            ossClient = new OSSClientBuilder().build(endpoint, accessKey, secretKey);

            // 设置文件元数据
            com.aliyun.oss.model.ObjectMetadata metadata = new com.aliyun.oss.model.ObjectMetadata();
            metadata.setContentType("image/jpeg");
            metadata.setContentLength(content.length);

            // 上传字节数组
            ossClient.putObject(bucketName, dbpath, new ByteArrayInputStream(content), metadata);

            return dbpath;
        } catch (Exception e) {
            log.error("上传文件到阿里云OSS失败", e);
            throw e;
        } finally {
            // 确保关闭OSS客户端
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }


    //新增帮助反馈信息
    @Override
    public Result<?> addHelp(String token, CommonHelp commonHelp){
        HanHaiMember member = shiroRealm.checkUserTokenIsEffectHanHaiOpenId(token);
        commonHelp.setUserId(member.getId());
        commonHelp.setCreateTime(new Date());
        commonHelpService.save(commonHelp);
        return Result.OK("增加成功");
    }
}
