package com.bonus.sharedstation.app.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.sharedstation.app.domain.GreenUserInfo;
import com.bonus.sharedstation.app.dto.WashClothingOrderDTO;
import com.bonus.sharedstation.app.entity.WashClothingOrder;
import com.bonus.sharedstation.app.entity.WashClothingOrderInfo;
import com.bonus.sharedstation.app.entity.WashClothingPrice;
import com.bonus.sharedstation.app.mapper.WashClothingOrderInfoMapper;
import com.bonus.sharedstation.app.mapper.WashClothingOrderMapper;
import com.bonus.sharedstation.app.mapper.WashClothingPriceMapper;
import com.bonus.sharedstation.app.service.WashClothingOrderService;
import com.bonus.sharedstation.app.vo.ApiResponse;
import com.bonus.sharedstation.app.vo.ApiResponseForPay;
import com.bonus.sharedstation.app.vo.Customer;
import com.bonus.sharedstation.app.vo.ResponseDatad;
import com.bonus.sharedstation.common.utils.DateUtils;
import com.bonus.sharedstation.common.utils.OrderNumberGeneratorUtils;
import com.bonus.sharedstation.web.dto.WashClothingPriceDTO;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 便民服务信息表保洁(CleaningServicesOrder)表服务实现类
 *
 * @author makejava
 * @since 2024-12-10 17:02:11
 */
@Service("washClothingOrderService")
@Slf4j
public class WashClothingOrderServiceImpl extends ServiceImpl<WashClothingOrderMapper, WashClothingOrder> implements WashClothingOrderService {

    @Resource
    private WashClothingOrderMapper dao;
    @Resource
    private WashClothingOrderInfoMapper washClothingOrderInfoMapper;
    @Resource
    private WashClothingPriceMapper washClothingPriceMapper;


    @Value("${niu.niupayurl}")
    private String niupayurl;

    @Value("${niu.niusearchuserurl}")
    private String niusearchuserurl;

    @Value("${niu.niupayreturnurl}")
    private String niupayreturnurl;

    @Value("${niu.applicationid}")
    private String applicationid;

    @Value("${niu.applicationidpsw}")
    private String applicationidpsw;

    @Value("${niu.sncode}")
    private String sncode;

    @Value("${niu.serialnum}")
    private String serialnum;

    @Resource
    private BaseService baseService;

    /**
     * 分页
     *
     * @param dto
     * @return
     */
    @Override
    public AjaxResult getListPageApp(WashClothingOrderDTO dto) {
        log.info("查询分页入参: {}", dto);
        LambdaQueryWrapper<WashClothingOrder> queryWrapper = new LambdaQueryWrapper<>();
        // 创建分页对象
        Page<WashClothingOrder> page = new Page<>(dto.getCurrentPage(), dto.getLimit());
        // 根据userId是否提供来动态添加条件
        if (dto.getUserId() != null) {
            queryWrapper.eq(WashClothingOrder::getUserId, dto.getUserId());
        }

        if (StringUtils.isNotEmpty(dto.getName())) {
            queryWrapper.like(WashClothingOrder::getName, dto.getName());
        }
        queryWrapper
                .eq(WashClothingOrder::getIsDeleted, dto.getIsDeleted())
                .orderByDesc(WashClothingOrder::getCreatedTime);
        Page<WashClothingOrder> result = dao.selectPage(page, queryWrapper);
        //处理参数问题
        List<WashClothingOrder> records = result.getRecords();
        if (records == null) {
            return AjaxResult.success(result);
        }
        //查询所有的绿植订单信息
        LambdaQueryWrapper<WashClothingOrderInfo> greenOrderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        greenOrderInfoLambdaQueryWrapper
                .eq(WashClothingOrderInfo::getIsDeleted, dto.getIsDeleted())
                .orderByDesc(WashClothingOrderInfo::getCreatedTime);
        List<WashClothingOrderInfo> greenOrderInfos = washClothingOrderInfoMapper.selectList(greenOrderInfoLambdaQueryWrapper);
        for (WashClothingOrder record : records) {
            if (record != null) {
                Integer id = record.getId();
                List<WashClothingOrderInfo> collect = greenOrderInfos.stream().
                        filter(greenOrderInfo -> greenOrderInfo.getOrderId() != null
                                && greenOrderInfo.getOrderId().equals(id)).collect(Collectors.toList());
                if (collect != null) {
                    record.setOrderInfoList(collect);
                }
            }
        }
        return AjaxResult.success(result);
    }


