package com.writeoff.module.notification.service;

import com.writeoff.common.api.PageResult;
import com.writeoff.common.exception.BusinessException;
import com.writeoff.module.notification.dto.CreateNotificationTextTemplateRequest;
import com.writeoff.module.notification.dto.UpdateNotificationTextTemplateRequest;
import com.writeoff.module.notification.model.NotificationTextTemplateInfo;
import com.writeoff.security.AuthContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class NotificationTextTemplateService {
    private final JdbcTemplate jdbcTemplate;

    private static final RowMapper<NotificationTextTemplateInfo> ROW_MAPPER = (rs, n) -> new NotificationTextTemplateInfo(
            rs.getLong("id"),
            rs.getString("template_name"),
            rs.getString("subject_template"),
            rs.getString("title_template"),
            rs.getString("content_template"),
            rs.getString("status")
    );

    public NotificationTextTemplateService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public PageResult<NotificationTextTemplateInfo> list(int pageNo, int pageSize) {
        int safePage = Math.max(pageNo, 1);
        int safeSize = Math.min(Math.max(pageSize, 1), 200);
        int offset = (safePage - 1) * safeSize;

        Integer total = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM notification_text_template WHERE tenant_id=? AND is_deleted=0",
                Integer.class,
                tenantId()
        );
        long totalCount = total == null ? 0 : total;

        List<NotificationTextTemplateInfo> list = jdbcTemplate.query(
                "SELECT id, template_name, subject_template, title_template, content_template, status " +
                        "FROM notification_text_template WHERE tenant_id=? AND is_deleted=0 ORDER BY id DESC LIMIT ? OFFSET ?",
                ROW_MAPPER,
                tenantId(),
                safeSize,
                offset
        );
        return new PageResult<NotificationTextTemplateInfo>(list, totalCount, safePage, safeSize);
    }

    @Transactional(rollbackFor = Exception.class)
    public NotificationTextTemplateInfo create(CreateNotificationTextTemplateRequest request) {
        assertTemplateNameUnique(request.getTemplateName().trim(), null);
        String status = normalizeStatus(request.getStatus());
        jdbcTemplate.update(
                "INSERT INTO notification_text_template (tenant_id, template_name, subject_template, title_template, content_template, status, created_by, updated_by) " +
                        "VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
                tenantId(),
                request.getTemplateName().trim(),
                trimText(request.getSubjectTemplate()),
                trimText(request.getTitleTemplate()),
                request.getContentTemplate().trim(),
                status,
                safeUserId(),
                safeUserId()
        );
        Long id = jdbcTemplate.queryForObject("SELECT IFNULL(MAX(id), 0) FROM notification_text_template WHERE tenant_id=?", Long.class, tenantId());
        return findById(id == null ? 0L : id);
    }

    @Transactional(rollbackFor = Exception.class)
    public NotificationTextTemplateInfo update(Long id, UpdateNotificationTextTemplateRequest request) {
        assertExists(id);
        assertTemplateNameUnique(request.getTemplateName().trim(), id);
        String status = normalizeStatus(request.getStatus());
        jdbcTemplate.update(
                "UPDATE notification_text_template SET template_name=?, subject_template=?, title_template=?, content_template=?, status=?, updated_at=CURRENT_TIMESTAMP, updated_by=? " +
                        "WHERE tenant_id=? AND id=?",
                request.getTemplateName().trim(),
                trimText(request.getSubjectTemplate()),
                trimText(request.getTitleTemplate()),
                request.getContentTemplate().trim(),
                status,
                safeUserId(),
                tenantId(),
                id
        );
        return findById(id);
    }

    public NotificationTextTemplateInfo enable(Long id) {
        return updateStatus(id, "ENABLED");
    }

    public NotificationTextTemplateInfo disable(Long id) {
        return updateStatus(id, "DISABLED");
    }

    @Transactional(rollbackFor = Exception.class)
    public void softDelete(Long id) {
        assertExists(id);
        NotificationTextTemplateInfo tpl = findById(id);
        if ("ENABLED".equals(tpl.getStatus())) {
            throw new BusinessException(10001, "请先停用文案模板再删除");
        }
        // 检查是否被活跃策略引用
        Integer refCount = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM notification_policy WHERE tenant_id=? AND template_id=? AND is_deleted=0",
                Integer.class, tenantId(), id);
        if (refCount != null && refCount > 0) {
            throw new BusinessException(10001, "该文案模板仍被通知策略引用，请先调整策略");
        }
        jdbcTemplate.update(
                "UPDATE notification_text_template SET is_deleted=1, updated_at=CURRENT_TIMESTAMP, updated_by=? WHERE tenant_id=? AND id=?",
                safeUserId(), tenantId(), id);
    }

    private NotificationTextTemplateInfo updateStatus(Long id, String status) {
        assertExists(id);
        jdbcTemplate.update(
                "UPDATE notification_text_template SET status=?, updated_at=CURRENT_TIMESTAMP, updated_by=? WHERE tenant_id=? AND id=?",
                status,
                safeUserId(),
                tenantId(),
                id
        );
        return findById(id);
    }

    private NotificationTextTemplateInfo findById(Long id) {
        List<NotificationTextTemplateInfo> list = jdbcTemplate.query(
                "SELECT id, template_name, subject_template, title_template, content_template, status " +
                        "FROM notification_text_template WHERE tenant_id=? AND id=? AND is_deleted=0",
                ROW_MAPPER,
                tenantId(),
                id
        );
        if (list.isEmpty()) {
            throw new BusinessException(10003, "通知文案模板不存在");
        }
        return list.get(0);
    }

    private void assertExists(Long id) {
        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM notification_text_template WHERE tenant_id=? AND id=? AND is_deleted=0",
                Integer.class,
                tenantId(),
                id
        );
        if (count == null || count == 0) {
            throw new BusinessException(10003, "通知文案模板不存在");
        }
    }

    private String normalizeStatus(String status) {
        String val = status == null ? "ENABLED" : status.trim().toUpperCase();
        if (!"ENABLED".equals(val) && !"DISABLED".equals(val)) {
            throw new BusinessException(10001, "状态仅支持 ENABLED/DISABLED");
        }
        return val;
    }

    private void assertTemplateNameUnique(String templateName, Long excludeId) {
        String normalized = templateName == null ? "" : templateName.trim();
        if (normalized.length() == 0) {
            throw new BusinessException(10001, "文案模板名称不能为空");
        }
        Integer count;
        if (excludeId == null) {
            count = jdbcTemplate.queryForObject(
                    "SELECT COUNT(1) FROM notification_text_template WHERE tenant_id=? AND template_name=? AND is_deleted=0",
                    Integer.class,
                    tenantId(),
                    normalized
            );
        } else {
            count = jdbcTemplate.queryForObject(
                    "SELECT COUNT(1) FROM notification_text_template WHERE tenant_id=? AND template_name=? AND is_deleted=0 AND id<>?",
                    Integer.class,
                    tenantId(),
                    normalized,
                    excludeId
            );
        }
        if (count != null && count > 0) {
            throw new BusinessException(10001, "文案模板名称已存在，请换一个名称");
        }
    }

    private String trimText(String text) {
        if (text == null) {
            return null;
        }
        String val = text.trim();
        return val.length() == 0 ? null : val;
    }

    private Long safeUserId() {
        Long userId = AuthContext.userId();
        return userId == null ? 0L : userId;
    }

    private Long tenantId() {
        return AuthContext.requireTenantId();
    }
}
