package com.ruoyi.notification.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.notification.domain.NotificationLog;
import com.ruoyi.notification.domain.NotificationMessage;
import com.ruoyi.notification.domain.NotificationTemplate;
import com.ruoyi.notification.service.INotificationService;

/**
 * 通知服务实现
 * 
 * @author ruoyi
 * @date 2025-12-19
 */
@Service
public class NotificationServiceImpl implements INotificationService 
{
    private static final Logger log = LoggerFactory.getLogger(NotificationServiceImpl.class);

    // 通知渠道常量
    private static final String CHANNEL_EMAIL = "EMAIL";
    private static final String CHANNEL_SMS = "SMS";
    private static final String CHANNEL_WECHAT = "WECHAT";
    private static final String CHANNEL_SYSTEM = "SYSTEM";
    private static final String CHANNEL_APP_PUSH = "APP_PUSH";

    // 消息状态常量
    private static final String STATUS_PENDING = "PENDING";
    private static final String STATUS_SENDING = "SENDING";
    private static final String STATUS_SUCCESS = "SUCCESS";
    private static final String STATUS_FAILED = "FAILED";

    // 优先级常量
    private static final String PRIORITY_HIGH = "HIGH";
    private static final String PRIORITY_NORMAL = "NORMAL";
    private static final String PRIORITY_LOW = "LOW";

    // 邮箱和手机号验证正则
    private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
    private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");

    @Override
    @Transactional
    public boolean sendNotification(NotificationMessage message) 
    {
        log.info("开始发送通知: notificationId={}, channel={}, recipient={}", 
                message.getNotificationId(), message.getNotificationChannel(), 
                message.getRecipientAddress());

        try {
            // 验证消息
            if (!validateMessage(message)) {
                log.error("通知消息验证失败: {}", message);
                return false;
            }

            // 生成通知ID（如果没有）
            if (message.getNotificationId() == null || message.getNotificationId().isEmpty()) {
                message.setNotificationId(generateNotificationId());
            }

            // 设置初始状态
            if (message.getMessageStatus() == null || message.getMessageStatus().isEmpty()) {
                message.setMessageStatus(STATUS_PENDING);
            }

            // 根据渠道发送通知
            boolean sendResult = sendByChannel(message);

            // 记录发送日志
            logNotification(message, sendResult);

            log.info("通知发送完成: notificationId={}, result={}", 
                    message.getNotificationId(), sendResult);

            return sendResult;

        } catch (Exception e) {
            log.error("发送通知失败: notificationId={}, error={}", 
                     message.getNotificationId(), e.getMessage(), e);
            logNotification(message, false);
            return false;
        }
    }

    @Override
    @Transactional
    public Map<String, Object> sendBatchNotifications(List<NotificationMessage> messages) 
    {
        log.info("开始批量发送通知: count={}", messages.size());

        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failedCount = 0;
        List<String> failedIds = new ArrayList<>();

        for (NotificationMessage message : messages) {
            try {
                boolean sendResult = sendNotification(message);
                if (sendResult) {
                    successCount++;
                } else {
                    failedCount++;
                    failedIds.add(message.getNotificationId());
                }
            } catch (Exception e) {
                log.error("批量发送通知失败: notificationId={}, error={}", 
                         message.getNotificationId(), e.getMessage(), e);
                failedCount++;
                failedIds.add(message.getNotificationId());
            }
        }

        result.put("totalCount", messages.size());
        result.put("successCount", successCount);
        result.put("failedCount", failedCount);
        result.put("failedIds", failedIds);

        log.info("批量发送通知完成: total={}, success={}, failed={}", 
                messages.size(), successCount, failedCount);

        return result;
    }

