package com.qqchen.deploy.backend.notification.service.impl;

import com.qqchen.deploy.backend.framework.annotation.ServiceType;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.exception.UniqueConstraintException;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.framework.utils.JsonUtils;
import com.qqchen.deploy.backend.notification.adapter.INotificationChannelAdapter;
import com.qqchen.deploy.backend.notification.dto.BaseSendNotificationRequest;
import com.qqchen.deploy.backend.notification.dto.NotificationChannelDTO;
import com.qqchen.deploy.backend.notification.dto.NotificationChannelQuery;
import com.qqchen.deploy.backend.notification.entity.NotificationChannel;
import com.qqchen.deploy.backend.notification.entity.config.BaseNotificationConfig;
import com.qqchen.deploy.backend.notification.entity.config.EmailNotificationConfig;
import com.qqchen.deploy.backend.notification.entity.config.WeworkNotificationConfig;
import com.qqchen.deploy.backend.notification.factory.NotificationChannelAdapterFactory;
import com.qqchen.deploy.backend.notification.service.INotificationChannelService;
import com.qqchen.deploy.backend.notification.service.INotificationSendService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.qqchen.deploy.backend.framework.annotation.ServiceType.Type.DATABASE;

/**
 * 通知渠道Service实现
 *
 * @author qqchen
 * @since 2025-10-22
 */
@Slf4j
@Service
@ServiceType(DATABASE)
public class NotificationSendServiceImpl implements INotificationSendService {

    @Resource
    private NotificationChannelAdapterFactory adapterFactory;

    public void send(NotificationChannel channel, BaseSendNotificationRequest request) {
        // 1. 参数校验
        if (channel == null || request == null) {
            throw new BusinessException(ResponseCode.INVALID_PARAM);
        }

        if (request.getContent() == null || request.getContent().isEmpty()) {
            throw new BusinessException(ResponseCode.INVALID_PARAM);
        }

        // 2. 校验渠道状态
        if (!channel.getEnabled()) {
            throw new BusinessException(ResponseCode.NOTIFICATION_CHANNEL_DISABLED);
        }

        // 3. 获取对应的适配器
        INotificationChannelAdapter adapter;
        try {
            adapter = adapterFactory.getAdapter(channel.getChannelType());
        } catch (IllegalArgumentException e) {
            log.error("获取通知渠道适配器失败: {}", e.getMessage());
            throw new BusinessException(ResponseCode.ERROR);
        }

        // 5. 转换配置
        BaseNotificationConfig config = convertConfig(channel);

        // 6. 发送通知
        try {
            log.info("发送通知 - 渠道ID: {}, 渠道类型: {}, 内容: {}", channel.getId(), channel.getChannelType(), request.getContent());

            adapter.send(config, request);
            log.info("通知发送成功 - 渠道ID: {}", channel.getId());
        } catch (IllegalArgumentException e) {
            // 配置错误（如 Webhook Key 未配置）
            log.error("通知渠道配置错误 - 渠道ID: {}, 错误: {}", channel.getId(), e.getMessage());
            throw new BusinessException(ResponseCode.NOTIFICATION_CHANNEL_CONFIG_ERROR, new Object[] {e.getMessage()});
        } catch (Exception e) {
            log.error("通知发送失败 - 渠道ID: {}, 错误: {}", channel.getId(), e.getMessage(), e);
            throw new BusinessException(ResponseCode.NOTIFICATION_SEND_FAILED, new Object[] {e.getMessage()});
        }
    }

    /**
     * 将Map配置转换为具体的配置类型
     */
    private BaseNotificationConfig convertConfig(NotificationChannel channel) {
        return switch (channel.getChannelType()) {
            case WEWORK -> JsonUtils.fromMap(channel.getConfig(), WeworkNotificationConfig.class);
            case EMAIL -> JsonUtils.fromMap(channel.getConfig(), EmailNotificationConfig.class);
            default -> throw new IllegalArgumentException("不支持的渠道类型: " + channel.getChannelType());
        };
    }
}

