package com.ylx.massage.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.ylx.common.config.WechatAccountConfig;
import com.ylx.massage.domain.TJs;
import com.ylx.massage.domain.TOrder;
import com.ylx.massage.domain.TXiangmu;
import com.ylx.massage.service.OrderNotificationService;
import com.ylx.massage.service.TJsService;
import com.ylx.massage.utils.DateTimeUtils;
import com.ylx.massage.utils.WeChatUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * 订单消息通知服务实现类
 * <p>
 * 负责处理订单生命周期中各阶段的消息通知功能。
 * 所有通知通过微信公众号模板消息推送给用户。
 * </p>
 *
 * @author ylx
 * @version 1.0
 * @since 2024
 */
@Service
@Slf4j
public class OrderNotificationServiceImpl implements OrderNotificationService {

    @Resource
    private WeChatUtil weChatUtil;

    @Resource
    private WechatAccountConfig wxPayProperties;

    @Resource
    private TJsService jsService;

    /**
     * 订单待接单提醒（技师侧）
     *
     * @param order 订单信息
     */
    @Override
    public void sendPendingRemindNotification(TOrder order) {
        try {
            log.info("订单待接单提醒（技师侧）");
            cn.hutool.json.JSONObject param = buildPendingRemindParams(order);
            //获取技师openid
            TJs js = jsService.getById(order.getcJsId());
            weChatUtil.notification(js.getcOpenId(), wxPayProperties.getTechTemplate1(), param);
            log.info("订单待接单提醒发送成功，订单号：{}", order.getOrderNo());
        } catch (Exception e) {
            log.error("订单待接单提醒发送失败，订单号：{}", order.getOrderNo(), e);
        }
    }

    /**
     * 订单已接单通知（用户侧）
     *
     * @param order 订单信息
     */
    @Override
    public void sendReceivedNotification(TOrder order) {
        try {
            cn.hutool.json.JSONObject param = buildReceivedNotificationParams(order);
            weChatUtil.notification(order.getcOpenId(), wxPayProperties.getUserTemplate1(), param);
            log.info("订单已接单通知发送成功，订单号：{}", order.getOrderNo());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("订单已接单通知发送失败，订单号：{}", order.getOrderNo(), e);
        }
    }

    /**
     * 订单完成通知（用户侧）
     *
     * @param order 订单信息
     */
    @Override
    public void sendCompletedNotification(TOrder order) {
        try {
            cn.hutool.json.JSONObject param = buildCompletedNotificationParams(order);
            weChatUtil.notification(order.getcOpenId(), wxPayProperties.getUserTemplate2(), param);
            log.info("订单完成通知发送成功，订单号：{}", order.getOrderNo());
        } catch (Exception e) {
            log.error("订单完成通知发送失败，订单号：{}", order.getOrderNo(), e);
        }
    }

    /**
     * 订单取消通知（用户侧）
     *
     * @param order 订单信息
     */
    @Override
    public void sendCancelledNotification(TOrder order) {
        try {
            cn.hutool.json.JSONObject param = buildCancelledNotificationParams(order);
            weChatUtil.notification(order.getcOpenId(), wxPayProperties.getUserTemplate3(), param);
            log.info("订单取消通知发送成功，订单号：{}", order.getOrderNo());
        } catch (Exception e) {
            log.error("订单取消通知发送失败，订单号：{}", order.getOrderNo(), e);
        }
    }