    @Override
    @Transactional
    public boolean sendTemplateNotification(String templateCode, String recipientType, 
                                          String recipientId, String recipientAddress, 
                                          String channel, Map<String, Object> parameters,
                                          String businessType, String businessId) 
    {
        log.info("使用模板发送通知: templateCode={}, channel={}, recipient={}", 
                templateCode, channel, recipientAddress);

        try {
            // 获取模板
            NotificationTemplate template = getTemplateByCode(templateCode);
            if (template == null) {
                log.error("通知模板不存在: templateCode={}", templateCode);
                return false;
            }

            // 渲染模板内容
            String subject = renderTemplate(template.getSubjectTemplate(), parameters);
            String content = renderTemplate(template.getContentTemplate(), parameters);

            // 创建通知消息
            NotificationMessage message = new NotificationMessage();
            message.setNotificationId(generateNotificationId());
            message.setTemplateId(template.getTemplateId());
            message.setRecipientType(recipientType);
            message.setRecipientId(recipientId);
            message.setRecipientAddress(recipientAddress);
            message.setNotificationType(template.getNotificationType());
            message.setNotificationChannel(channel);
            message.setSubject(subject);
            message.setContent(content);
            message.setPriority(PRIORITY_NORMAL);
            message.setMessageStatus(STATUS_PENDING);
            message.setBusinessType(businessType);
            message.setBusinessId(businessId);
            message.setCreateTime(DateUtils.getNowDate());

            // 发送通知
            return sendNotification(message);

        } catch (Exception e) {
            log.error("使用模板发送通知失败: templateCode={}, error={}", 
                     templateCode, e.getMessage(), e);
            return false;
        }
    }
    @Override
    public boolean sendPaymentReminder(Long contractId, String recipientId, 
                                     String recipientAddress, String channel,
                                     String dueDate, String amount) 
    {
        log.info("发送付款提醒: contractId={}, recipient={}, channel={}", 
                contractId, recipientAddress, channel);

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("contractId", contractId);
        parameters.put("dueDate", dueDate);
        parameters.put("amount", amount);
        parameters.put("recipientId", recipientId);

        return sendTemplateNotification("PAYMENT_REMINDER", "USER", recipientId, 
                                       recipientAddress, channel, parameters,
                                       "CONTRACT", contractId.toString());
    }

    @Override
    public boolean sendContractStatusNotification(Long contractId, String recipientId,
                                                String recipientAddress, String channel,
                                                String oldStatus, String newStatus) 
    {
        log.info("发送合同状态变更通知: contractId={}, recipient={}, oldStatus={}, newStatus={}", 
                contractId, recipientAddress, oldStatus, newStatus);

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("contractId", contractId);
        parameters.put("oldStatus", oldStatus);
        parameters.put("newStatus", newStatus);
        parameters.put("recipientId", recipientId);

        return sendTemplateNotification("CONTRACT_STATUS_CHANGE", "USER", recipientId, 
                                       recipientAddress, channel, parameters,
                                       "CONTRACT", contractId.toString());
    }

    @Override
    public boolean sendSystemAlert(String alertType, String alertLevel, 
                                 String alertMessage, String businessType, String businessId) 
    {
        log.info("发送系统告警: alertType={}, alertLevel={}, businessType={}", 
                alertType, alertLevel, businessType);

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("alertType", alertType);
        parameters.put("alertLevel", alertLevel);
        parameters.put("alertMessage", alertMessage);
        parameters.put("timestamp", DateUtils.dateTimeNow());

        // 系统告警发送给管理员
        String adminEmail = "admin@example.com";
        String adminPhone = "13800138000";

        boolean emailResult = sendTemplateNotification("SYSTEM_ALERT", "ADMIN", "admin", 
                                                      adminEmail, CHANNEL_EMAIL, parameters,
                                                      businessType, businessId);

        boolean smsResult = sendTemplateNotification("SYSTEM_ALERT", "ADMIN", "admin", 
                                                    adminPhone, CHANNEL_SMS, parameters,
                                                    businessType, businessId);

        return emailResult || smsResult;
    }

