package com.yimeng.okr.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yimeng.okr.entity.PerformanceScore;
import com.yimeng.okr.entity.ScoreAppeal;
import com.yimeng.okr.entity.SysUser;
import com.yimeng.okr.enums.ScoreType;
import com.yimeng.okr.enums.UserRole;
import com.yimeng.okr.event.NotificationEvent;
import com.yimeng.okr.exception.BusinessException;
import com.yimeng.okr.mapper.PerformanceScoreMapper;
import com.yimeng.okr.mapper.ScoreAppealMapper;
import com.yimeng.okr.mapper.SysUserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
public class ScoreAppealService {

    private static final String STATUS_OPEN = "OPEN";
    private static final String STATUS_PUBLISHED = "PUBLISHED";

    private final ScoreAppealMapper appealMapper;
    private final PerformanceScoreMapper scoreMapper;
    private final SysUserMapper userMapper;
    private final AuthorizationService authorizationService;
    private final ApplicationEventPublisher publisher;

    @Transactional
    public ScoreAppeal submitAppeal(Long periodId, Long userId, String reason) {
        if (reason == null || reason.trim().isEmpty()) {
            throw new BusinessException("申诉原因不能为空");
        }
        PerformanceScore score = scoreMapper.selectOne(
                new LambdaQueryWrapper<PerformanceScore>()
                        .eq(PerformanceScore::getPeriodId, periodId)
                        .eq(PerformanceScore::getUserId, userId)
                        .eq(PerformanceScore::getType, ScoreType.FINAL));
        if (score == null || !STATUS_PUBLISHED.equals(score.getStatus())) {
            throw new BusinessException("绩效结果尚未发布，暂不能提交申诉");
        }
        long openCount = appealMapper.selectCount(
                new LambdaQueryWrapper<ScoreAppeal>()
                        .eq(ScoreAppeal::getPeriodId, periodId)
                        .eq(ScoreAppeal::getUserId, userId)
                        .eq(ScoreAppeal::getStatus, STATUS_OPEN));
        if (openCount > 0) {
            throw new BusinessException("已有待处理申诉，请勿重复提交");
        }
        ScoreAppeal appeal = new ScoreAppeal();
        appeal.setPeriodId(periodId);
        appeal.setUserId(userId);
        appeal.setScoreId(score.getId());
        appeal.setStatus(STATUS_OPEN);
        appeal.setReason(reason.trim());
        appeal.setSubmittedAt(LocalDateTime.now());
        appealMapper.insert(appeal);
        notifyHr(appeal);
        return appeal;
    }

    @Transactional
    public ScoreAppeal resolveAppeal(Long appealId, Long operatorId, String status, String reply) {
        if (!authorizationService.isHrOrAbove(operatorId)) {
            throw new BusinessException(403, "无权限，需要HR管理员或以上权限");
        }
        if (!"ACCEPTED".equals(status) && !"REJECTED".equals(status)) {
            throw new BusinessException("申诉处理状态必须为 ACCEPTED 或 REJECTED");
        }
        ScoreAppeal appeal = appealMapper.selectById(appealId);
        if (appeal == null) {
            throw new BusinessException(404, "申诉不存在");
        }
        if (!STATUS_OPEN.equals(appeal.getStatus())) {
            throw new BusinessException("申诉已处理，无需重复处理");
        }
        appeal.setStatus(status);
        appeal.setReply(reply);
        appeal.setResolvedBy(operatorId);
        appeal.setResolvedAt(LocalDateTime.now());
        appealMapper.updateById(appeal);
        publisher.publishEvent(new NotificationEvent(
                this, appeal.getUserId(), "SCORE_APPEAL_RESOLVED",
                "绩效申诉已处理", "你的绩效申诉已处理，处理结果：" + status,
                "score_appeal", appeal.getId()));
        return appeal;
    }

    public List<ScoreAppeal> listAppeals(Long operatorId, String status) {
        if (!authorizationService.isHrOrAbove(operatorId)) {
            throw new BusinessException(403, "无权限，需要HR管理员或以上权限");
        }
        LambdaQueryWrapper<ScoreAppeal> wrapper = new LambdaQueryWrapper<ScoreAppeal>()
                .orderByDesc(ScoreAppeal::getSubmittedAt);
        if (status != null && !status.isBlank()) {
            wrapper.eq(ScoreAppeal::getStatus, status);
        }
        return appealMapper.selectList(wrapper);
    }

    private void notifyHr(ScoreAppeal appeal) {
        List<SysUser> admins = userMapper.selectList(
                new LambdaQueryWrapper<SysUser>()
                        .in(SysUser::getRole, List.of(UserRole.HR_ADMIN, UserRole.SUPER_ADMIN)));
        if (admins == null) return;
        for (SysUser admin : admins) {
            publisher.publishEvent(new NotificationEvent(
                    this, admin.getId(), "SCORE_APPEAL_SUBMITTED",
                    "新的绩效申诉", "有员工提交了绩效申诉，请及时处理",
                    "score_appeal", appeal.getId()));
        }
    }
}