    /**
     * 分页
     *
     * @param dto
     * @return
     */
    @Override
    public AjaxResult getListWeb(WashClothingOrderDTO dto) {
        log.info("查询分页入参: {}", dto);
        LambdaQueryWrapper<WashClothingOrder> queryWrapper = new LambdaQueryWrapper<>();
        // 创建分页对象
        Page<WashClothingOrder> page = new Page<>(dto.getCurrentPage(), dto.getLimit());

        if (StringUtils.isNotEmpty(dto.getName())) {
            queryWrapper.like(WashClothingOrder::getName, dto.getName());
        }
        queryWrapper
                .eq(WashClothingOrder::getIsDeleted, dto.getIsDeleted())
                .orderByDesc(WashClothingOrder::getCreatedTime);

        Page<WashClothingOrder> result = dao.selectPage(page, queryWrapper);
        //处理参数问题
        List<WashClothingOrder> records = result.getRecords();
        if (records == null) {
            return AjaxResult.success(result);
        }
        //查询所有的绿植订单信息
        LambdaQueryWrapper<WashClothingOrderInfo> greenOrderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        greenOrderInfoLambdaQueryWrapper
                .eq(WashClothingOrderInfo::getIsDeleted, dto.getIsDeleted())
                .orderByDesc(WashClothingOrderInfo::getCreatedTime);
        List<WashClothingOrderInfo> greenOrderInfos = washClothingOrderInfoMapper.selectList(greenOrderInfoLambdaQueryWrapper);
        for (WashClothingOrder record : records) {
            if (record != null) {
                Integer id = record.getId();
                List<WashClothingOrderInfo> collect = greenOrderInfos.stream().
                        filter(greenOrderInfo -> greenOrderInfo.getOrderId() != null
                                && greenOrderInfo.getOrderId().equals(id)).collect(Collectors.toList());
                if (collect != null) {
                    record.setOrderInfoList(collect);
                }
            }
        }
        return AjaxResult.success(result);
    }

    @Override
    public AjaxResult selectInfoById(WashClothingOrder dto) {
        WashClothingOrder greenOrder = dao.selectById(dto.getId());
        LambdaQueryWrapper<WashClothingOrderInfo> greenOrderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();

        if (greenOrder != null) {
            greenOrderInfoLambdaQueryWrapper
                    .eq(WashClothingOrderInfo::getIsDeleted, dto.getIsDeleted())
                    .eq(WashClothingOrderInfo::getOrderId, greenOrder.getId())
                    .orderByDesc(WashClothingOrderInfo::getCreatedTime);
            List<WashClothingOrderInfo> greenOrderInfos =
                    washClothingOrderInfoMapper.selectList(greenOrderInfoLambdaQueryWrapper);

            if (greenOrderInfos != null) {
                greenOrder.setOrderInfoList(greenOrderInfos);
            }
            return AjaxResult.success(greenOrder);
        }
        return AjaxResult.error("暂无相关数据");
    }

