package com.njcn.rdms.module.project.service.workreport.remind;

import com.njcn.rdms.module.project.constant.WorkReportConstants;
import com.njcn.rdms.module.project.dal.dataobject.workreport.monthly.MonthlyReportDO;
import com.njcn.rdms.module.project.dal.dataobject.workreport.project.ProjectReportDO;
import com.njcn.rdms.module.project.dal.dataobject.workreport.weekly.WeeklyReportDO;
import com.njcn.rdms.module.project.dal.mysql.workreport.monthly.MonthlyReportMapper;
import com.njcn.rdms.module.project.dal.mysql.workreport.project.ProjectReportMapper;
import com.njcn.rdms.module.project.dal.mysql.workreport.weekly.WeeklyReportMapper;
import com.njcn.rdms.module.project.framework.notify.NotifySendEvent;
import com.njcn.rdms.module.project.framework.notify.NotifyTemplateCodeConstants;
import com.njcn.rdms.module.system.enums.notify.NotifyMessageLevelConstants;
import jakarta.annotation.Resource;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.IsoFields;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class WorkReportPendingSubmitRemindService {

    private static final List<String> REMIND_STATUS_CODES = List.of(
            WorkReportConstants.STATUS_DRAFT,
            WorkReportConstants.STATUS_REJECTED);

    @Resource
    private WeeklyReportMapper weeklyReportMapper;
    @Resource
    private MonthlyReportMapper monthlyReportMapper;
    @Resource
    private ProjectReportMapper projectReportMapper;
    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Transactional(rollbackFor = Exception.class)
    public void remindPendingSubmitReports() {
        LocalDateTime cutoffTime = LocalDateTime.now().minusDays(2);
        remindWeekly(cutoffTime);
        remindMonthly(cutoffTime);
        remindProject(cutoffTime);
    }

    private void remindWeekly(LocalDateTime cutoffTime) {
        List<WeeklyReportDO> reports = weeklyReportMapper.selectListByPendingSubmitReminder(cutoffTime, REMIND_STATUS_CODES);
        for (WeeklyReportDO report : reports) {
            if (report == null || report.getReporterId() == null) {
                continue;
            }
            Map<String, Object> params = new HashMap<>();
            params.put("reportTypeName", "周报");
            params.put("periodKey", formatWeeklyPeriod(report.getPeriodKey(), report.getPeriodStartDate(), report.getPeriodEndDate()));
            params.put("managerName", defaultText(report.getSupervisorName(), "系统通知"));
            applicationEventPublisher.publishEvent(NotifySendEvent.of(
                    List.of(report.getReporterId()),
                    NotifyTemplateCodeConstants.WORK_REPORT_TEAM_REMIND,
                    params,
                    NotifyMessageLevelConstants.REMIND));
        }
    }

    private void remindMonthly(LocalDateTime cutoffTime) {
        List<MonthlyReportDO> reports = monthlyReportMapper.selectListByPendingSubmitReminder(cutoffTime, REMIND_STATUS_CODES);
        for (MonthlyReportDO report : reports) {
            if (report == null || report.getReporterId() == null) {
                continue;
            }
            Map<String, Object> params = new HashMap<>();
            params.put("reportTypeName", "月报");
            params.put("periodKey", formatMonthlyPeriod(report.getPeriodKey(), report.getPeriodStartDate()));
            params.put("managerName", defaultText(report.getSupervisorName(), "系统通知"));
            applicationEventPublisher.publishEvent(NotifySendEvent.of(
                    List.of(report.getReporterId()),
                    NotifyTemplateCodeConstants.WORK_REPORT_TEAM_REMIND,
                    params,
                    NotifyMessageLevelConstants.REMIND));
        }
    }

    private void remindProject(LocalDateTime cutoffTime) {
        List<ProjectReportDO> reports = projectReportMapper.selectListByPendingSubmitReminder(cutoffTime, REMIND_STATUS_CODES);
        for (ProjectReportDO report : reports) {
            if (report == null || report.getProjectOwnerId() == null) {
                continue;
            }
            Map<String, Object> params = new HashMap<>();
            params.put("projectName", defaultText(report.getProjectName(), ""));
            params.put("periodLabel", defaultText(report.getPeriodLabel(), report.getPeriodKey()));
            params.put("managerName", defaultText(report.getSupervisorName(), "系统通知"));
            applicationEventPublisher.publishEvent(NotifySendEvent.of(
                    List.of(report.getProjectOwnerId()),
                    NotifyTemplateCodeConstants.WORK_REPORT_PROJECT_HALF_MONTH_TEAM_REMIND,
                    params,
                    NotifyMessageLevelConstants.REMIND));
        }
    }

    private String formatWeeklyPeriod(String periodKey, LocalDate startDate, LocalDate endDate) {
        if (startDate == null || endDate == null) {
            return defaultText(periodKey, "");
        }
        int weekBasedYear = startDate.get(IsoFields.WEEK_BASED_YEAR);
        int weekOfYear = startDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
        return weekBasedYear + "年" + weekOfYear + "周（"
                + startDate.getMonthValue() + "月" + startDate.getDayOfMonth() + "日-"
                + endDate.getMonthValue() + "月" + endDate.getDayOfMonth() + "日）";
    }

    private String formatMonthlyPeriod(String periodKey, LocalDate startDate) {
        if (startDate == null) {
            return defaultText(periodKey, "");
        }
        return startDate.getYear() + "年" + startDate.getMonthValue() + "月";
    }

    private String defaultText(String text, String fallback) {
        return StringUtils.hasText(text) ? text.trim() : fallback;
    }
}
