package com.zcloud.personnel.positioning.command.query;

import com.zcloud.personnel.positioning.dto.clientobject.BiCompanyOnlinePersonCO;
import com.zcloud.personnel.positioning.persistence.dataobject.BiPersonPositionUserDO;
import com.zcloud.personnel.positioning.persistence.repository.UserRepository;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 可视化大屏第三方人员定位统一入口。
 *
 * @Author Codex
 * @Date 2026-07-27
 */
@Component
@RequiredArgsConstructor
public class BiPersonLocationProvider {
    private static final Logger LOGGER = LoggerFactory.getLogger(BiPersonLocationProvider.class);

    private final UserRepository userRepository;

    public List<BiCompanyOnlinePersonCO> listCompanyOnlinePersons(String corpinfoId,
                                                                  String corpinfoName,
                                                                  String corpCode) {
        if (!StringUtils.hasText(corpinfoId)) {
            return Collections.emptyList();
        }
        LOGGER.info("开始查询可视化大屏第三方人员定位，corpinfoId={}", corpinfoId);
        List<ThirdPartyPersonLocation> locations = loadThirdPartyPersonLocations(corpinfoId, corpinfoName, corpCode);
        if (locations.isEmpty()) {
            LOGGER.info("可视化大屏第三方人员定位为空，corpinfoId={}", corpinfoId);
            return Collections.emptyList();
        }
        Map<String, BiPersonPositionUserDO> userMap = buildUserMap(corpinfoId);
        List<BiCompanyOnlinePersonCO> result = new ArrayList<>(locations.size());
        for (ThirdPartyPersonLocation location : locations) {
            result.add(toOnlinePerson(corpinfoId, corpinfoName, location, userMap));
        }
        LOGGER.info("可视化大屏第三方人员定位转换完成，corpinfoId={}，定位人数={}", corpinfoId, result.size());
        return result;
    }

    private List<ThirdPartyPersonLocation> loadThirdPartyPersonLocations(String corpinfoId,
                                                                         String corpinfoName,
                                                                         String corpCode) {
        LOGGER.info("TODO 待接入第三方人员定位接口，corpinfoId={}，corpinfoName={}，corpCode={}",
                corpinfoId, corpinfoName, corpCode);
        // TODO 后续只在这里接入第三方接口：根据企业id获取在线人员、经纬度、定位时间、人员唯一标识。
        return Collections.emptyList();
    }

    private Map<String, BiPersonPositionUserDO> buildUserMap(String corpinfoId) {
        List<BiPersonPositionUserDO> users = userRepository.listBiPersonPositionUsers(corpinfoId);
        Map<String, BiPersonPositionUserDO> result = new LinkedHashMap<>();
        for (BiPersonPositionUserDO user : users) {
            putUser(result, user.getUserId() == null ? null : String.valueOf(user.getUserId()), user);
            putUser(result, user.getUsername(), user);
            putUser(result, user.getMobileNo(), user);
            putUser(result, user.getIdCardNo(), user);
        }
        return result;
    }

    private void putUser(Map<String, BiPersonPositionUserDO> userMap,
                         String key,
                         BiPersonPositionUserDO user) {
        if (StringUtils.hasText(key)) {
            userMap.putIfAbsent(key.trim(), user);
        }
    }

    private BiCompanyOnlinePersonCO toOnlinePerson(String corpinfoId,
                                                   String corpinfoName,
                                                   ThirdPartyPersonLocation location,
                                                   Map<String, BiPersonPositionUserDO> userMap) {
        BiPersonPositionUserDO user = findUser(location, userMap);
        BiCompanyOnlinePersonCO co = new BiCompanyOnlinePersonCO();
        co.setUserId(user == null ? null : user.getUserId());
        co.setStaffName(firstText(user == null ? null : user.getPersonName(), location.getPersonName()));
        co.setStaffNo(firstText(location.getStaffNo(), location.getUsername()));
        co.setMobileNo(firstText(user == null ? null : user.getMobileNo(), location.getMobileNo()));
        co.setCorpinfoId(corpinfoId);
        co.setCorpinfoName(firstText(corpinfoName, user == null ? null : user.getCorpinfoName()));
        co.setInternalEmployee(user != null);
        co.setPersonType(user == null ? "TEMP" : "INTERNAL");
        co.setTerminalNo(location.getTerminalNo());
        co.setCurrentLocation(location.getLocationName());
        co.setLastLocationTime(location.getLastLocationTime());
        co.setLon(location.getLon());
        co.setLat(location.getLat());
        co.setStaffRawJson(location.getPersonRawJson());
        co.setLocationRawJson(location.getLocationRawJson());
        return co;
    }

    private BiPersonPositionUserDO findUser(ThirdPartyPersonLocation location,
                                            Map<String, BiPersonPositionUserDO> userMap) {
        BiPersonPositionUserDO user = userMap.get(location.getUserId() == null
                ? null : String.valueOf(location.getUserId()));
        if (user == null) {
            user = userMap.get(location.getUsername());
        }
        if (user == null) {
            user = userMap.get(location.getMobileNo());
        }
        if (user == null) {
            user = userMap.get(location.getIdCardNo());
        }
        return user;
    }

    private String firstText(String... values) {
        if (values == null) {
            return null;
        }
        for (String value : values) {
            if (StringUtils.hasText(value)) {
                return value;
            }
        }
        return null;
    }

    @Data
    private static class ThirdPartyPersonLocation {
        private Long userId;
        private String username;
        private String personName;
        private String staffNo;
        private String mobileNo;
        private String idCardNo;
        private String terminalNo;
        private String locationName;
        private Long lastLocationTime;
        private BigDecimal lon;
        private BigDecimal lat;
        private String personRawJson;
        private String locationRawJson;
    }
}
