package com.huimv.employment.service.worker;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huimv.employment.common.exception.BizException;
import com.huimv.employment.common.exception.ErrorCode;
import com.huimv.employment.service.enterprise.EnterpriseService;
import com.huimv.employment.service.worker.dto.ThirdPartyAvailableWorkerItem;
import com.huimv.employment.service.worker.dto.ThirdPartyWorkerGroupResponse;
import com.huimv.employment.service.worker.dto.ThirdPartyWorkerQueryItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * 第三方人力可用工人列表（Mock）：按工种精确匹配，并按工种分组返回。
 */
@Service
public class ThirdPartyWorkerService {

    private static final Logger log = LoggerFactory.getLogger(ThirdPartyWorkerService.class);
    private static final String MOCK_RESOURCE = "mock/available-workers.json";

    private final ObjectMapper objectMapper;
    private final EnterpriseService enterpriseService;

    private volatile List<MockWorkerRow> cachedRows;

    public ThirdPartyWorkerService(ObjectMapper objectMapper, EnterpriseService enterpriseService) {
        this.objectMapper = objectMapper;
        this.enterpriseService = enterpriseService;
    }

    /**
     * 按条件列表查询可用工人：每条条件以 {@code jobType} 精确匹配工种，
     * {@code workLocation} 可选（有值则地点包含匹配）；结果按工种分组。
     */
    public ThirdPartyWorkerGroupResponse listAvailable(Long userId, List<ThirdPartyWorkerQueryItem> queries) {
        enterpriseService.requireEnterpriseUser(userId);
        if (queries == null || queries.isEmpty()) {
            throw new BizException(ErrorCode.BAD_REQUEST, "查询条件不能为空，示例：[{\"jobType\":\"搬运工\",\"workLocation\":\"上海\"}]");
        }

        List<ThirdPartyWorkerQueryItem> normalized = new ArrayList<>();
        for (ThirdPartyWorkerQueryItem q : queries) {
            if (q == null || !StringUtils.hasText(q.getJobType())) {
                throw new BizException(ErrorCode.BAD_REQUEST, "jobType 不能为空");
            }
            ThirdPartyWorkerQueryItem item = new ThirdPartyWorkerQueryItem();
            item.setJobType(q.getJobType().trim());
            item.setWorkLocation(StringUtils.hasText(q.getWorkLocation()) ? q.getWorkLocation().trim() : null);
            normalized.add(item);
        }

        // 保持查询工种顺序；同一工人只出现一次
        Map<String, List<ThirdPartyAvailableWorkerItem>> grouped = new LinkedHashMap<>();
        for (ThirdPartyWorkerQueryItem q : normalized) {
            grouped.putIfAbsent(q.getJobType(), new ArrayList<>());
        }
        Set<Long> seenWorkerIds = new HashSet<>();

        for (MockWorkerRow row : loadRows()) {
            if (!StringUtils.hasText(row.confirmedWorkType)) {
                continue;
            }
            String jobType = row.confirmedWorkType.trim();
            for (ThirdPartyWorkerQueryItem q : normalized) {
                if (!jobType.equals(q.getJobType())) {
                    continue;
                }
                if (!matchLocation(row, q.getWorkLocation())) {
                    continue;
                }
                Long dedupeKey = row.workerId != null ? row.workerId : row.registrationId;
                if (dedupeKey != null && !seenWorkerIds.add(dedupeKey)) {
                    continue;
                }
                grouped.get(q.getJobType()).add(toWorkerItem(row));
                break;
            }
        }

        int total = 0;
        List<ThirdPartyWorkerGroupResponse.JobTypeGroup> groups = new ArrayList<>();
        for (Map.Entry<String, List<ThirdPartyAvailableWorkerItem>> e : grouped.entrySet()) {
            ThirdPartyWorkerGroupResponse.JobTypeGroup g = new ThirdPartyWorkerGroupResponse.JobTypeGroup();
            g.setJobType(e.getKey());
            g.setWorkers(e.getValue());
            g.setWorkerCount(e.getValue().size());
            total += e.getValue().size();
            groups.add(g);
        }

        ThirdPartyWorkerGroupResponse response = new ThirdPartyWorkerGroupResponse();
        response.setQueries(normalized);
        response.setTotalCount(total);
        response.setGroups(groups);
        response.setSource("mock");
        response.setMessage(total == 0
                ? "未匹配到可用工人（Mock）"
                : "已按工种精确匹配并分组返回可用工人（Mock）");
        return response;
    }

