package com.liquidnet.service.order.utils;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.common.sms.constant.SmsEnum;
import com.liquidnet.common.sms.processor.SmsProcessor;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.kylin.constant.GroupBuyStatusConst;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyActivityVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyMemberVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyOrderVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 拼团短信：成功。复用 SmsProcessor；总开关见 Redis {@link KylinRedisConst#GROUP_BUY_SMS_ENABLED}。
 */
@Component
@Slf4j
public class GroupBuySmsSender {

    @Autowired
    private SmsProcessor smsProcessor;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private DataUtils dataUtils;

    public void notifySuccess(KylinGroupBuyOrderVo group) {
        if (group == null || !isSmsEnabled()) {
            return;
        }
        List<String> phones = collectPhones(group, true, false);
        if (phones.isEmpty()) {
            log.info("拼团成功短信无有效手机号 groupOrderId={}", group.getGroupOrderId());
            return;
        }
        ObjectNode params = buildSuccessParams(group);
        String templateParam = params.toString();
        for (String phone : phones) {
            sendSafe(phone, SmsEnum.ADTemplate.SMS_510540063.name(), templateParam,
                    group.getGroupOrderId(), "success");
        }
    }

    private boolean isSmsEnabled() {
        Object v = redisUtil.get(KylinRedisConst.GROUP_BUY_SMS_ENABLED);
        if (v == null) {
            return true;
        }
        String s = String.valueOf(v).trim();
        return !("0".equals(s) || "false".equalsIgnoreCase(s));
    }

    /**
     * @param joinedOnly true=仅 JOINED；false 且 includePendingPay=true 时含 JOINED+PENDING_PAY
     */
    private List<String> collectPhones(KylinGroupBuyOrderVo group, boolean joinedOnly, boolean includePendingPay) {
        Set<String> phones = new HashSet<>();
        if (group == null || CollectionUtils.isEmpty(group.getMembers())) {
            return new ArrayList<>();
        }
        for (KylinGroupBuyMemberVo m : group.getMembers()) {
            if (m == null || StringUtils.isBlank(m.getOrderTicketsId())) {
                continue;
            }
            if (m.getOrderTicketsId().startsWith("ROBOT_")) {
                continue;
            }
            Integer st = m.getStatus();
            boolean ok = GroupBuyStatusConst.MemberStatus.JOINED.equals(st)
                    || (includePendingPay && GroupBuyStatusConst.MemberStatus.PENDING_PAY.equals(st));
            if (joinedOnly) {
                ok = GroupBuyStatusConst.MemberStatus.JOINED.equals(st);
            }
            if (!ok) {
                continue;
            }
            String mobile = resolveMobile(m.getOrderTicketsId());
            if (StringUtils.isNotBlank(mobile)) {
                phones.add(mobile.trim());
            }
        }
        return new ArrayList<>(phones);
    }

    private String resolveMobile(String orderTicketsId) {
        Object cached = redisUtil.get(KylinRedisConst.ORDER.concat(orderTicketsId));
        if (cached instanceof KylinOrderTicketVo) {
            return ((KylinOrderTicketVo) cached).getUserMobile();
        }
        KylinOrderTicketVo ticket = mongoTemplate.findOne(
                Query.query(Criteria.where("orderTicketsId").is(orderTicketsId)),
                KylinOrderTicketVo.class, KylinOrderTicketVo.class.getSimpleName());
        return ticket == null ? null : ticket.getUserMobile();
    }

    private ObjectNode buildSuccessParams(KylinGroupBuyOrderVo group) {
        ObjectNode node = JsonUtils.OM().createObjectNode();
        String name = "";
        String time = "";
        String ticket = "";
        try {
            KylinGroupBuyActivityVo activity = mongoTemplate.findOne(
                    Query.query(Criteria.where("activityId").is(group.getActivityId())),
                    KylinGroupBuyActivityVo.class, KylinGroupBuyActivityVo.class.getSimpleName());
            if (activity != null && StringUtils.isNotBlank(activity.getPerformanceId())) {
                KylinPerformanceVo p = dataUtils.getPerformanceVo(activity.getPerformanceId());
                if (p != null) {
                    name = p.getTitle() == null ? "" : p.getTitle();
                    String[] titles = resolveTimeTicketTitle(p, group.getTimeId(), group.getTicketId());
                    time = titles[0];
                    ticket = titles[1];
                }
            }
        } catch (Exception e) {
            log.warn("拼团成功短信组装变量失败 groupOrderId={}", group.getGroupOrderId(), e);
        }
        node.put("name", name);
        node.put("time", time);
        node.put("ticket", ticket);
        return node;
    }

    private String[] resolveTimeTicketTitle(KylinPerformanceVo p, String timeId, String ticketId) {
        String timeTitle = "";
        String ticketTitle = "";
        if (p.getTicketTimeList() == null || timeId == null) {
            return new String[]{timeTitle, ticketTitle};
        }
        for (KylinTicketTimesVo t : p.getTicketTimeList()) {
            if (!timeId.equals(t.getTimeId())) {
                continue;
            }
            timeTitle = t.getTitle() == null ? "" : t.getTitle();
            if (t.getTicketList() != null && ticketId != null) {
                for (KylinTicketVo tk : t.getTicketList()) {
                    if (ticketId.equals(tk.getTicketsId())) {
                        ticketTitle = tk.getTitle() == null ? "" : tk.getTitle();
                        break;
                    }
                }
            }
            break;
        }
        return new String[]{timeTitle, ticketTitle};
    }

    private void sendSafe(String phone, String templateCode, String templateParam, String groupOrderId, String scene) {
        try {
            boolean ok = smsProcessor.send(phone, SmsEnum.ADSignName.M02.getVal(), templateCode, templateParam);
            if (!ok) {
                log.warn("拼团短信发送失败 scene={} groupOrderId={} phone={}", scene, groupOrderId, phone);
            }
        } catch (Exception e) {
            log.error("拼团短信发送异常 scene={} groupOrderId={} phone={}", scene, groupOrderId, phone, e);
        }
    }
}
