package com.usky.sas.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.usky.common.core.bean.CommonPage;
import com.usky.sas.domain.SasFollowPerson;
import com.usky.sas.domain.SasPerson;
import com.usky.sas.domain.SasCredentialTypeCode;
import com.usky.sas.domain.SasPeopleTypeCode;
import com.usky.sas.domain.SasPersonTypeCode;
import com.usky.sas.mapper.SasFollowPersonMapper;
import com.usky.sas.mapper.SasPersonMapper;
import com.usky.sas.mapper.SasCredentialTypeCodeMapper;
import com.usky.sas.mapper.SasPeopleTypeCodeMapper;
import com.usky.sas.mapper.SasPersonTypeCodeMapper;
import com.usky.sas.mapper.SasSystemConfigMapper;
import com.usky.sas.mapper.SasVillageMapper;
import com.usky.sas.domain.SasVillage;
import com.usky.sas.domain.SasSystemConfig;
import com.usky.sas.service.SasPersonnelService;
import com.usky.sas.service.SasConfigService;
import com.usky.sas.service.dto.agbox.JsonRpcRequest;
import com.usky.sas.service.dto.agbox.PersonVo;
import com.usky.sas.service.dto.agbox.PersonBlackListVO;
import com.usky.sas.service.vo.PersonnelDetailResponse;
import com.usky.sas.service.vo.PersonnelListItem;
import com.usky.sas.service.vo.PersonnelPageRequest;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.IdcardUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SasPersonnelServiceImpl implements SasPersonnelService {

    /** 关注人员/黑名单 AG 路径 */
    private static final String AGBOX_PERSON_PATH = "/agbox/person";
    private static final String AGBOX_VILLAGE_PATH = "/agbox/village";
    /** getBlackList 请求中写死的 eventCode（关注类型） */
    private static final int FOLLOW_EVENT_CODE = 904;
    private static final int PERSON_PAGE_SIZE = 100;
    private static final int HTTP_TIMEOUT_MS = 90000;
    private static final int MAX_RETRIES = 5;
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private SasPersonMapper sasPersonMapper;

    @Autowired
    private SasConfigService sasConfigService;

    @Autowired
    private SasFollowPersonMapper sasFollowPersonMapper;

    @Autowired
    private SasCredentialTypeCodeMapper sasCredentialTypeCodeMapper;

    @Autowired
    private SasPeopleTypeCodeMapper sasPeopleTypeCodeMapper;

    @Autowired
    private SasVillageMapper sasVillageMapper;

    @Autowired
    private SasPersonTypeCodeMapper sasPersonTypeCodeMapper;

    @Autowired
    private SasSystemConfigMapper sasSystemConfigMapper;

    @Override
    public CommonPage<PersonnelListItem> whitelistPage(PersonnelPageRequest request) {
        // 目前按人员表简单分页，后续可根据白名单标识补充筛选条件
        return buildPersonPage(request);
    }

    @Override
    public int syncWhitelist() {
        // 预留与 agbox 同步实现
        return 0;
    }

    @Override
    public PersonnelDetailResponse whitelistDetail(String personCode) {
        return buildPersonDetail(personCode);
    }

    @Override
    public CommonPage<PersonnelListItem> blacklistPage(PersonnelPageRequest request) {
        // 目前按人员表简单分页，后续可根据黑名单标识补充筛选条件
        return buildPersonPage(request);
    }

    @Override
    public int syncBlacklist() {
        // 预留与 agbox 同步实现
        return 0;
    }

    @Override
    public PersonnelDetailResponse blacklistDetail(String personCode) {
        return buildPersonDetail(personCode);
    }

    @Override
    public CommonPage<PersonnelListItem> registeredPage(PersonnelPageRequest request) {
        com.usky.sas.domain.SasConfig config = sasConfigService.getConfig();
        if (config == null || config.getKeyds() == null || config.getHost() == null) {
            log.debug("在册人员分页：未配置 AG，走本地人员表分页");
            return buildPersonPage(request);
        }
        String villageCode = request.getVillageCode();
        if (villageCode == null || villageCode.isEmpty()) {
            villageCode = getVillageCodeForSync();
        }
        if (villageCode == null || villageCode.isEmpty()) {
            log.debug("在册人员分页：无地块编码，走本地人员表分页");
            return buildPersonPage(request);
        }
        int page = request.getCurrent() != null ? request.getCurrent() : 1;
        int pageSize = request.getSize() != null ? request.getSize() : 10;
        try {
            String baseUrl = buildAgboxBaseUrl(config.getHost(), config.getPort());
            String villageUrl = baseUrl + AGBOX_VILLAGE_PATH;
            Map<String, Object> params = new HashMap<>();
            params.put("page", page);
            params.put("pageSize", pageSize);
            params.put("villageCode", villageCode);
            JsonRpcRequest getPersonJson = new JsonRpcRequest("getPerson", params, null);
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("key", config.getKeyds());
            requestBody.put("json", JSONUtil.toJsonStr(getPersonJson));
            log.info("请求AG在册人员分页：page={}, pageSize={}, villageCode={}", page, pageSize, villageCode);

            String resultStr = postWithRetry(villageUrl, requestBody);
            PersonVo personVo = new ObjectMapper().readValue(resultStr, PersonVo.class);
            PersonVo.PersonResult result = personVo != null ? personVo.getResult() : null;
            List<PersonVo.PersonMsg> personList = (result != null && result.getPerson() != null) ? result.getPerson() : Collections.emptyList();

            SasSystemConfig systemConfig = sasSystemConfigMapper.selectOne(new LambdaQueryWrapper<SasSystemConfig>().last("limit 1"));
            boolean maskIdCard = systemConfig != null && Boolean.TRUE.equals(systemConfig.getMaskIdCardNo());

            List<PersonnelListItem> list = personList.stream()
                    .map(msg -> personMsgToListItem(msg, maskIdCard))
                    .collect(Collectors.toList());

            long total = (result != null && result.getCount() != null) ? result.getCount() : 0;
            return new CommonPage<>(list, total, (long) page, (long) pageSize);
        } catch (Exception e) {
            log.warn("在册人员分页请求 AG 失败，回退本地人员表：{}", e.getMessage());
            return buildPersonPage(request);
        }
    }

    private PersonnelListItem personMsgToListItem(PersonVo.PersonMsg msg, boolean maskIdCard) {
        PersonnelListItem item = new PersonnelListItem();
        item.setPersonCode(msg.getPersonCode());
        item.setName(msg.getName());
        item.setCredentialType(msg.getCredentialType());
        if (msg.getCredentialNo() != null) {
            if (maskIdCard && msg.getCredentialNo().length() > 8) {
                item.setCredentialNo(IdcardUtil.hide(msg.getCredentialNo(), 4, msg.getCredentialNo().length() - 4));
            } else {
                item.setCredentialNo(msg.getCredentialNo());
            }
        }
        item.setPeopleTypeCode(msg.getPersonTypeCode());
        if (msg.getFacePicUrl() != null && StrUtil.isNotBlank(msg.getFacePicUrl().getUrl()) && StrUtil.isNotBlank(msg.getFacePicUrl().getPath())) {
            item.setPicUrl(msg.getFacePicUrl().getUrl() + msg.getFacePicUrl().getPath());
        }
        if (msg.getPicId() != null && !msg.getPicId().isEmpty()) {
            item.setPicId(msg.getPicId());
        }
        if (msg.getUpdateTime() != null && !msg.getUpdateTime().isEmpty()) {
            try {
                item.setUpdateTime(LocalDateTime.parse(msg.getUpdateTime().replace(' ', 'T').substring(0, Math.min(19, msg.getUpdateTime().length())), DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            } catch (Exception ignored) {
                item.setUpdateTime(null);
            }
        }
        if (msg.getPersonEntranceTypeCode() != null) {
            SasPersonTypeCode pt = sasPersonTypeCodeMapper.selectById(msg.getPersonEntranceTypeCode());
            if (pt != null) {
                item.setPersonTypeName(pt.getName());
            }
        }
        if (msg.getPersonTypeCode() != null) {
            SasPeopleTypeCode pc = sasPeopleTypeCodeMapper.selectById(String.valueOf(msg.getPersonTypeCode()));
            if (pc != null) {
                item.setPeopleTypeName(pc.getName());
            }
        }
        if (msg.getCredentialType() != null) {
            SasCredentialTypeCode ct = sasCredentialTypeCodeMapper.selectById(msg.getCredentialType());
            if (ct != null) {
                item.setCredentialTypeName(ct.getName());
            }
        }
        return item;
    }

    @Override
    public int syncRegistered() {
        com.usky.sas.domain.SasConfig config = sasConfigService.getConfig();
        if (config == null || config.getKeyds() == null || config.getHost() == null) {
            log.warn("同步在册人员失败：未配置 AG 接口（key/host）");
            return 0;
        }
        String villageCode = getVillageCodeForSync();
        if (villageCode == null || villageCode.isEmpty()) {
            log.warn("同步在册人员失败：地块信息表中无可用地块（请先同步地块或设置默认地块）");
            return 0;
        }
        String baseUrl = buildAgboxBaseUrl(config.getHost(), config.getPort());
        String villageUrl = baseUrl + AGBOX_VILLAGE_PATH;
        String key = config.getKeyds();
        ObjectMapper mapper = new ObjectMapper();
        int totalSynced = 0;
        int page = 1;

        try {
            while (true) {
                Map<String, Object> params = new HashMap<>();
                params.put("page", page);
                params.put("pageSize", PERSON_PAGE_SIZE);
                params.put("villageCode", villageCode);
                JsonRpcRequest getPersonJson = new JsonRpcRequest("getPerson", params, null);
                Map<String, Object> requestBody = new HashMap<>();
                requestBody.put("key", key);
                requestBody.put("json", JSONUtil.toJsonStr(getPersonJson));
                log.info("请求AG在册人员，page={}：{}", page, JSONUtil.toJsonStr(getPersonJson));

                String resultStr = postWithRetry(villageUrl, requestBody);
                log.info("AG在册人员响应 page={}：{}", page, resultStr);

                PersonVo personVo = mapper.readValue(resultStr, PersonVo.class);
                PersonVo.PersonResult result = personVo != null ? personVo.getResult() : null;
                List<PersonVo.PersonMsg> personList = (result != null && result.getPerson() != null) ? result.getPerson() : Collections.emptyList();

                if (personList.isEmpty()) {
                    break;
                }

                for (PersonVo.PersonMsg msg : personList) {
                    if (msg.getPersonCode() == null || msg.getPersonCode().isEmpty()) {
                        continue;
                    }
                    try {
                        SasPerson entity = personMsgToSasPerson(msg);
                        SasPerson exist = sasPersonMapper.selectById(msg.getPersonCode());
                        LocalDateTime now = LocalDateTime.now();
                        if (exist != null) {
                            entity.setCreateTime(exist.getCreateTime());
                            entity.setUpdateTime(now);
                            sasPersonMapper.updateById(entity);
                        } else {
                            entity.setCreateTime(now);
                            entity.setUpdateTime(now);
                            sasPersonMapper.insert(entity);
                        }
                        totalSynced++;
                    } catch (Exception e) {
                        log.error("同步在册人员 {} 失败：{}", msg.getPersonCode(), e.getMessage(), e);
                    }
                }

                if (personList.size() < PERSON_PAGE_SIZE) {
                    break;
                }
                page++;
            }
        } catch (Exception e) {
            log.error("同步在册人员失败：{}", e.getMessage(), e);
        }
        log.info("在册人员同步完成，共同步 {} 条", totalSynced);
        return totalSynced;
    }

    private SasPerson personMsgToSasPerson(PersonVo.PersonMsg msg) {
        SasPerson entity = new SasPerson();
        entity.setPersonCode(msg.getPersonCode());
        entity.setName(msg.getName());
        entity.setCredentialType(msg.getCredentialType());
        entity.setCredentialNo(msg.getCredentialNo());
        entity.setPhone1(msg.getPhone1());
        entity.setPhone2(msg.getPhone2());
        entity.setPhone3(msg.getPhone3());
        entity.setPeopleTypeCode(msg.getPersonTypeCode());
        entity.setPersonEntranceTypeCode(msg.getPersonEntranceTypeCode());
        entity.setEntranceTypeCode(msg.getEntranceTypeCode());
        entity.setCompanyCode(msg.getCompanyCode());
        entity.setOrigin(msg.getOrigin());
        entity.setPlaceOfBirth(msg.getPlaceOfBirth());
        entity.setEducationCode(msg.getEducationCode());
        entity.setMaritalStatusCode(msg.getMaritalStatusCode());
        entity.setNationalityCode(msg.getNationalityCode());
        if (msg.getPicId() != null && !msg.getPicId().isEmpty()) {
            entity.setPicId(msg.getPicId());
        } else if (msg.getFacePicUrl() != null) {
            String url = msg.getFacePicUrl().getUrl();
            String path = msg.getFacePicUrl().getPath();
            if (url != null && path != null) {
                entity.setPicId(url + path);
            }
        }
        if (msg.getUpdateTime() != null && !msg.getUpdateTime().isEmpty()) {
            try {
                entity.setUpdateTime(LocalDateTime.parse(msg.getUpdateTime(), DATE_TIME_FORMATTER));
            } catch (Exception ignored) {
                entity.setUpdateTime(LocalDateTime.now());
            }
        }
        return entity;
    }

    private String buildAgboxBaseUrl(String host, String port) {
        if (host == null || host.isEmpty()) {
            return "";
        }
        if (host.startsWith("http://") || host.startsWith("https://")) {
            return host;
        }
        return "http://" + host;
    }

    /**
     * 从地块信息表动态获取用于同步的 villageCode：优先取默认地块（is_default=true），若无则取第一条。
     */
    private String getVillageCodeForSync() {
        LambdaQueryWrapper<SasVillage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SasVillage::getIsDefault, true).last("limit 1");
        List<SasVillage> list = sasVillageMapper.selectList(wrapper);
        if (list != null && !list.isEmpty()) {
            return list.get(0).getVillageCode();
        }
        wrapper = new LambdaQueryWrapper<>();
        wrapper.last("limit 1");
        list = sasVillageMapper.selectList(wrapper);
        return (list != null && !list.isEmpty()) ? list.get(0).getVillageCode() : null;
    }

    private String postWithRetry(String url, Map<String, Object> requestBody) {
        Exception lastEx = null;
        for (int i = 0; i < MAX_RETRIES; i++) {
            try {
                return HttpRequest.post(url)
                        .form(requestBody)
                        .timeout(HTTP_TIMEOUT_MS)
                        .execute()
                        .body();
            } catch (Exception e) {
                lastEx = e;
                if (i < MAX_RETRIES - 1) {
                    long delayMs = 2000L * (i + 1);
                    log.warn("AG 接口请求失败，第 {} 次重试（{}ms 后）：{}", i + 1, delayMs, e.getMessage());
                    try {
                        Thread.sleep(delayMs);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("重试被中断", ie);
                    }
                }
            }
        }
        String causeMsg = lastEx != null ? lastEx.getMessage() : "";
        throw new RuntimeException("AG 接口请求失败，重试 " + MAX_RETRIES + " 次后仍失败：" + causeMsg, lastEx);
    }

    @Override
    public PersonnelDetailResponse registeredDetail(String personCode) {
        return buildPersonDetail(personCode);
    }

    @Override
    public CommonPage<PersonnelListItem> followPage(PersonnelPageRequest request) {
        IPage<SasFollowPerson> page = new Page<>(request.getCurrent(), request.getSize());
        LambdaQueryWrapper<SasFollowPerson> wrapper = new LambdaQueryWrapper<>();
        if (request.getName() != null && !request.getName().isEmpty()) {
            wrapper.like(SasFollowPerson::getName, request.getName());
        }
        if (request.getPersonCode() != null && !request.getPersonCode().isEmpty()) {
            wrapper.eq(SasFollowPerson::getPersonCode, request.getPersonCode());
        }
        page = sasFollowPersonMapper.selectPage(page, wrapper);
        List<PersonnelListItem> list = page.getRecords().stream()
                .map(this::fromFollowPerson)
                .collect(Collectors.toList());
        return new CommonPage<>(list, page.getTotal(), page.getCurrent(), page.getSize());
    }

    @Override
    public int syncFollow() {
        com.usky.sas.domain.SasConfig config = sasConfigService.getConfig();
        if (config == null || config.getKeyds() == null || config.getHost() == null) {
            log.warn("同步关注人员失败：未配置 AG 接口（key/host）");
            return 0;
        }
        String baseUrl = buildAgboxBaseUrl(config.getHost(), config.getPort());
        String personUrl = baseUrl + AGBOX_PERSON_PATH;
        String key = config.getKeyds();
        ObjectMapper mapper = new ObjectMapper();
        int totalSynced = 0;
        int page = 1;

        try {
            while (true) {
                Map<String, Object> params = new HashMap<>();
                params.put("page", page);
                params.put("pageSize", PERSON_PAGE_SIZE);
                params.put("eventCode", FOLLOW_EVENT_CODE);
                JsonRpcRequest getBlackListJson = new JsonRpcRequest("getBlackList", params, null);
                Map<String, Object> requestBody = new HashMap<>();
                requestBody.put("key", key);
                requestBody.put("json", JSONUtil.toJsonStr(getBlackListJson));
                log.info("请求AG关注人员(getBlackList)，page={}：{}", page, JSONUtil.toJsonStr(getBlackListJson));

                String resultStr = postWithRetry(personUrl, requestBody);
                log.info("AG关注人员响应 page={}：{}", page, resultStr);

                PersonBlackListVO vo = mapper.readValue(resultStr, PersonBlackListVO.class);
                PersonBlackListVO.PersonBlackResult result = vo != null ? vo.getResult() : null;
                List<PersonBlackListVO.PersonBlackList> blackList = (result != null && result.getBlackList() != null) ? result.getBlackList() : Collections.emptyList();

                if (blackList.isEmpty()) {
                    break;
                }

                int indexInPage = 0;
                for (PersonBlackListVO.PersonBlackList item : blackList) {
                    String personCode = item.getPersonCode();
                    if (personCode == null || personCode.isEmpty()) {
                        personCode = "follow_" + FOLLOW_EVENT_CODE + "_" + page + "_" + indexInPage;
                    }
                    indexInPage++;
                    try {
                        SasFollowPerson entity = blackListItemToFollowPerson(personCode, item);
                        SasFollowPerson exist = sasFollowPersonMapper.selectById(entity.getPersonCode());
                        LocalDateTime now = LocalDateTime.now();
                        if (exist != null) {
                            entity.setCreateTime(exist.getCreateTime());
                            entity.setUpdateTime(now);
                            sasFollowPersonMapper.updateById(entity);
                        } else {
                            entity.setCreateTime(now);
                            entity.setUpdateTime(now);
                            sasFollowPersonMapper.insert(entity);
                        }
                        totalSynced++;
                    } catch (Exception e) {
                        log.error("同步关注人员 {} 失败：{}", personCode, e.getMessage(), e);
                    }
                }

                if (blackList.size() < PERSON_PAGE_SIZE) {
                    break;
                }
                page++;
            }
        } catch (Exception e) {
            log.error("同步关注人员失败：{}", e.getMessage(), e);
        }
        log.info("关注人员同步完成，共同步 {} 条", totalSynced);
        return totalSynced;
    }

    private SasFollowPerson blackListItemToFollowPerson(String personCode, PersonBlackListVO.PersonBlackList item) {
        SasFollowPerson entity = new SasFollowPerson();
        entity.setPersonCode(personCode);
        entity.setName(item.getNote() != null ? item.getNote() : item.getPersonCode());
        entity.setFollowPeopleType(item.getEventCode());
        if (item.getPicUrl() != null) {
            String url = item.getPicUrl().getUrl();
            String path = item.getPicUrl().getPath();
            if (url != null && path != null) {
                entity.setPicId(url + path);
            } else if (path != null) {
                entity.setPicId(path);
            } else if (url != null) {
                entity.setPicId(url);
            }
        }
        return entity;
    }

    @Override
    public PersonnelDetailResponse followDetail(String personCode) {
        SasFollowPerson followPerson = sasFollowPersonMapper.selectById(personCode);
        if (followPerson == null) {
            return null;
        }
        PersonnelDetailResponse detail = new PersonnelDetailResponse();
        detail.setPersonCode(followPerson.getPersonCode());
        detail.setName(followPerson.getName());
        detail.setPicId(followPerson.getPicId());
        detail.setUpdateTime(followPerson.getUpdateTime());
        return detail;
    }

    private CommonPage<PersonnelListItem> buildPersonPage(PersonnelPageRequest request) {
        IPage<SasPerson> page = new Page<>(request.getCurrent(), request.getSize());
        LambdaQueryWrapper<SasPerson> wrapper = new LambdaQueryWrapper<>();
        if (request.getName() != null && !request.getName().isEmpty()) {
            wrapper.like(SasPerson::getName, request.getName());
        }
        if (request.getPersonCode() != null && !request.getPersonCode().isEmpty()) {
            wrapper.eq(SasPerson::getPersonCode, request.getPersonCode());
        }
        wrapper.orderByDesc(SasPerson::getUpdateTime);
        page = sasPersonMapper.selectPage(page, wrapper);
        List<SasPerson> records = page.getRecords();
        if (records == null) {
            records = Collections.emptyList();
        }
        List<PersonnelListItem> list = records.stream()
                .map(this::fromPerson)
                .collect(Collectors.toList());
        return new CommonPage<>(list, page.getTotal(), page.getCurrent(), page.getSize());
    }

    private PersonnelDetailResponse buildPersonDetail(String personCode) {
        SasPerson person = sasPersonMapper.selectById(personCode);
        if (person == null) {
            return null;
        }
        PersonnelDetailResponse detail = new PersonnelDetailResponse();
        detail.setPersonCode(person.getPersonCode());
        detail.setName(person.getName());
        detail.setCredentialType(person.getCredentialType());
        detail.setCredentialNo(person.getCredentialNo());
        // 证件类型名称：从 sas_credential_type_code 查询
        if (person.getCredentialType() != null) {
            SasCredentialTypeCode ct = sasCredentialTypeCodeMapper.selectById(person.getCredentialType());
            detail.setCredentialTypeName(ct != null ? ct.getName() : null);
        }
        detail.setPicId(person.getPicId());
        detail.setPhone1(person.getPhone1());
        detail.setPhone2(person.getPhone2());
        detail.setPhone3(person.getPhone3());
        detail.setRemark(null); // sas_person 表无备注字段，可后续扩展
        detail.setPeopleTypeCode(person.getPeopleTypeCode());
        // 人员类型名称：从 sas_people_type_code 查询（code 为字符串）
        if (person.getPeopleTypeCode() != null) {
            SasPeopleTypeCode pt = sasPeopleTypeCodeMapper.selectById(String.valueOf(person.getPeopleTypeCode()));
            detail.setPeopleTypeName(pt != null ? pt.getName() : null);
        }
        detail.setEntranceTypeCode(person.getEntranceTypeCode());
        detail.setEntranceTypeName(null); // 暂无出入类型编码表，可后续扩展
        detail.setEducationCode(person.getEducationCode());
        detail.setMaritalStatusCode(person.getMaritalStatusCode());
        detail.setNationalityCode(person.getNationalityCode());
        detail.setOrigin(person.getOrigin());
        detail.setPlaceOfBirth(person.getPlaceOfBirth());
        detail.setUpdateTime(person.getUpdateTime());
        return detail;
    }

    private PersonnelListItem fromPerson(SasPerson p) {
        PersonnelListItem item = new PersonnelListItem();
        item.setPersonCode(p.getPersonCode());
        item.setName(p.getName());
        item.setCredentialType(p.getCredentialType());
        item.setCredentialNo(p.getCredentialNo());
        item.setPeopleTypeCode(p.getPeopleTypeCode());
        item.setPicId(p.getPicId());
        item.setUpdateTime(p.getUpdateTime());
        return item;
    }

    private PersonnelListItem fromFollowPerson(SasFollowPerson p) {
        PersonnelListItem item = new PersonnelListItem();
        item.setPersonCode(p.getPersonCode());
        item.setName(p.getName());
        item.setFollowPeopleType(p.getFollowPeopleType());
        item.setPicId(p.getPicId());
        item.setUpdateTime(p.getUpdateTime());
        return item;
    }
}

