package jnpf.attendance.schedule;

import jnpf.model.attendance.vo.WorkstationGroupUserVo;
import jnpf.model.attendance.vo.WorkstationWithUsersVo;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 工作站维度汇总的「岗位 → 可排人员」专岗/通岗桶，供第九～十步候选过滤与专岗优先排序。
 * <p>
 * 由 {@link #fromWorkstations(List)} 从 {@link WorkstationWithUsersVo} 列表构建；
 * {@link ShiftPlanFinalStaffAssigner#assign} 入口第一步即创建本对象。
 * <p>
 * <b>岗位对齐</b>：{@link WorkstationWithUsersVo#getPositionId()} 须与 {@link ShiftPlanPostNeed#getPostId()} 一致。
 * <p>
 * <b>人员分类</b>：{@link WorkstationGroupUserVo#getIsExtra()} == false → 专岗；
 * true → 通岗（可跨岗支援，在 {@link ShiftPlanFinalStaffAssigner#orderedCandidates} 中排在专岗之后）。
 */
public final class WorkstationPostStaffBuckets {

    private final Map<String, Set<String>> specialistIdsByPost;
    private final Map<String, Set<String>> generalIdsByPost;

    public WorkstationPostStaffBuckets(
            Map<String, Set<String>> specialistIdsByPost, Map<String, Set<String>> generalIdsByPost) {
        this.specialistIdsByPost = unmodifiableCopy(specialistIdsByPost);
        this.generalIdsByPost = unmodifiableCopy(generalIdsByPost);
    }

    private static Map<String, Set<String>> unmodifiableCopy(Map<String, Set<String>> in) {
        Map<String, Set<String>> m = new LinkedHashMap<>();
        if (in != null) {
            for (Map.Entry<String, Set<String>> e : in.entrySet()) {
                if (e.getKey() == null || e.getValue() == null) {
                    continue;
                }
                m.put(e.getKey(), Collections.unmodifiableSet(new LinkedHashSet<>(e.getValue())));
            }
        }
        return Collections.unmodifiableMap(m);
    }

    /**
     * 遍历工作站列表，按岗位 ID 汇总专岗/通岗 userId 集合。
     * <p>
     * 同一 userId 出现在多工作站同岗位时，Set 自动去重。
     */
    public static WorkstationPostStaffBuckets fromWorkstations(List<WorkstationWithUsersVo> workstations) {
        Map<String, Set<String>> spec = new LinkedHashMap<>();
        Map<String, Set<String>> gen = new LinkedHashMap<>();
        if (workstations == null) {
            return new WorkstationPostStaffBuckets(spec, gen);
        }
        for (WorkstationWithUsersVo w : workstations) {
            if (w == null || w.getPositionId() == null || w.getPositionId().trim().isEmpty()) {
                continue;
            }
            String postId = w.getPositionId().trim();
            List<WorkstationGroupUserVo> users = w.getUserList();
            if (users == null) {
                continue;
            }
            for (WorkstationGroupUserVo u : users) {
                if (u == null || u.getUserId() == null || u.getUserId().trim().isEmpty()) {
                    continue;
                }
                String uid = u.getUserId().trim();
                if (Boolean.TRUE.equals(u.getIsExtra())) {
                    gen.computeIfAbsent(postId, k -> new LinkedHashSet<>()).add(uid);
                } else {
                    spec.computeIfAbsent(postId, k -> new LinkedHashSet<>()).add(uid);
                }
            }
        }
        return new WorkstationPostStaffBuckets(spec, gen);
    }

    /** 该岗位绑定的专岗员工 ID（无序 Set）。 */
    public Set<String> getSpecialistIds(String postId) {
        if (postId == null) {
            return Collections.emptySet();
        }
        Set<String> s = specialistIdsByPost.get(postId);
        return s == null ? Collections.emptySet() : s;
    }

    /** 该岗位绑定的通岗员工 ID（无序 Set）。 */
    public Set<String> getGeneralIds(String postId) {
        if (postId == null) {
            return Collections.emptySet();
        }
        Set<String> s = generalIdsByPost.get(postId);
        return s == null ? Collections.emptySet() : s;
    }

    /**
     * 该岗位是否配置了至少一名工作站人员（专岗或通岗）。
     * <p>
     * true 时与上游候选人求交；交集为空则无法从该岗位工作站选人（不再退化为工作站全集）。
     */
    public boolean hasWorkstationBinding(String postId) {
        return !getSpecialistIds(postId).isEmpty() || !getGeneralIds(postId).isEmpty();
    }

    public Map<String, Set<String>> getSpecialistIdsByPost() {
        return specialistIdsByPost;
    }

    public Map<String, Set<String>> getGeneralIdsByPost() {
        return generalIdsByPost;
    }
}