    /**
     * 新增
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public AjaxResult add(WashClothingOrderDTO dto) {
        log.info("新增入参 : " + dto);
        GreenUserInfo userInfo = baseService.getUserInfo(dto.getUserId());
        //得到登录人
        WashClothingOrder greenOrder = new WashClothingOrder();
        BeanUtils.copyProperties(dto, greenOrder);
        greenOrder.setCreatedBy(userInfo.getLoginName());
        greenOrder.setCreatedTime(new Date());
        greenOrder.setUserId(userInfo.getUserId());
        greenOrder.setCustId(String.valueOf(SecurityUtils.getLoginUser().getCustId()));
        greenOrder.setIsDeleted("0");
        greenOrder.setOrderTime(new Date());
        //流水号
        greenOrder.setOrdno(OrderNumberGeneratorUtils.generateOrderNumber());
        //
        return payByNiu(userInfo, greenOrder);
        //新增绿植订单

    }


    /**
     * 支付相关接入第三方小牛支付
     *
     * @param userInfo
     * @param dto
     * @return
     */
    private AjaxResult payByNiu(GreenUserInfo userInfo, WashClothingOrder dto) {
        //1 先查询人员对应的卡号
        //应用秘钥
        String appsecret = applicationidpsw;
        //传参
        HashMap<Object, Object> bodyMap = new HashMap<>(2);
        if (StringUtils.isEmpty(userInfo.getMobile())) {
            log.info("下单没有配置手机号,无法下单,请联系管理员配置");
            return AjaxResult.error("用户信息获取失败！");
        }
        //根据手机号查询
        bodyMap.put("mobile", userInfo.getMobile());
//        bodyMap.put("mobile", "15996330508");
        //请求内容字典排序，转换为String
        String content = JSON.toJSONString(bodyMap, SerializerFeature.MapSortField, SerializerFeature.WriteMapNullValue);
        log.info("请求内容转换为JSON字符串，字典排序：{}", content);
        //构造请求验签参数方法

        Map<String, Object> map = makeSign(content, appsecret, bodyMap);
        HttpRequest request = HttpUtil.createPost(niusearchuserurl);
        log.info("request=" + JSONUtil.toJsonStr(map));
        request.body(JSONUtil.toJsonStr(map), ContentType.JSON.toString());
        HttpResponse response = request.execute();
        log.info("response={}", response.body());
        //转成实体类
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            ApiResponse apiResponse = objectMapper.readValue(response.body(), ApiResponse.class);
            ResponseDatad data = apiResponse.getData();
            List<Customer> customerList = data.getCustomerList();
            if (StringUtils.isEmpty(customerList)) {
                log.info("没有找到对应餐卡,无法下单,请联系管理员配置");
                return AjaxResult.error("没有找到对应餐卡,无法下单,请联系管理员配置");
            }
            Customer customer = customerList.get(0);
            //传参
            HashMap<Object, Object> bodyMapForPayContent = new HashMap<>(2);
            //构建 content
            intoMapEnity(bodyMapForPayContent, dto, customer);
            String payContent = JSON.toJSONString(bodyMapForPayContent, SerializerFeature.MapSortField, SerializerFeature.WriteMapNullValue);
            log.info("content: " + payContent);
            Map<String, Object> payBodyMap = makeSign(payContent, appsecret, bodyMapForPayContent);

            HttpRequest requestForPay = HttpUtil.createPost(niupayurl);
            log.info("request=" + JSONUtil.toJsonStr(payBodyMap));
            requestForPay.body(JSONUtil.toJsonStr(payBodyMap), ContentType.JSON.toString());
            HttpResponse responseForPay = requestForPay.execute();
            log.info("responseForPay={}", responseForPay.body());
            //转成实体类响应数据
            ApiResponseForPay apiResponseForPay = objectMapper.readValue(responseForPay.body(), ApiResponseForPay.class);
            if (apiResponseForPay == null) {
                log.error("扣款食堂卡失败,请检查");
                return AjaxResult.error("扣款食堂卡失败,请检查");
            }
            if (StringUtils.isNotNull(apiResponseForPay) && apiResponseForPay.getCode() == 10000) {
                boolean b = saveOrUpdate(dto);
                Double moneyCount = 0.00;
                if (StringUtils.isNotNull(dto.getId())) {
                    //增加 绿植订单信息品类
                    if (StringUtils.isNotEmpty(dto.getOrderInfoList())) {
                        for (WashClothingOrderInfo greenOrderInfo : dto.getOrderInfoList()) {
                            greenOrderInfo.setOrderId(dto.getId());
                            int insert = washClothingOrderInfoMapper.insert(greenOrderInfo);
                            if (insert == 1) {
                                // 统计这一单的金额
                                moneyCount = moneyCount + (greenOrderInfo.getGreenPrice() * greenOrderInfo.getClothingNum());
                            }
                        }
                        return AjaxResult.success("选购成功,消费金额为: " + moneyCount);
                    } else {
                        return AjaxResult.error("请选购对应洗衣项目");
                    }
                }
                return AjaxResult.error("洗衣项目新增失败");
            }
            if (StringUtils.isNotNull(apiResponseForPay)) {
                return AjaxResult.error("小牛支付提示:" + apiResponseForPay.getMsg());
            }
            return AjaxResult.error("支付有误,请联系管理员");
        } catch (Exception e) {
            log.error("下单失败");
            e.printStackTrace();
            return AjaxResult.error("下单失败");
        }
    }

    private void intoMapEnity(HashMap bodyMap, WashClothingOrder dto, Customer customer) {
        //金额
        Double usePrice = dto.getUsePrice();
        int convertedPrice = (int) (usePrice * 100);
        bodyMap.put("amount", convertedPrice);
        //人员 id
        bodyMap.put("custId", Long.valueOf(customer.getCustId()));
        //流水号
        bodyMap.put("macOrdId", dto.getOrdno());
        //sn码
        bodyMap.put("machineSn", sncode);
        //
        bodyMap.put("nuClearMode", 2);

        bodyMap.put("ordTime", DateUtils.formatDate(dto.getOrderTime()));

        bodyMap.put("deliveryType", "2");
        //
    }


    private Map<String, Object> makeSign(String content, String appsecret, HashMap<Object, Object> bodyMap) {
        Map<String, Object> map = new TreeMap<>();
        map.put("appid", applicationid);
        map.put("version", "1.0.0");
        map.put("signtype", "md5");
        map.put("timestamp", String.valueOf(System.currentTimeMillis()));
        map.put("nonce", RandomUtil.randomNumbers(10));
        map.put("content", content);
        //生成sign，防篡改
        String toSignStr = Joiner.on("&")
                .useForNull("")
                .withKeyValueSeparator("=")
                .join(map) + "&appsecret=" + appsecret;
        log.info("所有参数字典排序，待加签String：{}", toSignStr);

        // md5/sha256 加签（其他方式待提供）
        String sign = DigestUtils.md5Hex(toSignStr).toUpperCase();
        System.err.println("sign: " + sign);
        log.info("加签String：{}", sign);
        map.put("sign", sign);

        //post请求
        map.replace("content", bodyMap);
        return map;
    }


    @Override
    public AjaxResult updateInfoById(WashClothingOrder dto) {
        return null;
    }


    /**
     * 分页查询
     *
     * @param dto
     * @return
     */
    @Override
    public AjaxResult getListPage(WashClothingPriceDTO dto) {
        log.info("查询 入参: {}", dto);
        LambdaQueryWrapper<WashClothingPrice> queryWrapper = new LambdaQueryWrapper<>();
        // 创建分页对象
        Page<WashClothingPrice> page = new Page<>(dto.getCurrentPage(), dto.getLimit());
        if (StringUtils.isNotEmpty(dto.getName())) {
            queryWrapper.like(WashClothingPrice::getName, dto.getName());
        }
        queryWrapper
                .eq(WashClothingPrice::getIsDeleted, dto.getIsDeleted())
                .orderByDesc(WashClothingPrice::getCreatedTime);

        Page<WashClothingPrice> result = washClothingPriceMapper.selectPage(page, queryWrapper);
        //处理参数问题
        return AjaxResult.success(result);
    }

}

