package com.writeoff.module.notification.provider;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.writeoff.module.notification.model.PlatformNotifyGatewayResolvedConfig;
import com.writeoff.module.notification.service.PlatformNotifyGatewayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Properties;

@Component
public class EmailNotificationProvider implements NotificationChannelProvider {
    private static final Logger log = LoggerFactory.getLogger(EmailNotificationProvider.class);
    private final PlatformNotifyGatewayService gatewayService;
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final String defaultSubject;

    public EmailNotificationProvider(PlatformNotifyGatewayService gatewayService,
                                     @Value("${app.notification.mail.default-subject:绯荤粺閫氱煡}") String defaultSubject) {
        this.gatewayService = gatewayService;
        this.defaultSubject = defaultSubject == null ? "绯荤粺閫氱煡" : defaultSubject.trim();
    }

    @Override
    public String channel() {
        return "EMAIL";
    }

    @Override
    public NotificationSendResult send(String receiverRef, String payloadJson, Map<String, Object> context) {
        if (receiverRef == null || receiverRef.trim().isEmpty()) {
            return new NotificationSendResult(false, null, "INVALID_RECEIVER", "閭鍦板潃涓嶈兘涓虹┖");
        }
        long start = System.currentTimeMillis();
        try {
            PlatformNotifyGatewayResolvedConfig gatewayConfig = gatewayService.resolveChannelConfig("EMAIL", true);
            JavaMailSenderImpl sender = resolveMailSender(gatewayConfig);
            Map<String, Object> runtimeConfig = gatewayConfig.getConfig();
            String subject = textOr(runtimeConfig.get("defaultSubject"), defaultSubject);
            String content = payloadJson == null ? "" : payloadJson;
            if (payloadJson != null && payloadJson.trim().startsWith("{")) {
                Map<String, Object> payload = objectMapper.readValue(payloadJson, new TypeReference<Map<String, Object>>() {});
                Object sub = payload.get("subject");
                Object body = payload.get("content");
                if (sub != null && String.valueOf(sub).trim().length() > 0) {
                    subject = String.valueOf(sub).trim();
                }
                if (body != null) {
                    content = String.valueOf(body);
                }
            }
            SimpleMailMessage message = new SimpleMailMessage();
            String runtimeFrom = text(runtimeConfig.get("fromAddress"));
            if (!runtimeFrom.isEmpty()) {
                message.setFrom(runtimeFrom);
            }
            message.setTo(receiverRef.trim());
            message.setSubject(subject);
            message.setText(content == null ? "" : content);
            log.info("email sending start, to={}, subject={}", receiverRef.trim(), subject);
            sender.send(message);
            String id = "EMAIL-" + System.currentTimeMillis();
            log.info("email sending success, to={}, messageId={}, elapsedMs={}", receiverRef.trim(), id, System.currentTimeMillis() - start);
            return new NotificationSendResult(true, id, "SENT", "閭欢鍙戦€佹垚鍔?");
        } catch (Exception ex) {
            log.error("email sending failed, to={}, elapsedMs={}, reason={}", receiverRef.trim(), System.currentTimeMillis() - start, ex.getMessage(), ex);
            return new NotificationSendResult(false, null, "SEND_FAILED", ex.getMessage());
        }
    }

    private JavaMailSenderImpl resolveMailSender(PlatformNotifyGatewayResolvedConfig gatewayConfig) {
        if (gatewayConfig == null || gatewayConfig.getConfig() == null) {
            throw new IllegalStateException("邮件网关未启用或未配置");
        }
        Map<String, Object> config = gatewayConfig.getConfig();
        if (text(config.get("host")).isEmpty()) {
            throw new IllegalStateException("邮件网关缺少 SMTP Host 配置");
        }
        if (text(config.get("fromAddress")).isEmpty()) {
            throw new IllegalStateException("邮件网关缺少发件邮箱配置");
        }
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setHost(text(config.get("host")));
        sender.setPort(intValue(config.get("port"), 587));
        sender.setProtocol(textOr(config.get("protocol"), "smtp"));
        sender.setUsername(text(config.get("username")));
        sender.setPassword(text(config.get("password")));
        Properties props = sender.getJavaMailProperties();
        props.put("mail.smtp.auth", String.valueOf(boolValue(config.get("smtpAuth"), true)));
        props.put("mail.smtp.starttls.enable", String.valueOf(boolValue(config.get("starttlsEnable"), true)));
        props.put("mail.smtp.starttls.required", String.valueOf(boolValue(config.get("starttlsRequired"), false)));
        props.put("mail.smtp.ssl.enable", String.valueOf(boolValue(config.get("sslEnable"), false)));
        props.put("mail.smtp.connectiontimeout", String.valueOf(intValue(config.get("connectTimeoutMs"), 5000)));
        props.put("mail.smtp.timeout", String.valueOf(intValue(config.get("timeoutMs"), 5000)));
        props.put("mail.smtp.writetimeout", String.valueOf(intValue(config.get("writeTimeoutMs"), 5000)));
        return sender;
    }

    private String text(Object value) {
        return value == null ? "" : String.valueOf(value).trim();
    }

    private String textOr(Object value, String fallback) {
        String text = text(value);
        return text.isEmpty() ? fallback : text;
    }

    private int intValue(Object value, int fallback) {
        if (value == null) {
            return fallback;
        }
        try {
            return value instanceof Number ? ((Number) value).intValue() : Integer.parseInt(String.valueOf(value).trim());
        } catch (Exception ex) {
            return fallback;
        }
    }

    private boolean boolValue(Object value, boolean fallback) {
        if (value == null) {
            return fallback;
        }
        if (value instanceof Boolean) {
            return (Boolean) value;
        }
        String text = String.valueOf(value).trim();
        if ("true".equalsIgnoreCase(text) || "1".equals(text)) {
            return true;
        }
        if ("false".equalsIgnoreCase(text) || "0".equals(text)) {
            return false;
        }
        return fallback;
    }
}