    @Override
    public boolean retryFailedNotification(String notificationId) 
    {
        log.info("重试失败通知: notificationId={}", notificationId);

        try {
            // 这里应该从数据库查询失败的通知记录
            // 为了演示，创建一个模拟的重试逻辑
            log.info("重试通知成功: notificationId={}", notificationId);
            return true;

        } catch (Exception e) {
            log.error("重试通知失败: notificationId={}, error={}", 
                     notificationId, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public Map<String, Object> getNotificationStatus(String notificationId) 
    {
        log.info("获取通知状态: notificationId={}", notificationId);

        Map<String, Object> status = new HashMap<>();
        
        try {
            // 这里应该从数据库查询通知状态
            // 为了演示，返回模拟数据
            status.put("notificationId", notificationId);
            status.put("status", STATUS_SUCCESS);
            status.put("sendTime", DateUtils.getNowDate());
            status.put("deliveryTime", DateUtils.getNowDate());
            status.put("retryCount", 0);

        } catch (Exception e) {
            log.error("获取通知状态失败: notificationId={}, error={}", 
                     notificationId, e.getMessage(), e);
            status.put("error", e.getMessage());
        }

        return status;
    }

    @Override
    public List<NotificationMessage> getNotificationHistory(String businessType, String businessId) 
    {
        log.info("获取通知历史: businessType={}, businessId={}", businessType, businessId);

        List<NotificationMessage> history = new ArrayList<>();
        
        try {
            // 这里应该从数据库查询通知历史
            // 为了演示，返回空列表
            log.info("获取通知历史完成: businessType={}, businessId={}, count={}", 
                    businessType, businessId, history.size());

        } catch (Exception e) {
            log.error("获取通知历史失败: businessType={}, businessId={}, error={}", 
                     businessType, businessId, e.getMessage(), e);
        }

        return history;
    }

    @Override
    public boolean validateNotificationChannel(String channel, String recipientAddress) 
    {
        if (channel == null || recipientAddress == null) {
            return false;
        }

        switch (channel.toUpperCase()) {
            case CHANNEL_EMAIL:
                return EMAIL_PATTERN.matcher(recipientAddress).matches();
            case CHANNEL_SMS:
                return PHONE_PATTERN.matcher(recipientAddress).matches();
            case CHANNEL_WECHAT:
                return recipientAddress.length() > 0;
            case CHANNEL_SYSTEM:
                return recipientAddress.length() > 0;
            case CHANNEL_APP_PUSH:
                return recipientAddress.length() > 0;
            default:
                return false;
        }
    }

    @Override
    public List<String> getSupportedChannels() 
    {
        return Arrays.asList(CHANNEL_EMAIL, CHANNEL_SMS, CHANNEL_WECHAT, 
                           CHANNEL_SYSTEM, CHANNEL_APP_PUSH);
    }

    @Override
    public boolean createNotificationTemplate(NotificationTemplate template) 
    {
        log.info("创建通知模板: templateCode={}", template.getTemplateCode());

        try {
            // 这里应该保存到数据库
            log.info("通知模板创建成功: templateCode={}", template.getTemplateCode());
            return true;

        } catch (Exception e) {
            log.error("创建通知模板失败: templateCode={}, error={}", 
                     template.getTemplateCode(), e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean updateNotificationTemplate(NotificationTemplate template) 
    {
        log.info("更新通知模板: templateCode={}", template.getTemplateCode());

        try {
            // 这里应该更新数据库
            log.info("通知模板更新成功: templateCode={}", template.getTemplateCode());
            return true;

        } catch (Exception e) {
            log.error("更新通知模板失败: templateCode={}, error={}", 
                     template.getTemplateCode(), e.getMessage(), e);
            return false;
        }
    }

    @Override
    public NotificationTemplate getTemplateByCode(String templateCode) 
    {
        log.info("获取通知模板: templateCode={}", templateCode);

        try {
            // 这里应该从数据库查询
            // 为了演示，返回模拟模板
            NotificationTemplate template = createMockTemplate(templateCode);
            
            if (template != null) {
                log.info("获取通知模板成功: templateCode={}", templateCode);
            } else {
                log.warn("通知模板不存在: templateCode={}", templateCode);
            }

            return template;

        } catch (Exception e) {
            log.error("获取通知模板失败: templateCode={}, error={}", 
                     templateCode, e.getMessage(), e);
            return null;
        }
    }

    @Override
    public Map<String, Object> getNotificationStatistics(String startDate, String endDate) 
    {
        log.info("获取通知统计: startDate={}, endDate={}", startDate, endDate);

        Map<String, Object> statistics = new HashMap<>();
        
        try {
            // 这里应该从数据库统计
            // 为了演示，返回模拟数据
            statistics.put("totalCount", 100);
            statistics.put("successCount", 95);
            statistics.put("failedCount", 5);
            statistics.put("successRate", "95%");
            
            Map<String, Integer> channelStats = new HashMap<>();
            channelStats.put(CHANNEL_EMAIL, 40);
            channelStats.put(CHANNEL_SMS, 30);
            channelStats.put(CHANNEL_SYSTEM, 20);
            channelStats.put(CHANNEL_WECHAT, 10);
            statistics.put("channelStatistics", channelStats);

        } catch (Exception e) {
            log.error("获取通知统计失败: startDate={}, endDate={}, error={}", 
                     startDate, endDate, e.getMessage(), e);
            statistics.put("error", e.getMessage());
        }

        return statistics;
    }
    // 私有辅助方法

    /**
     * 验证通知消息
     */
    private boolean validateMessage(NotificationMessage message) 
    {
        if (message == null) {
            log.error("通知消息不能为空");
            return false;
        }

        if (message.getRecipientAddress() == null || message.getRecipientAddress().isEmpty()) {
            log.error("接收地址不能为空");
            return false;
        }

        if (message.getNotificationChannel() == null || message.getNotificationChannel().isEmpty()) {
            log.error("通知渠道不能为空");
            return false;
        }

        if (message.getContent() == null || message.getContent().isEmpty()) {
            log.error("通知内容不能为空");
            return false;
        }

        // 验证渠道和地址匹配
        if (!validateNotificationChannel(message.getNotificationChannel(), message.getRecipientAddress())) {
            log.error("通知渠道和接收地址不匹配: channel={}, address={}", 
                     message.getNotificationChannel(), message.getRecipientAddress());
            return false;
        }

        return true;
    }

    /**
     * 根据渠道发送通知
     */
    private boolean sendByChannel(NotificationMessage message) 
    {
        String channel = message.getNotificationChannel().toUpperCase();
        
        switch (channel) {
            case CHANNEL_EMAIL:
                return sendEmailNotification(message);
            case CHANNEL_SMS:
                return sendSmsNotification(message);
            case CHANNEL_WECHAT:
                return sendWechatNotification(message);
            case CHANNEL_SYSTEM:
                return sendSystemNotification(message);
            case CHANNEL_APP_PUSH:
                return sendAppPushNotification(message);
            default:
                log.error("不支持的通知渠道: {}", channel);
                return false;
        }
    }

    /**
     * 发送邮件通知
     */
    private boolean sendEmailNotification(NotificationMessage message) 
    {
        log.info("发送邮件通知: to={}, subject={}", 
                message.getRecipientAddress(), message.getSubject());

        try {
            // 这里应该集成邮件发送服务
            // 为了演示，模拟发送成功
            Thread.sleep(100); // 模拟网络延迟
            
            log.info("邮件发送成功: to={}", message.getRecipientAddress());
            return true;

        } catch (Exception e) {
            log.error("邮件发送失败: to={}, error={}", 
                     message.getRecipientAddress(), e.getMessage(), e);
            return false;
        }
    }

    /**
     * 发送短信通知
     */
    private boolean sendSmsNotification(NotificationMessage message) 
    {
        log.info("发送短信通知: to={}, content={}", 
                message.getRecipientAddress(), message.getContent());

        try {
            // 这里应该集成短信发送服务
            // 为了演示，模拟发送成功
            Thread.sleep(50); // 模拟网络延迟
            
            log.info("短信发送成功: to={}", message.getRecipientAddress());
            return true;

        } catch (Exception e) {
            log.error("短信发送失败: to={}, error={}", 
                     message.getRecipientAddress(), e.getMessage(), e);
            return false;
        }
    }

    /**
     * 发送微信通知
     */
    private boolean sendWechatNotification(NotificationMessage message) 
    {
        log.info("发送微信通知: to={}, content={}", 
                message.getRecipientAddress(), message.getContent());

        try {
            // 这里应该集成微信发送服务
            // 为了演示，模拟发送成功
            Thread.sleep(80); // 模拟网络延迟
            
            log.info("微信通知发送成功: to={}", message.getRecipientAddress());
            return true;

        } catch (Exception e) {
            log.error("微信通知发送失败: to={}, error={}", 
                     message.getRecipientAddress(), e.getMessage(), e);
            return false;
        }
    }

    /**
     * 发送系统通知
     */
    private boolean sendSystemNotification(NotificationMessage message) 
    {
        log.info("发送系统通知: to={}, content={}", 
                message.getRecipientAddress(), message.getContent());

        try {
            // 这里应该保存到系统消息表
            // 为了演示，模拟发送成功
            
            log.info("系统通知发送成功: to={}", message.getRecipientAddress());
            return true;

        } catch (Exception e) {
            log.error("系统通知发送失败: to={}, error={}", 
                     message.getRecipientAddress(), e.getMessage(), e);
            return false;
        }
    }

    /**
     * 发送APP推送通知
     */
    private boolean sendAppPushNotification(NotificationMessage message) 
    {
        log.info("发送APP推送通知: to={}, content={}", 
                message.getRecipientAddress(), message.getContent());

        try {
            // 这里应该集成推送服务
            // 为了演示，模拟发送成功
            Thread.sleep(60); // 模拟网络延迟
            
            log.info("APP推送通知发送成功: to={}", message.getRecipientAddress());
            return true;

        } catch (Exception e) {
            log.error("APP推送通知发送失败: to={}, error={}", 
                     message.getRecipientAddress(), e.getMessage(), e);
            return false;
        }
    }

    /**
     * 记录通知日志
     */
    private void logNotification(NotificationMessage message, boolean success) 
    {
        try {
            NotificationLog log = new NotificationLog();
            log.setNotificationId(message.getNotificationId());
            log.setTemplateId(message.getTemplateId());
            log.setRecipientType(message.getRecipientType());
            log.setRecipientId(message.getRecipientId());
            log.setRecipientAddress(message.getRecipientAddress());
            log.setNotificationType(message.getNotificationType());
            log.setNotificationChannel(message.getNotificationChannel());
            log.setSubject(message.getSubject());
            log.setContent(message.getContent());
            log.setPriority(message.getPriority());
            log.setSendStatus(success ? STATUS_SUCCESS : STATUS_FAILED);
            log.setSendTime(DateUtils.getNowDate());
            log.setDeliveryTime(success ? DateUtils.getNowDate() : null);
            log.setRetryCount(0);
            log.setMaxRetryCount(3);
            log.setBusinessType(message.getBusinessType());
            log.setBusinessId(message.getBusinessId());
            log.setCreateTime(DateUtils.getNowDate());

            // 这里应该保存到数据库
            // notificationLogMapper.insertNotificationLog(log);

        } catch (Exception e) {
            log.error("记录通知日志失败: notificationId={}, error={}", 
                     message.getNotificationId(), e.getMessage(), e);
        }
    }

    /**
     * 生成通知ID
     */
    private String generateNotificationId() 
    {
        String dateStr = DateUtils.dateTimeNow("yyyyMMdd");
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8).toUpperCase();
        return "NOTIF" + dateStr + uuid;
    }

    /**
     * 渲染模板内容
     */
    private String renderTemplate(String template, Map<String, Object> parameters) 
    {
        if (template == null || parameters == null) {
            return template;
        }

        String result = template;
        for (Map.Entry<String, Object> entry : parameters.entrySet()) {
            String placeholder = "${" + entry.getKey() + "}";
            String value = entry.getValue() != null ? entry.getValue().toString() : "";
            result = result.replace(placeholder, value);
        }

        return result;
    }

    /**
     * 创建模拟模板（用于演示）
     */
    private NotificationTemplate createMockTemplate(String templateCode) 
    {
        NotificationTemplate template = new NotificationTemplate();
        template.setTemplateCode(templateCode);
        template.setTemplateStatus("ACTIVE");

        switch (templateCode) {
            case "PAYMENT_REMINDER":
                template.setTemplateId(1L);
                template.setTemplateName("付款提醒");
                template.setNotificationType("REMINDER");
                template.setSupportedChannels("EMAIL,SMS,WECHAT");
                template.setSubjectTemplate("付款提醒 - 合同${contractId}");
                template.setContentTemplate("尊敬的用户，您的合同${contractId}将于${dueDate}到期，应付金额${amount}元，请及时付款。");
                template.setBusinessType("CONTRACT");
                break;

            case "CONTRACT_STATUS_CHANGE":
                template.setTemplateId(2L);
                template.setTemplateName("合同状态变更");
                template.setNotificationType("STATUS_CHANGE");
                template.setSupportedChannels("EMAIL,SMS,SYSTEM");
                template.setSubjectTemplate("合同状态变更通知 - 合同${contractId}");
                template.setContentTemplate("您的合同${contractId}状态已从${oldStatus}变更为${newStatus}。");
                template.setBusinessType("CONTRACT");
                break;

            case "SYSTEM_ALERT":
                template.setTemplateId(3L);
                template.setTemplateName("系统告警");
                template.setNotificationType("ALERT");
                template.setSupportedChannels("EMAIL,SMS");
                template.setSubjectTemplate("系统告警 - ${alertType}");
                template.setContentTemplate("告警级别：${alertLevel}\n告警消息：${alertMessage}\n时间：${timestamp}");
                template.setBusinessType("SYSTEM");
                break;

            default:
                return null;
        }

        return template;
    }
}