    private List<MockWorkerRow> loadRows() {
        List<MockWorkerRow> local = cachedRows;
        if (local != null) {
            return local;
        }
        synchronized (this) {
            if (cachedRows != null) {
                return cachedRows;
            }
            try (InputStream in = new ClassPathResource(MOCK_RESOURCE).getInputStream()) {
                MockRoot root = objectMapper.readValue(in, MockRoot.class);
                cachedRows = root != null && root.workers != null ? root.workers : new ArrayList<>();
                log.info("已加载第三方可用工人 Mock 数据 path={} count={}", MOCK_RESOURCE, cachedRows.size());
                return cachedRows;
            } catch (Exception ex) {
                log.error("加载第三方可用工人 Mock 失败 path={}", MOCK_RESOURCE, ex);
                throw new BizException(ErrorCode.INTERNAL_ERROR, "可用工人 Mock 数据加载失败");
            }
        }
    }

    private static boolean matchLocation(MockWorkerRow row, String location) {
        if (!StringUtils.hasText(location)) {
            return true;
        }
        if (!StringUtils.hasText(row.workLocation)) {
            return false;
        }
        return row.workLocation.trim().toLowerCase(Locale.ROOT)
                .contains(location.toLowerCase(Locale.ROOT));
    }

    private static ThirdPartyAvailableWorkerItem toWorkerItem(MockWorkerRow row) {
        ThirdPartyAvailableWorkerItem item = new ThirdPartyAvailableWorkerItem();
        item.setRegistrationId(row.registrationId);
        item.setWorkerId(row.workerId);
        item.setRealName(row.realName);
        item.setConfirmedWorkType(row.confirmedWorkType);
        item.setThirdPartySource(row.thirdPartySource != null ? row.thirdPartySource : 1);
        item.setMobile(row.mobile);
        item.setIdCardNo(row.idCardNo);
        item.setMobileMask(StringUtils.hasText(row.mobileMask) ? row.mobileMask : maskMobile(row.mobile));
        item.setRegStatus(row.regStatus);
        item.setStatusTag(row.statusTag);
        item.setStatusText(row.statusText);
        item.setFailReason(row.failReason);
        item.setSubmittedAt(row.submittedAt);
        return item;
    }

    private static String maskMobile(String mobile) {
        if (!StringUtils.hasText(mobile) || mobile.length() < 7) {
            return mobile;
        }
        return mobile.substring(0, 3) + "****" + mobile.substring(mobile.length() - 4);
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class MockRoot {
        public List<MockWorkerRow> workers;
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class MockWorkerRow {
        @JsonProperty("registration_id")
        public Long registrationId;
        @JsonProperty("worker_id")
        public Long workerId;
        @JsonProperty("real_name")
        public String realName;
        @JsonProperty("confirmed_work_type")
        public String confirmedWorkType;
        @JsonProperty("third_party_source")
        public Integer thirdPartySource;
        @JsonProperty("mobile")
        public String mobile;
        @JsonProperty("id_card_no")
        public String idCardNo;
        @JsonProperty("mobile_mask")
        public String mobileMask;
        @JsonProperty("reg_status")
        public String regStatus;
        @JsonProperty("status_tag")
        public String statusTag;
        @JsonProperty("status_text")
        public String statusText;
        @JsonProperty("fail_reason")
        public String failReason;
        @JsonProperty("submitted_at")
        public LocalDateTime submittedAt;
        /** 仅 Mock 筛选用，不回显到 workers 子对象 */
        @JsonProperty("work_location")
        public String workLocation;
    }
}
