package com.dora.service.impl;

import com.dora.entity.WechatMessageTemplate;
import com.dora.service.WechatEventHandlerService;
import com.dora.service.WechatManagementService;
import com.dora.service.WeChatMessageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.concurrent.TimeUnit;

import java.util.HashMap;
import java.util.Map;

/**
 * 微信事件处理服务实现
 * 
 * @author dora
 * @date 2024/12/01
 */
@Slf4j
@Service
public class WechatEventHandlerServiceImpl implements WechatEventHandlerService {

    private final WechatManagementService wechatManagementService;
    private final WeChatMessageService weChatMessageService;
    private final RedisTemplate<String, String> redisTemplate;

    private static final String WX_LOGIN_SCENE_PREFIX = "wx_login_scene:";

    public WechatEventHandlerServiceImpl(WechatManagementService wechatManagementService, 
                                           WeChatMessageService weChatMessageService, 
                                           RedisTemplate<String, String> redisTemplate) {
        this.wechatManagementService = wechatManagementService;
        this.weChatMessageService = weChatMessageService;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void dispatchEvent(WxMpXmlMessage wxMessage) {
        String msgType = wxMessage.getMsgType();
        String event = wxMessage.getEvent();

        try {
            if ("event".equals(msgType)) {
                handleEvent(wxMessage);
            } else if ("text".equals(msgType)) {
                handleTextMessage(wxMessage);
            } else {
                handleOtherMessage(wxMessage);
            }
        } catch (Exception e) {
            log.error("处理微信消息失败 - msgType: {}, event: {}, fromUser: {}",
                    msgType, event, wxMessage.getFromUser(), e);
        }
    }

    private void handleEvent(WxMpXmlMessage wxMessage) {
        String event = wxMessage.getEvent();
        String eventKey = wxMessage.getEventKey();
        String fromUser = wxMessage.getFromUser();

        switch (event) {
            case "subscribe":
                handleSubscribeEvent(wxMessage);
                if (eventKey != null && eventKey.startsWith("qrscene_")) {
                    String sceneStr = eventKey.replace("qrscene_", "");
                    handleSceneEvent(sceneStr, fromUser);
                }
                break;
            case "unsubscribe":
                handleUnsubscribeEvent(wxMessage);
                break;
            case "SCAN":
                handleScanEvent(wxMessage);
                if (eventKey != null) {
                    handleSceneEvent(eventKey, fromUser);
                }
                break;
            case "CLICK":
                handleMenuClickEvent(wxMessage);
                break;
            case "VIEW":
                handleMenuViewEvent(wxMessage);
                break;
            default:
                log.warn("未处理的事件类型: {}", event);
        }
    }

    @Override
    public void handleSubscribeEvent(WxMpXmlMessage wxMessage) {
        String openid = wxMessage.getFromUser();
        String eventKey = wxMessage.getEventKey();
        
        log.info("处理关注事件 - openid: {}, eventKey: {}", openid, eventKey);
        
        try {
            // 1. 发送欢迎消息
            WechatMessageTemplate welcomeTemplate = wechatManagementService.getTemplateByTrigger("subscribe", null);
            if (welcomeTemplate != null) {
                sendTemplateMessage(openid, welcomeTemplate);
            } else {
                // 使用默认欢迎消息
                weChatMessageService.sendTextMessage(openid, getWelcomeMessage());
            }
            
            // 2. 如果是扫码关注，处理扫码逻辑
            if (StringUtils.hasText(eventKey) && eventKey.startsWith("qrscene_")) {
                String sceneStr = eventKey.replace("qrscene_", "");
                handleSceneLogic(sceneStr, openid);
            }
            
        } catch (Exception e) {
            log.error("处理关注事件失败 - openid: {}", openid, e);
        }
    }

    @Override
    public void handleUnsubscribeEvent(WxMpXmlMessage wxMessage) {
        String openid = wxMessage.getFromUser();
        log.info("处理取消关注事件 - openid: {}", openid);
        
        try {
            // 可以在这里记录取消关注的统计信息
            // 注意：取消关注后无法主动发送消息给用户
            
        } catch (Exception e) {
            log.error("处理取消关注事件失败 - openid: {}", openid, e);
        }
    }

    @Override
    public void handleScanEvent(WxMpXmlMessage wxMessage) {
        String openid = wxMessage.getFromUser();
        String eventKey = wxMessage.getEventKey();
        
        log.info("处理扫码事件 - openid: {}, eventKey: {}", openid, eventKey);
        
        try {
            // 1. 发送扫码提示消息
            WechatMessageTemplate scanTemplate = wechatManagementService.getTemplateByTrigger("scan", eventKey);
            if (scanTemplate == null) {
                // 如果没有针对具体场景值的模板，则尝试获取扫码事件的默认回复模板
                scanTemplate = wechatManagementService.getTemplateByTrigger("default", "scan_default");
            }

            if (scanTemplate != null) {
                sendTemplateMessage(openid, scanTemplate);
            } else {
                weChatMessageService.sendTextMessage(openid, "您已扫码！");
            }
            
            // 2. 处理扫码业务逻辑
            handleSceneLogic(eventKey, openid);
            
        } catch (Exception e) {
            log.error("处理扫码事件失败 - openid: {}, eventKey: {}", openid, eventKey, e);
        }
    }

    @Override
    public void handleMenuClickEvent(WxMpXmlMessage wxMessage) {
        String openid = wxMessage.getFromUser();
        String eventKey = wxMessage.getEventKey();
        
        log.info("处理菜单点击事件 - openid: {}, eventKey: {}", openid, eventKey);
        
        try {
            // 1. 根据菜单Key查找对应的消息模板
            WechatMessageTemplate template = wechatManagementService.getTemplateByTrigger("click", eventKey);
            
            if (template != null) {
                // 发送配置的模板消息
                sendTemplateMessage(openid, template);
            } else {
                // 如果没有配置特定菜单的模板，尝试获取菜单点击的默认回复
                WechatMessageTemplate defaultClickTemplate = wechatManagementService.getTemplateByTrigger("default", "click_default");
                if (defaultClickTemplate != null) {
                    sendTemplateMessage(openid, defaultClickTemplate);
                } else {
                    // 最后的兜底：发送提示消息
                    log.warn("未配置菜单点击回复 - eventKey: {}, 建议在后台配置消息模板", eventKey);
                    weChatMessageService.sendTextMessage(openid, "感谢您的操作！如需帮助，请联系客服。");
                }
            }
            
        } catch (Exception e) {
            log.error("处理菜单点击事件失败 - openid: {}, eventKey: {}", openid, eventKey, e);
        }
    }

    @Override
    public void handleMenuViewEvent(WxMpXmlMessage wxMessage) {
        String openid = wxMessage.getFromUser();
        String eventKey = wxMessage.getEventKey();
        
        log.info("处理菜单跳转事件 - openid: {}, eventKey: {}", openid, eventKey);
        
        try {
            // 记录菜单跳转统计
            // 可以在这里添加统计逻辑
            
        } catch (Exception e) {
            log.error("处理菜单跳转事件失败 - openid: {}, eventKey: {}", openid, eventKey, e);
        }
    }

    @Override
    public void handleTextMessage(WxMpXmlMessage wxMessage) {
        String openid = wxMessage.getFromUser();
        String content = wxMessage.getContent();
        
        log.info("处理文本消息 - openid: {}, content: {}", openid, content);
        
        try {
            if (!StringUtils.hasText(content)) {
                return;
            }
            
            // 1. 根据关键词查找回复模板
            WechatMessageTemplate template = wechatManagementService.getTemplateByKeyword(content.trim());
            
            if (template != null) {
                // 发送匹配的模板消息
                sendTemplateMessage(openid, template);
                } else {
                    // 发送默认回复
                    WechatMessageTemplate defaultTemplate = wechatManagementService.getDefaultReplyTemplate();
                    if (defaultTemplate != null) {
                        sendTemplateMessage(openid, defaultTemplate);
                    } else {
                        // 尝试获取最终的兜底回复模板
                        WechatMessageTemplate fallbackTemplate = wechatManagementService.getTemplateByTrigger("default", "fallback_default");
                        if (fallbackTemplate != null) {
                            sendTemplateMessage(openid, fallbackTemplate);
                        } else {
                            // 最后的硬编码兜底回复
                            weChatMessageService.sendTextMessage(openid, "感谢您的消息！我们已收到，将尽快处理。");
                        }
                    }
                }
            
        } catch (Exception e) {
            log.error("处理文本消息失败 - openid: {}, content: {}", openid, content, e);
        }
    }

    @Override
    public void handleOtherMessage(WxMpXmlMessage wxMessage) {
        String openid = wxMessage.getFromUser();
        String msgType = wxMessage.getMsgType();
        
        log.info("处理其他消息类型 - openid: {}, msgType: {}", openid, msgType);
        
        try {
            // 对于其他类型的消息，可以发送默认回复
            WechatMessageTemplate defaultTemplate = wechatManagementService.getDefaultReplyTemplate();
            if (defaultTemplate != null) {
                sendTemplateMessage(openid, defaultTemplate);
            } else {
                // 尝试获取最终的兜底回复模板
                WechatMessageTemplate fallbackTemplate = wechatManagementService.getTemplateByTrigger("default", "fallback_default");
                if (fallbackTemplate != null) {
                    sendTemplateMessage(openid, fallbackTemplate);
                } else {
                    // 最后的硬编码兜底回复
                    weChatMessageService.sendTextMessage(openid, "感谢您的消息！我们已收到，将尽快处理。");
                }
            }
            
        } catch (Exception e) {
            log.error("处理其他消息类型失败 - openid: {}, msgType: {}", openid, msgType, e);
        }
    }

    @Override
    public boolean sendTemplateMessage(String openid, WechatMessageTemplate template) {
        try {
            if (template == null || !template.isEnabled()) {
                return false;
            }
            
            // 使用WechatManagementService的sendTemplateMessage方法
            return wechatManagementService.sendTemplateMessage(openid, template);
            
        } catch (Exception e) {
            log.error("发送模板消息失败 - openid: {}, templateId: {}", openid, template.getId(), e);
            return false;
        }
    }

    @Override
    public String getWelcomeMessage() {
        // 默认欢迎消息（仅在未配置后台模板时使用）
        return "🎉 欢迎关注1818AI！\n\n" +
               "我们为您提供：\n" +
               "📚 优质课程内容\n" +
               "🎯 个性化学习推荐\n" +
               "💡 AI智能辅导\n\n" +
               "点击菜单开始您的学习之旅！";
    }

    @Override
    public String processMenuClick(String menuKey, String openid) {
        // 此方法已废弃，菜单点击响应现在完全由后台配置的消息模板控制
        // 保留此方法仅为接口兼容性
        log.warn("调用了已废弃的 processMenuClick 方法，建议使用消息模板配置菜单响应");
        return null;
    }

    /**
     * 处理场景逻辑（登录、绑定等）
     */
    private void handleSceneLogic(String sceneStr, String openid) {
        try {
            // 这里保持原有的登录和绑定逻辑
            // 可以根据场景值的前缀判断是登录还是绑定场景
            if (sceneStr.startsWith("bind_")) {
                // 绑定场景处理逻辑
                log.info("处理绑定场景 - sceneStr: {}, openid: {}", sceneStr, openid);
                // 绑定场景的具体逻辑可以在这里实现
                // 例如：解析绑定码，关联用户账号等
            } else {
                // 登录场景处理逻辑
                log.info("处理登录场景 - sceneStr: {}, openid: {}", sceneStr, openid);
                // 登录场景的具体逻辑可以在这里实现
                // 例如：生成登录token，更新登录状态等
            }
            
        } catch (Exception e) {
            log.error("处理场景逻辑失败 - sceneStr: {}, openid: {}", sceneStr, openid, e);
        }
    }

    /**
     * 处理场景事件（登录或绑定）
     * 
     * @param sceneStr 场景值
     * @param openid 用户openid
     */
    private void handleSceneEvent(String sceneStr, String openid) {
        try {
            log.info("处理场景事件 - 场景值: {}, openid: {}", sceneStr, openid);
            
            // 判断是登录场景还是绑定场景
            if (sceneStr.startsWith("bind_")) {
                // 绑定场景
                log.info("识别为绑定场景，但此场景应由UserController处理");
            } else {
                // 登录场景
                log.info("识别为登录场景");
                saveLoginInfo(sceneStr, openid);
            }
        } catch (Exception e) {
            log.error("处理场景事件失败 - 场景值: {}, openid: {}", sceneStr, openid, e);
        }
    }

    /**
     * 保存登录信息到Redis（支持多用户扫同一二维码）
     * 
     * @param sceneStr 场景值
     * @param openid 用户openid
     */
    private void saveLoginInfo(String sceneStr, String openid) {
        try {
            // 使用Set结构存储多个openid，避免覆盖问题
            String setKey = WX_LOGIN_SCENE_PREFIX + sceneStr;
            redisTemplate.opsForSet().add(setKey, openid);
            redisTemplate.expire(setKey, 10, TimeUnit.MINUTES);
            log.info("用户扫码成功 - 场景值: {}, openid: {}", sceneStr, openid);
        } catch (Exception e) {
            log.error("保存登录信息失败", e);
        }
    }

}
