package com.erp.notification.service.impl;

import com.erp.notification.dto.NotificationRequest;
import com.erp.notification.service.NotificationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 通知服务实现
 */
@Slf4j
@Service
public class NotificationServiceImpl implements NotificationService {

    private final RestTemplate restTemplate = new RestTemplate();

    @Value("${notification.dingtalk.webhook:}")
    private String dingTalkWebhook;

    @Value("${notification.dingtalk.enabled:false}")
    private boolean dingTalkEnabled;

    @Value("${notification.sms.enabled:false}")
    private boolean smsEnabled;

    @Value("${notification.email.enabled:false}")
    private boolean emailEnabled;

    private final StringRedisTemplate redisTemplate;

    public NotificationServiceImpl(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public boolean send(NotificationRequest request) {
        if (request == null || request.getType() == null) {
            log.warn("通知请求为空或类型为空");
            return false;
        }

        return switch (request.getType().toLowerCase()) {
            case "dingtalk" -> sendDingTalk(request.getTitle(), request.getContent());
            case "email" -> sendEmail(request.getRecipient(), request.getTitle(), request.getContent());
            case "sms" -> sendSms(request.getRecipient(), request.getContent());
            case "system" -> sendSystemNotice(
                    request.getTenantId(),
                    request.getTitle(),
                    request.getContent(),
                    request.getBizType(),
                    request.getBizId()
            );
            default -> {
                log.warn("未知通知类型: {}", request.getType());
                yield false;
            }
        };
    }

    @Override
    public boolean sendDingTalk(String title, String content) {
        if (!dingTalkEnabled || dingTalkWebhook == null || dingTalkWebhook.isEmpty()) {
            log.debug("钉钉通知未配置，跳过");
            return false;
        }

        try {
            String json = String.format(
                "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"%s\",\"text\":\"%s\"}}",
                escapeJson(title),
                escapeJson(content + "\n\n> 发送时间: " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            );

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> entity = new HttpEntity<>(json, headers);

            restTemplate.postForEntity(dingTalkWebhook, entity, String.class);
            log.info("钉钉通知发送成功: {}", title);
            return true;
        } catch (Exception e) {
            log.error("钉钉通知发送失败: {}", e.getMessage());
            return false;
        }
    }

    @Override
    public boolean sendEmail(String to, String subject, String content) {
        if (!emailEnabled || to == null || to.isEmpty()) {
            log.debug("邮件通知未配置或收件人为空，跳过");
            return false;
        }

        try {
            // TODO: 实现真实的邮件发送（可接入 SendGrid / 阿里云邮件）
            // 这里记录日志，模拟发送
            log.info("邮件通知发送 [模拟]: to={}, subject={}", to, subject);
            recordNotification("email", to, subject, content);
            return true;
        } catch (Exception e) {
            log.error("邮件通知发送失败: {}", e.getMessage());
            return false;
        }
    }

    @Override
    public boolean sendSms(String phone, String content) {
        if (!smsEnabled || phone == null || phone.isEmpty()) {
            log.debug("短信通知未配置或手机号为空，跳过");
            return false;
        }

        try {
            // TODO: 实现真实的短信发送（可接入阿里云/腾讯云短信）
            log.info("短信通知发送 [模拟]: phone={}, content={}", phone, content);
            recordNotification("sms", phone, null, content);
            return true;
        } catch (Exception e) {
            log.error("短信通知发送失败: {}", e.getMessage());
            return false;
        }
    }

    @Override
    public boolean sendSystemNotice(Long tenantId, String title, String content, String bizType, String bizId) {
        try {
            // 将系统通知记录到 Redis 队列，供前端查询
            String key = "notifications:tenant:" + tenantId;
            String json = String.format(
                "{\"title\":\"%s\",\"content\":\"%s\",\"bizType\":\"%s\",\"bizId\":\"%s\",\"time\":\"%s\",\"read\":false}",
                escapeJson(title),
                escapeJson(content),
                bizType != null ? bizType : "",
                bizId != null ? bizId : "",
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
            );
            redisTemplate.opsForList().leftPush(key, json);
            // 最多保留100条通知
            redisTemplate.opsForList().trim(key, 0, 99);
            // 通知30天过期
            redisTemplate.expire(key, 30, TimeUnit.DAYS);

            log.info("系统通知已记录: tenantId={}, title={}", tenantId, title);
            return true;
        } catch (Exception e) {
            log.error("系统通知记录失败: {}", e.getMessage());
            return false;
        }
    }

    @Override
    public void sendBatch(List<NotificationRequest> requests) {
        for (NotificationRequest request : requests) {
            try {
                send(request);
            } catch (Exception e) {
                log.error("批量发送通知失败: {}", e.getMessage());
            }
        }
    }

    /**
     * 记录通知发送历史到Redis
     */
    private void recordNotification(String type, String recipient, String subject, String content) {
        String key = "notification:history:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String json = String.format(
            "{\"type\":\"%s\",\"recipient\":\"%s\",\"subject\":\"%s\",\"time\":\"%s\"}",
            type,
            recipient,
            subject != null ? escapeJson(subject) : "",
            LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
        );
        redisTemplate.opsForList().leftPush(key, json);
        redisTemplate.opsForList().trim(key, 0, 999); // 每天最多1000条
    }

    /**
     * JSON字符串转义
     */
    private String escapeJson(String str) {
        if (str == null) return "";
        return str.replace("\\", "\\\\")
                  .replace("\"", "\\\"")
                  .replace("\n", "\\n")
                  .replace("\r", "\\r")
                  .replace("\t", "\\t");
    }
}