    /**
     * 构建待接单提醒消息参数（技师侧）
     *
     * @param order 订单信息
     * @return JSONObject 消息参数
     */
    private cn.hutool.json.JSONObject buildPendingRemindParams(TOrder order) {
        cn.hutool.json.JSONObject param = JSONUtil.createObj();
        // 订单号
        param.set("character_string9", JSONUtil.createObj().set("value", order.getOrderNo()));
        // 用户电话
        param.set("phone_number3", JSONUtil.createObj().set("value", order.getcPhone()));
        // 项目
        String projectNames = getProjectNames(order);
        param.set("thing10", JSONUtil.createObj().set("value", projectNames));
        // 下单地址
        param.set("thing13", JSONUtil.createObj().set("value", order.getAddress()));
        // 预约时间
        LocalDateTime startTime = order.getStartTime();
        if(startTime==null){
            // 预约时间为空，设置默认值
            startTime = LocalDateTime.now();
        }
        Date date = Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant());
        param.set("time6", JSONUtil.createObj().set("value", DateTimeUtils.formatDate(date, "yyyy-MM-dd HH:mm")));
        return param;
    }

    /**
     * 构建已接单通知消息参数
     *
     * @param order 订单信息
     * @return JSONObject 消息参数
     */
    private cn.hutool.json.JSONObject buildReceivedNotificationParams(TOrder order) {
        cn.hutool.json.JSONObject param = JSONUtil.createObj();
        // 订单号
        param.set("character_string1", JSONUtil.createObj().set("value", order.getOrderNo()));
        // 项目名称
        String projectNames = getProjectNames(order);
        param.set("thing4", JSONUtil.createObj().set("value", projectNames));

        //根据技师ID查询技师姓名
        TJs js = jsService.getById(order.getcJsId());
        String jsName = js.getcName();
        // 商家名称
        param.set("thing9", JSONUtil.createObj().set("value", jsName));
        // 联系电话
        param.set("phone_number5", JSONUtil.createObj().set("value", js.getcPhone()));
        return param;
    }

    /**
     * 构建完成通知消息参数（用户侧）
     *
     * @param order 订单信息
     * @return JSONObject 消息参数
     */
    private cn.hutool.json.JSONObject buildCompletedNotificationParams(TOrder order) {
        cn.hutool.json.JSONObject param = JSONUtil.createObj();
        // 订单号
        param.set("character_string8", JSONUtil.createObj().set("value", order.getOrderNo()));
        // 项目名称
        String projectNames = getProjectNames(order);
        param.set("thing19", JSONUtil.createObj().set("value", projectNames));
        // 完成时间
        LocalDateTime completeTime = order.getEndTime();
        Date date = Date.from(completeTime.atZone(ZoneId.systemDefault()).toInstant());
        param.set("time18", JSONUtil.createObj().set("value", DateTimeUtils.formatDate(date, "yyyy-MM-dd HH:mm")));
        return param;
    }

    /**
     * 构建取消通知消息参数
     *
     * @param order 订单信息
     * @return JSONObject 消息参数
     */
    private cn.hutool.json.JSONObject buildCancelledNotificationParams(TOrder order) {
        cn.hutool.json.JSONObject param = JSONUtil.createObj();
        // 订单号
        param.set("character_string2", JSONUtil.createObj().set("value", order.getOrderNo()));
        // 取消原因
        param.set("thing5", JSONUtil.createObj().set("value", "用户个人原因"));
        // 项目名称
        String projectNames = getProjectNames(order);
        param.set("thing25", JSONUtil.createObj().set("value", projectNames));
        //订单金额
        param.set("amount23", JSONUtil.createObj().set("value", order.getTotalPrice().toString()));
        return param;
    }

    /**
     * 从订单明细中提取项目名称
     * <p>
     * 解析订单的商品列表，将多个项目名称用逗号连接
     * </p>
     *
     * @param order 订单信息
     * @return String 项目名称字符串，多个项目用逗号分隔
     */
    private String getProjectNames(TOrder order) {
        List<TXiangmu> list = JSONObject.parseArray(order.getcGoods().toJSONString(), TXiangmu.class);
        StringBuilder sb = new StringBuilder();
        for (TXiangmu xiangmu : list) {
            sb.append(xiangmu.getcTitle()).append(",");
        }
        // 移除最后一个逗号
        if (sb.length() > 0) {
            sb.setLength(sb.length() - 1);
        }
        return sb.toString();
    }

    /**
     * 订单已接单通知（技师侧）
     *
     * @param order 订单信息
     */
    @Override
    public void sendTechnicianReceivedNotification(TOrder order) {
        try {
            // 获取技师信息
            String jsOpenId = getTechnicianOpenId(order);
            log.info("技师的openId：{}", jsOpenId);
            if (jsOpenId == null) {
                log.warn("技师信息不存在，无法发送已接单通知，订单号：{}", order.getOrderNo());
                return;
            }

            cn.hutool.json.JSONObject param = buildTechnicianReceivedNotificationParams(order);
            weChatUtil.notification(jsOpenId, wxPayProperties.getTechTemplate2(), param);
            log.info("技师侧已接单通知发送成功，订单号：{}", order.getOrderNo());
        } catch (Exception e) {
            log.error("技师侧已接单通知发送失败，订单号：{}", order.getOrderNo(), e);
        }
    }

    /**
     * 订单取消通知（技师侧）
     *
     * @param order 订单信息
     */
    @Override
    public void sendTechnicianCancelledNotification(TOrder order) {
        try {
            // 获取技师的openId
            String jsOpenId = getTechnicianOpenId(order);
            log.info("技师的openId：{}", jsOpenId);
            if (jsOpenId == null) {
                log.warn("技师信息不存在，无法发送取消通知，订单号：{}", order.getOrderNo());
                return;
            }

            cn.hutool.json.JSONObject param = buildTechnicianCancelledNotificationParams(order);
            weChatUtil.notification(jsOpenId, wxPayProperties.getTechTemplate3(), param);
            log.info("技师侧取消订单通知发送成功，订单号：{}", order.getOrderNo());
        } catch (Exception e) {
            log.error("技师侧取消订单通知发送失败，订单号：{}", order.getOrderNo(), e);
        }
    }

    /**
     * 构建技师侧已接单通知消息参数
     *
     * @param order 订单信息
     * @return JSONObject 消息参数
     */
    private cn.hutool.json.JSONObject buildTechnicianReceivedNotificationParams(TOrder order) {
        cn.hutool.json.JSONObject param = JSONUtil.createObj();
        // 订单编号
        param.set("character_string1", JSONUtil.createObj().set("value", order.getOrderNo()));
        // 联系电话
        param.set("phone_number5", JSONUtil.createObj().set("value", order.getcPhone()));
        // 项目名称
        String projectNames = getProjectNames(order);
        param.set("thing4", JSONUtil.createObj().set("value", projectNames));
        // 预约地址
        param.set("thing14", JSONUtil.createObj().set("value", order.getAddress()));
        // 预约时间
        LocalDateTime dtCreateTime = order.getDtCreateTime();
        Date createTime = Date.from(dtCreateTime.atZone(ZoneId.systemDefault()).toInstant());
        param.set("time3", JSONUtil.createObj().set("value", DateTimeUtils.formatDate(createTime, "yyyy-MM-dd HH:mm")));
        return param;
    }

    /**
     * 构建技师侧取消通知消息参数
     *
     * @param order 订单信息
     * @return JSONObject 消息参数
     */
    private cn.hutool.json.JSONObject buildTechnicianCancelledNotificationParams(TOrder order) {
        cn.hutool.json.JSONObject param = JSONUtil.createObj();
        // 订单号
        param.set("character_string2", JSONUtil.createObj().set("value", order.getOrderNo()));
        // 取消原因
        param.set("thing5", JSONUtil.createObj().set("value", getCancelReason(order)));
        // 订单金额
        param.set("amount23", JSONUtil.createObj().set("value", order.getTotalPrice().toString()));
        return param;
    }

    /**
     * 获取技师的 OpenId
     *
     * @param order 订单信息
     * @return String 技师 OpenId，如果技师不存在则返回 null
     */
    private String getTechnicianOpenId(TOrder order) {
        if (order.getcJsId() == null) {
            return null;
        }
        try {
            return jsService.getById(order.getcJsId()).getcOpenId();
        } catch (Exception e) {
            log.error("获取技师信息失败，技师ID：{}", order.getcJsId(), e);
            return null;
        }
    }

    /**
     * 获取订单取消原因
     *
     * @param order 订单信息
     * @return String 取消原因描述
     */
    private String getCancelReason(TOrder order) {
        // 如果订单中有具体的取消原因，使用订单中的原因
        if (order.getReasonRefusal() != null && !order.getReasonRefusal().trim().isEmpty()) {
            return order.getReasonRefusal();
        }
        // 默认取消原因
        return "用户取消订单";
    }
}
