package com.yimeng.okr.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yimeng.okr.dto.WorkflowActionDto;
import com.yimeng.okr.dto.WorkspaceOverviewDto;
import com.yimeng.okr.entity.AssessmentPeriod;
import com.yimeng.okr.enums.PeriodStatus;
import com.yimeng.okr.mapper.AssessmentPeriodMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class WorkspaceService {

    private final JdbcTemplate jdbcTemplate;
    private final AssessmentPeriodMapper periodMapper;

    public WorkspaceOverviewDto getOverview(Long userId, Long periodId) {
        AssessmentPeriod period;
        if (periodId != null) {
            period = periodMapper.selectById(periodId);
        } else {
            period = findRecommendedPeriod();
        }
        if (period == null) {
            return emptyOverview();
        }

        WorkspaceOverviewDto dto = new WorkspaceOverviewDto();

        WorkspaceOverviewDto.RecommendedPeriod rp = new WorkspaceOverviewDto.RecommendedPeriod();
        rp.setId(period.getId());
        rp.setName(period.getName());
        rp.setStatus(period.getStatus().name());
        rp.setStartDate(period.getStartDate() != null ? period.getStartDate().toString() : null);
        rp.setEndDate(period.getEndDate() != null ? period.getEndDate().toString() : null);
        dto.setRecommendedPeriod(rp);

        List<AssessmentPeriod> allPeriods = periodMapper.selectList(
                new LambdaQueryWrapper<AssessmentPeriod>()
                        .ne(AssessmentPeriod::getStatus, PeriodStatus.ARCHIVED)
                        .orderByDesc(AssessmentPeriod::getStartDate));
        List<WorkspaceOverviewDto.PeriodOption> options = new ArrayList<>();
        for (AssessmentPeriod p : allPeriods) {
            WorkspaceOverviewDto.PeriodOption opt = new WorkspaceOverviewDto.PeriodOption();
            opt.setId(p.getId());
            opt.setName(p.getName());
            opt.setStatus(p.getStatus().name());
            options.add(opt);
        }
        dto.setAvailablePeriods(options);
        dto.setCurrentPhase(period.getStatus().name());
        dto.setMyTodos(buildTodos(userId, period));
        dto.setTeamSummary(buildTeamSummary(userId, period.getId()));
        dto.setRisks(buildRisks(period.getId(), userId));
        dto.setUpcomingDeadlines(buildDeadlines(period));
        dto.setAllowedActions(buildAllowedActions(period, userId));

        return dto;
    }

    private AssessmentPeriod findRecommendedPeriod() {
        var periods = periodMapper.selectList(
                new LambdaQueryWrapper<AssessmentPeriod>()
                        .in(AssessmentPeriod::getStatus, Arrays.asList(PeriodStatus.OKR_ALIGN, PeriodStatus.EXECUTING, PeriodStatus.ASSESSING))
                        .orderByDesc(AssessmentPeriod::getStartDate));
        if (!periods.isEmpty()) return periods.get(0);

        periods = periodMapper.selectList(
                new LambdaQueryWrapper<AssessmentPeriod>()
                        .ne(AssessmentPeriod::getStatus, PeriodStatus.ARCHIVED)
                        .orderByDesc(AssessmentPeriod::getStartDate));
        return periods.isEmpty() ? null : periods.get(0);
    }

    private List<WorkspaceOverviewDto.TodoItem> buildTodos(Long userId, AssessmentPeriod period) {
        List<WorkspaceOverviewDto.TodoItem> todos = new ArrayList<>();
        String status = period.getStatus().name();

        if ("OKR_ALIGN".equals(status)) {
            Integer count = jdbcTemplate.queryForObject(
                    "SELECT COUNT(*) FROM okr_objective WHERE period_id = ? AND user_id = ? AND (deleted IS NULL OR deleted = 0)",
                    Integer.class, period.getId(), userId);
            if (count == null || count == 0) {
                todos.add(todo("DRAFT_OKR", "制定 OKR", "/okr/my", period.getId()));
            } else {
                todos.add(todo("EDIT_OKR", "修改 OKR", "/okr/my", period.getId()));
            }
            Integer pending = jdbcTemplate.queryForObject(
                    "SELECT COUNT(*) FROM okr_objective o JOIN sys_user u ON o.user_id = u.id " +
                    "WHERE o.period_id = ? AND u.superior_id = ? AND o.status = 'SUBMITTED'",
                    Integer.class, period.getId(), userId);
            if (pending != null && pending > 0) {
                todos.add(todo("REVIEW_OKR", "审核下属 OKR", "/okr/team", period.getId(), null, pending));
            }
        }

        if ("EXECUTING".equals(status)) {
            Integer krCount = jdbcTemplate.queryForObject(
                    "SELECT COUNT(*) FROM kr_key_result k JOIN okr_objective o ON k.objective_id = o.id " +
                    "WHERE o.period_id = ? AND o.user_id = ? AND k.status != 'COMPLETED'",
                    Integer.class, period.getId(), userId);
            if (krCount != null && krCount > 0) {
                todos.add(todo("UPDATE_PROGRESS", "更新 KR 进度", "/okr/execution", period.getId(), null, krCount));
            }
        }

        if ("ASSESSING".equals(status)) {
            Integer selfCount = jdbcTemplate.queryForObject(
                    "SELECT COUNT(*) FROM performance_score WHERE period_id = ? AND user_id = ? AND type = 'SELF'",
                    Integer.class, period.getId(), userId);
            if (selfCount == null || selfCount == 0) {
                todos.add(todo("SELF_SCORE", "提交自评", "/scores/my", period.getId()));
            }
            Integer finalCount = jdbcTemplate.queryForObject(
                    "SELECT COUNT(*) FROM sys_user WHERE superior_id = ? AND deleted = 0",
                    Integer.class, userId);
            if (finalCount != null && finalCount > 0) {
                Integer pendingFinal = jdbcTemplate.queryForObject(
                        "SELECT COUNT(*) FROM performance_score s JOIN sys_user u ON s.user_id = u.id " +
                        "WHERE s.period_id = ? AND u.superior_id = ? AND s.type = 'SELF' AND s.status = 'SELF_SUBMITTED'",
                        Integer.class, period.getId(), userId);
                if (pendingFinal != null && pendingFinal > 0) {
                    todos.add(todo("FINAL_SCORE", "完成终评", "/scores/review", period.getId(), null, pendingFinal));
                }
            }
        }

        return todos;
    }

    private WorkspaceOverviewDto.TodoItem todo(String type, String label, String url, Long periodId) {
        return todo(type, label, url, periodId, null, null);
    }

    private WorkspaceOverviewDto.TodoItem todo(String type, String label, String url, Long periodId, Long objectId, Integer count) {
        WorkspaceOverviewDto.TodoItem item = new WorkspaceOverviewDto.TodoItem();
        item.setType(type);
        item.setLabel(label);
        item.setTargetUrl(url + "?periodId=" + periodId);
        item.setPeriodId(periodId);
        item.setObjectId(objectId);
        item.setCount(count);
        return item;
    }

    private WorkspaceOverviewDto.TeamSummary buildTeamSummary(Long userId, Long periodId) {
        WorkspaceOverviewDto.TeamSummary ts = new WorkspaceOverviewDto.TeamSummary();
        Integer total = jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM sys_user WHERE superior_id = ? AND deleted = 0", Integer.class, userId);
        ts.setTotalMembers(total != null ? total : 0);

        if (ts.getTotalMembers() > 0) {
            Integer okrSub = jdbcTemplate.queryForObject(
                    "SELECT COUNT(DISTINCT o.user_id) FROM okr_objective o JOIN sys_user u ON o.user_id = u.id " +
                    "WHERE o.period_id = ? AND u.superior_id = ?",
                    Integer.class, periodId, userId);
            ts.setOkrSubmitted(okrSub != null ? okrSub : 0);
        }
        return ts;
    }

    private List<WorkspaceOverviewDto.RiskItem> buildRisks(Long periodId, Long userId) {
        List<WorkspaceOverviewDto.RiskItem> risks = new ArrayList<>();
        // Only show blocked KRs that belong to the user or their direct subordinates
        List<Map<String, Object>> blocked = jdbcTemplate.queryForList(
                "SELECT k.title, u.real_name FROM kr_key_result k " +
                "JOIN okr_objective o ON k.objective_id = o.id " +
                "JOIN sys_user u ON o.user_id = u.id " +
                "WHERE o.period_id = ? AND k.status = 'BLOCKED' " +
                "AND (o.user_id = ? OR u.superior_id = ?) LIMIT 5",
                periodId, userId, userId);
        for (Map<String, Object> row : blocked) {
            WorkspaceOverviewDto.RiskItem risk = new WorkspaceOverviewDto.RiskItem();
            risk.setType("BLOCKED_KR");
            risk.setLabel((String) row.get("title"));
            risk.setSeverity("WARNING");
            risk.setUserName((String) row.get("real_name"));
            risks.add(risk);
        }
        return risks;
    }

    private List<WorkspaceOverviewDto.DeadlineItem> buildDeadlines(AssessmentPeriod period) {
        List<WorkspaceOverviewDto.DeadlineItem> deadlines = new ArrayList<>();
        if (period.getEndDate() != null) {
            WorkspaceOverviewDto.DeadlineItem d = new WorkspaceOverviewDto.DeadlineItem();
            d.setLabel("周期结束");
            d.setDate(period.getEndDate().toString());
            long days = ChronoUnit.DAYS.between(LocalDate.now(), period.getEndDate());
            d.setType(days <= 7 ? "URGENT" : "NORMAL");
            deadlines.add(d);
        }
        return deadlines;
    }

    private List<WorkflowActionDto> buildAllowedActions(AssessmentPeriod period, Long userId) {
        List<WorkflowActionDto> actions = new ArrayList<>();
        actions.add(new WorkflowActionDto("VIEW_PERIOD", "查看周期详情", "/periods", period.getId(), null));
        actions.add(new WorkflowActionDto("VIEW_OKR", "查看 OKR", "/okr/my", period.getId(), null));
        actions.add(new WorkflowActionDto("VIEW_SCORES", "查看绩效", "/scores/my", period.getId(), null));
        return actions;
    }

    private WorkspaceOverviewDto emptyOverview() {
        WorkspaceOverviewDto dto = new WorkspaceOverviewDto();
        dto.setCurrentPhase("NO_PERIOD");
        dto.setMyTodos(Collections.emptyList());
        dto.setAvailablePeriods(Collections.emptyList());
        dto.setAllowedActions(Collections.emptyList());
        return dto;
    }
}
