package com.yimeng.okr.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yimeng.okr.dto.OkrDetailDto;
import com.yimeng.okr.dto.ScoringDto;
import com.yimeng.okr.entity.PerformanceFeedback;
import com.yimeng.okr.entity.PerformanceScore;
import com.yimeng.okr.enums.ScoreType;
import com.yimeng.okr.event.NotificationEvent;
import com.yimeng.okr.exception.BusinessException;
import com.yimeng.okr.mapper.PerformanceFeedbackMapper;
import com.yimeng.okr.mapper.PerformanceScoreMapper;
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 FeedbackService {

    private static final String STATUS_PENDING_EMPLOYEE = "PENDING_EMPLOYEE";
    private static final String STATUS_REPLIED = "REPLIED";
    private static final String STATUS_CLOSED = "CLOSED";

    private final PerformanceFeedbackMapper feedbackMapper;
    private final PerformanceScoreMapper scoreMapper;
    private final OkrService okrService;
    private final PerformanceService performanceService;
    private final AuthorizationService authorizationService;
    private final ApplicationEventPublisher publisher;

    @Transactional
    public PerformanceFeedback saveInterviewNotes(Long periodId, Long userId, Long superiorId,
                                                   String interviewNotes, String highlights,
                                                   String issues, String improvements) {
        authorizationService.requireCanManageUserData(superiorId, userId);
        PerformanceFeedback existing = feedbackMapper.selectOne(
                new LambdaQueryWrapper<PerformanceFeedback>()
                        .eq(PerformanceFeedback::getPeriodId, periodId)
                        .eq(PerformanceFeedback::getUserId, userId));
        if (existing != null) {
            existing.setInterviewNotes(interviewNotes);
            existing.setHighlights(highlights);
            existing.setIssues(issues);
            existing.setImprovements(improvements);
            existing.setStatus(STATUS_PENDING_EMPLOYEE);
            existing.setClosedAt(null);
            feedbackMapper.updateById(existing);
            publisher.publishEvent(new NotificationEvent(
                    this, userId, "FEEDBACK_NOTIFY",
                    "绩效面谈通知", "你的上级发起了绩效面谈，请查看并回复",
                    "feedback", existing.getId()));
            return existing;
        }

        PerformanceFeedback fb = new PerformanceFeedback();
        fb.setPeriodId(periodId);
        fb.setUserId(userId);
        fb.setSuperiorId(superiorId);
        fb.setInterviewNotes(interviewNotes);
        fb.setHighlights(highlights);
        fb.setIssues(issues);
        fb.setImprovements(improvements);
        fb.setStatus(STATUS_PENDING_EMPLOYEE);
        feedbackMapper.insert(fb);
        publisher.publishEvent(new NotificationEvent(
                this, userId, "FEEDBACK_NOTIFY",
                "绩效面谈通知", "你的上级发起了绩效面谈，请查看并回复",
                "feedback", fb.getId()));
        return fb;
    }

    @Transactional
    public PerformanceFeedback submitEmployeeFeedback(Long periodId, Long userId, String feedback) {
        if (feedback == null || feedback.trim().isEmpty()) {
            throw new BusinessException("员工反馈不能为空");
        }
        PerformanceFeedback existing = feedbackMapper.selectOne(
                new LambdaQueryWrapper<PerformanceFeedback>()
                        .eq(PerformanceFeedback::getPeriodId, periodId)
                        .eq(PerformanceFeedback::getUserId, userId));
        if (existing == null) {
            throw new BusinessException("面谈记录尚未填写，无法提交反馈");
        }
        if (STATUS_CLOSED.equals(existing.getStatus())) {
            throw new BusinessException("面谈已关闭，无法再次提交反馈");
        }
        existing.setEmployeeFeedback(feedback);
        existing.setStatus(STATUS_REPLIED);
        feedbackMapper.updateById(existing);
        return existing;
    }

    @Transactional
    public PerformanceFeedback closeFeedback(Long periodId, Long userId, Long actorId) {
        authorizationService.requireCanManageUserData(actorId, userId);
        PerformanceFeedback existing = feedbackMapper.selectOne(
                new LambdaQueryWrapper<PerformanceFeedback>()
                        .eq(PerformanceFeedback::getPeriodId, periodId)
                        .eq(PerformanceFeedback::getUserId, userId));
        if (existing == null) {
            throw new BusinessException("面谈记录尚未填写，无法关闭");
        }
        if (STATUS_CLOSED.equals(existing.getStatus())) {
            throw new BusinessException("面谈已关闭，无需重复关闭");
        }
        if (!STATUS_REPLIED.equals(existing.getStatus())) {
            throw new BusinessException("员工尚未回复，无法关闭面谈");
        }
        if (existing.getEmployeeFeedback() == null || existing.getEmployeeFeedback().trim().isEmpty()) {
            throw new BusinessException("员工反馈尚未提交，无法关闭面谈");
        }
        existing.setStatus(STATUS_CLOSED);
        existing.setClosedAt(LocalDateTime.now());
        feedbackMapper.updateById(existing);
        return existing;
    }

    public ScoringDto getFeedbackPage(Long periodId, Long userId, Long actorId) {
        authorizationService.requireCanViewUserData(actorId, userId);
        return performanceService.getScoringPage(periodId, userId, actorId);
    }
}
