package jnpf.certificate.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageInfo;
import jnpf.authority.utils.PermissionsApplicableEnums;
import jnpf.authority.utils.PermissionsApplicableObject;
import jnpf.authority.utils.PermissionsUtils;
import jnpf.certificate.helper.OrganizationHelper;
import jnpf.certificate.mapper.CertificateAppRiskMapper;
import jnpf.certificate.service.CertificateAppRiskService;
import jnpf.model.certificate.req.app.CertificateAppEmployeeRiskQueryReq;
import jnpf.model.certificate.req.app.CertificateAppRiskChartReq;
import jnpf.model.certificate.req.app.CertificateAppStoreRiskQueryReq;
import jnpf.model.certificate.vo.app.CertificateAppEmployeeRiskVO;
import jnpf.model.certificate.vo.app.CertificateAppRiskChartVO;
import jnpf.model.certificate.vo.app.CertificateAppRiskReminderCountVO;
import jnpf.model.certificate.vo.app.CertificateAppStatusCountVO;
import jnpf.model.certificate.vo.app.CertificateAppStoreRiskItemVO;
import jnpf.model.certificate.vo.app.CertificateAppStoreRiskVO;
import jnpf.model.warningnotice.enums.CertificateTypeEnum;
import jnpf.permission.eum.v2.FtbStoreTagEnum;
import jnpf.permission.vo.v2.organzie.OrganizeBaseInfoVO;
import jnpf.permission.vo.v2.organzie.OrganizeGeneralDetailVO;
import jnpf.permission.vo.v2.position.PositionBaseInfoVO;
import jnpf.permission.vo.v2.user.UserBaseRelationSimpleVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.storecertificatephoto.helper.StoreCertificatePhotoHelper;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * App 端证照风险服务实现。
 */
@Service
public class CertificateAppRiskServiceImpl implements CertificateAppRiskService {

    private static final int STATUS_MISSING = 1;
    private static final int STATUS_EXPIRED = 2;
    private static final int STATUS_NEAR_EXPIRE = 3;
    private static final int STATUS_NORMAL = 4;

    /**
     * 证照风险查询 Mapper。
     */
    @Autowired
    private CertificateAppRiskMapper certificateAppRiskMapper;

    /**
     * 数据权限工具。
     */
    @Autowired
    private PermissionsUtils permissionsUtils;
    @Autowired
    private OrganizationHelper organizationHelper;
    @Autowired
    private StoreCertificatePhotoHelper storeCertificatePhotoHelper;


    /**
     * 查询证照风险图表统计。
     * 健康证按用户数据权限统计，非健康证按组织数据权限统计。
     */
    @Override
    public CertificateAppRiskChartVO queryChart(CertificateAppRiskChartReq req) {
        CertificateAppRiskChartReq queryReq = req == null ? new CertificateAppRiskChartReq() : req;
        queryReq.setOrgId(StrUtil.trim(queryReq.getOrgId()));
        queryReq.setCertificateType(StrUtil.blankToDefault(
                StrUtil.trim(queryReq.getCertificateType()),
                CertificateTypeEnum.HEALTH_CERTIFICATE.getType()
        ));

        String orgId = queryReq.getOrgId();
        boolean healthCertificateQuery = isHealthCertificate(queryReq.getCertificateType());
        buildQueryUserIds(queryReq,healthCertificateQuery);
        //如果查询组织id，但是没有查询到该组织的用户id列表，则返回空
        if(healthCertificateQuery && StringUtil.isNotBlank(orgId) && CollectionUtil.isEmpty(queryReq.getUserIds())){
            return buildChart(null);
        }
        List<CertificateAppStatusCountVO> statusCountList;
        if (healthCertificateQuery) {
            statusCountList = certificateAppRiskMapper.queryHealthRiskStatusCount(queryReq);
        } else {
            statusCountList = certificateAppRiskMapper.queryStoreRiskStatusCount(queryReq);
        }
        return buildChart(statusCountList);
    }

    private void buildQueryUserIds(CertificateAppRiskChartReq queryReq,boolean healthCertificateQuery) {
        if(!healthCertificateQuery){
            return;
        }
        String queryReqOrgId = queryReq.getOrgId();
        if(StringUtil.isBlank(queryReqOrgId)){
            return;
        }
        List<String> userIdsByOrgId = organizationHelper.getUserIdsByOrgId(queryReqOrgId);
        queryReq.setUserIds(userIdsByOrgId);
    }

    /**
     * 分页查询员工证照风险数据。
     */
    @Override
    public PageInfo<CertificateAppEmployeeRiskVO> queryEmployeePage(CertificateAppEmployeeRiskQueryReq req) {
        CertificateAppEmployeeRiskQueryReq queryReq = req == null ? new CertificateAppEmployeeRiskQueryReq() : req;
        queryReq.setOrgId(StrUtil.trim(queryReq.getOrgId()));
        long current = queryReq.getCurrentPage() == null || queryReq.getCurrentPage() <= 0 ? 1L : queryReq.getCurrentPage();
        long pageSize = queryReq.getPageSize() == null || queryReq.getPageSize() <= 0 ? 10L : queryReq.getPageSize();
        String orgId = queryReq.getOrgId();
        Collection<String> queryUserIds;
        Map<String, UserBaseRelationSimpleVO> relationMap;
        if (StringUtil.isNotBlank(orgId)) {
            relationMap = organizationHelper.getUserBaseRelationMapByOrgId(orgId);
            queryUserIds = relationMap.keySet();
        } else {
            relationMap = Collections.emptyMap();
            queryUserIds = null;
        }
        if (StringUtil.isNotBlank(orgId) && CollectionUtil.isEmpty(queryUserIds)) {
            return buildEmptyEmployeePage(current, pageSize);
        }

        Page<CertificateAppEmployeeRiskVO> page = new Page<>(current, pageSize);
        Page<CertificateAppEmployeeRiskVO> queryPage = certificateAppRiskMapper.queryEmployeeRiskPageByUserIds(page, queryUserIds);
        List<CertificateAppEmployeeRiskVO> records = queryPage.getRecords() == null ? new ArrayList<>() : queryPage.getRecords();
        if (CollectionUtil.isEmpty(records)) {
            return buildEmptyEmployeePage(current, pageSize);
        }

        Set<String> pageUserIds = records.stream()
                .map(CertificateAppEmployeeRiskVO::getUserId)
                .filter(StringUtil::isNotBlank)
                .collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(pageUserIds)) {
            return buildEmptyEmployeePage(current, pageSize);
        }
        if (StringUtil.isBlank(orgId)) {
            relationMap = organizationHelper.getUserBaseRelationMapByUserIds(pageUserIds);
        }

        for (CertificateAppEmployeeRiskVO item : records){
            UserBaseRelationSimpleVO relation = relationMap.get(item.getUserId());
            if(Objects.isNull(relation)){
                continue;
            }
            item.setWorkerName(StrUtil.blankToDefault(StrUtil.trim(relation.getUserName()), "-"));
            item.setPhone(StrUtil.blankToDefault(StrUtil.trim(relation.getMobilePhone()), "-"));
            item.setOrgId(relation.getOrganizeId());
            item.setPositionId(relation.getPositionId());
            item.setOrgName(relation.getOrganizeName());
            item.setPositionName(relation.getPositionName());
            item.setPhone(relation.getMobilePhone());
        }

        PageInfo<CertificateAppEmployeeRiskVO> pageInfo = new PageInfo<>();
        pageInfo.setList(records);
        pageInfo.setPageNum((int) queryPage.getCurrent());
        pageInfo.setPageSize((int) queryPage.getSize());
        pageInfo.setTotal(queryPage.getTotal());
        return pageInfo;
    }

    /**
     * 分页查询门店证照风险数据。
     */
    @Override
    public PageInfo<CertificateAppStoreRiskVO> queryStorePage(CertificateAppStoreRiskQueryReq req) {
        CertificateAppStoreRiskQueryReq queryReq = req == null ? new CertificateAppStoreRiskQueryReq() : req;
        queryReq.setOrgId(StrUtil.trim(queryReq.getOrgId()));
        queryReq.setCertificateType(StrUtil.trim(queryReq.getCertificateType()));
        long current = queryReq.getCurrentPage() == null || queryReq.getCurrentPage() <= 0 ? 1L : queryReq.getCurrentPage();
        long pageSize = queryReq.getPageSize() == null || queryReq.getPageSize() <= 0 ? 10L : queryReq.getPageSize();

        PageInfo<CertificateAppStoreRiskVO> emptyPage = buildEmptyStorePage(current, pageSize);

        Page<CertificateAppStoreRiskVO> page = new Page<>(current, pageSize);
        Page<CertificateAppStoreRiskVO> queryPage = certificateAppRiskMapper.queryStoreRiskPage(page, queryReq);

        List<CertificateAppStoreRiskVO> records = queryPage.getRecords() == null ? Collections.emptyList() : queryPage.getRecords();
        if (CollectionUtil.isEmpty(records)) {
            return emptyPage;
        }

        Set<String> orgIds = new HashSet<>();
        records.forEach(vo -> {
            orgIds.add(vo.getSubjectId());
        });
        List<CertificateAppStoreRiskItemVO> detailList = certificateAppRiskMapper.queryStoreRiskDetailList(orgIds);

        Set<String> templateIds = detailList.stream()
                .map(CertificateAppStoreRiskItemVO::getTemplateId)
                .filter(StringUtil::isNotBlank)
                .collect(Collectors.toSet());
        Map<String,String> templateIdAndNames = null;
        if(CollUtil.isNotEmpty(templateIds)){
            templateIdAndNames = storeCertificatePhotoHelper.buildStoreCertificateIdAndNames(templateIds,1);
        }else {
            templateIdAndNames = new HashMap<>();
        }
        Map<String, String> finalTemplateIdAndNames = templateIdAndNames;
        Map<String, List<CertificateAppStoreRiskItemVO>> detailMap = CollectionUtil.emptyIfNull(detailList).stream()
                .peek(item -> item.setCertificateTypeName(resolveCertificateTypeName(item.getCertificateType(),item.getTemplateId(), finalTemplateIdAndNames)))
                .filter(item -> StringUtil.isNotBlank(item.getCertificateTypeName()))//过滤掉被禁用的证照
                .collect(Collectors.groupingBy(CertificateAppStoreRiskItemVO::getSubjectId, LinkedHashMap::new, Collectors.toList()));
        for (CertificateAppStoreRiskVO record : records) {
            List<CertificateAppStoreRiskItemVO> certificateList = detailMap.getOrDefault(record.getSubjectId(), Collections.emptyList());
            record.setCertificateList(certificateList);
        }
        Map<String, OrganizeBaseInfoVO> organizeBaseInfoVOMap = organizationHelper.buildBaseOrganizeVO(orgIds,UserProvider.getUser().getTenantId());

        fillStoreRiskItem(records,organizeBaseInfoVOMap);

        PageInfo<CertificateAppStoreRiskVO> pageInfo = new PageInfo<>();
        pageInfo.setList(records);
        pageInfo.setPageNum((int) queryPage.getCurrent());
        pageInfo.setPageSize((int) queryPage.getSize());
        pageInfo.setTotal(queryPage.getTotal());
        return pageInfo;
    }

    /**
     * 查询有风险的员工、组织、总数量
     */
    @Override
    public CertificateAppRiskReminderCountVO queryRiskReminderCount(String orgId) {

        List<String> orgIds = new ArrayList<>(1);
        Map<String,List<String>> userIdsByOrgId = null;
        if(StringUtil.isNotBlank(orgId)){
            userIdsByOrgId = organizationHelper.buildUserIdsByOrgIds(List.of(orgId),true,"");
            orgIds.add(orgId);
        }else{
            userIdsByOrgId = organizationHelper.buildUserIdsByOrgIds(null,true,"");
        }

        Set<String> userIds = userIdsByOrgId.values()
                .stream()
                .flatMap(Collection::stream)
                .collect(Collectors.toSet());
        long employeeCount = 0L;
        if(!CollUtil.isEmpty(userIds)){
            employeeCount = certificateAppRiskMapper.queryEmployeeRiskTotalCount(userIds);
        }

        Long organizationCount = certificateAppRiskMapper.queryOrganizationRiskTotalCount(orgIds);
        if(Objects.isNull(organizationCount)){
            organizationCount = 0L;
        }

        CertificateAppRiskReminderCountVO vo = new CertificateAppRiskReminderCountVO();
        vo.setEmployeeCount(employeeCount);
        vo.setOrganizationCount(organizationCount);
        vo.setTotalCount(employeeCount + organizationCount);
        return vo;
    }

    /**
     * 解析员工数据权限范围。
     * 通过 allDataPermission 标识是否全量权限，userIds 为受限时可访问用户。
     */
    private PermissionUserScope resolvePermissionUserScope(String userId, String moduleId) {
        List<String> permissionUserIds = permissionsUtils.obtainPersonnelUserIdDataPermissions(userId, moduleId);
        if (permissionUserIds == null) {
            return new PermissionUserScope(true, Collections.emptyList());
        }
        return new PermissionUserScope(false, normalizeIdList(permissionUserIds));
    }

    /**
     * 解析组织数据权限范围。
     * 通过 allDataPermission 标识是否全量权限，orgIds 为受限时可访问组织。
     */
    private PermissionOrgScope resolvePermissionOrgScope(String userId, String moduleId,String tenantId) {
        if (Boolean.TRUE.equals(UserProvider.getUser().getIsAdministrator())) {
            return new PermissionOrgScope(true, Collections.emptyList());
        }

        PermissionsApplicableObject applicableObject = permissionsUtils.obtainTheScopeOfUserPermissionsEnums(userId, moduleId,tenantId);
        PermissionsApplicableEnums applicableEnums = applicableObject == null ? null : applicableObject.getPermissionsApplicableEnums();
        if (PermissionsApplicableEnums.ALL.equals(applicableEnums)) {
            return new PermissionOrgScope(true, Collections.emptyList());
        }

        List<String> orgIds = normalizeIdList(applicableObject == null ? Collections.emptyList() : applicableObject.getOrgIds());
        if (CollUtil.isEmpty(orgIds)) {
            try {
                List<String> fallbackOrgIds = permissionsUtils.obtainPersonnelOrganizationIdDataPermissions(userId);
                if (fallbackOrgIds == null) {
                    return new PermissionOrgScope(true, Collections.emptyList());
                }
                orgIds = normalizeIdList(fallbackOrgIds);
            } catch (Exception e) {
                return new PermissionOrgScope(false, Collections.emptyList());
            }
        }
        return new PermissionOrgScope(false, orgIds);
    }

    /**
     * 规整 ID 列表：去空、去重、去前后空格。
     */
    private List<String> normalizeIdList(List<String> idList) {
        if (CollUtil.isEmpty(idList)) {
            return Collections.emptyList();
        }
        return idList.stream()
                .filter(StrUtil::isNotBlank)
                .map(StrUtil::trim)
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 是否为健康证类型。
     */
    private boolean isHealthCertificate(String certificateType) {
        return StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.HEALTH_CERTIFICATE.getType());
    }

    /**
     * 构建图表统计结果对象。
     */
    private CertificateAppRiskChartVO buildChart(List<CertificateAppStatusCountVO> statusCountList) {
        Map<Integer, Integer> countMap = CollUtil.emptyIfNull(statusCountList)
                .stream()
                .filter(item -> item != null && item.getStatus() != null)
                .collect(Collectors.toMap(
                        CertificateAppStatusCountVO::getStatus,
                        item -> item.getCount() == null ? 0 : item.getCount(),
                        Integer::sum
                ));

        int missingCount = countMap.getOrDefault(STATUS_MISSING, 0);
        int nearExpireCount = countMap.getOrDefault(STATUS_NEAR_EXPIRE, 0);
        int expiredCount = countMap.getOrDefault(STATUS_EXPIRED, 0);
        int normalCount = countMap.getOrDefault(STATUS_NORMAL, 0);
        int totalCount = missingCount + nearExpireCount + expiredCount + normalCount;

        CertificateAppRiskChartVO chartVO = new CertificateAppRiskChartVO();
        chartVO.setMissingCount(missingCount);
        chartVO.setNearExpireCount(nearExpireCount);
        chartVO.setExpiredCount(expiredCount);
        chartVO.setNormalCount(normalCount);
        chartVO.setTotalCount(totalCount);

        chartVO.setStatusList(Arrays.asList(
                buildStatusCount(STATUS_MISSING, missingCount),
                buildStatusCount(STATUS_NEAR_EXPIRE, nearExpireCount),
                buildStatusCount(STATUS_EXPIRED, expiredCount),
                buildStatusCount(STATUS_NORMAL, normalCount)
        ));
        return chartVO;
    }

    /**
     * 构建单个状态统计项。
     */
    private CertificateAppStatusCountVO buildStatusCount(Integer status, Integer count) {
        CertificateAppStatusCountVO item = new CertificateAppStatusCountVO();
        item.setStatus(status);
        item.setStatusName(resolveStatusName(status));
        item.setCount(count == null ? 0 : count);
        return item;
    }

    /**
     * 构建空图表结果。
     */
    private CertificateAppRiskChartVO buildEmptyChart() {
        return buildChart(Collections.emptyList());
    }

    /**
     * 构建员工风险空分页。
     */
    private PageInfo<CertificateAppEmployeeRiskVO> buildEmptyEmployeePage(long current, long pageSize) {
        PageInfo<CertificateAppEmployeeRiskVO> pageInfo = new PageInfo<>();
        pageInfo.setList(Collections.emptyList());
        pageInfo.setPageNum((int) current);
        pageInfo.setPageSize((int) pageSize);
        pageInfo.setTotal(0);
        return pageInfo;
    }

    /**
     * 构建门店风险空分页。
     */
    private PageInfo<CertificateAppStoreRiskVO> buildEmptyStorePage(long current, long pageSize) {
        PageInfo<CertificateAppStoreRiskVO> pageInfo = new PageInfo<>();
        pageInfo.setList(Collections.emptyList());
        pageInfo.setPageNum((int) current);
        pageInfo.setPageSize((int) pageSize);
        pageInfo.setTotal(0);
        return pageInfo;
    }

    /**
     * 填充门店风险返回项的展示字段。
     */
    private void fillStoreRiskItem(List<CertificateAppStoreRiskVO> records,Map<String, OrganizeBaseInfoVO> organizeBaseInfoVOMap) {
        if (CollectionUtil.isEmpty(records)) {
            return;
        }
        for (CertificateAppStoreRiskVO item : records){
            OrganizeBaseInfoVO organizeBaseInfoVO = organizeBaseInfoVOMap.get(item.getSubjectId());
            if(Objects.isNull(organizeBaseInfoVO)){
                continue;
            }
            item.setOrganizeId(organizeBaseInfoVO.getId());
            item.setOrganizeName(organizeBaseInfoVO.getName());
            String storeTag = organizeBaseInfoVO.getStoreTag();
            item.setStoreTag(storeTag);
            item.setOrganizeLeaderName(organizeBaseInfoVO.getLeaderName());
            item.setOrganizeLeaderId(organizeBaseInfoVO.getLeaderId());
            FtbStoreTagEnum storeTagEnum = FtbStoreTagEnum.fromName(storeTag);
            if(Objects.nonNull(storeTagEnum)){
                item.setStoreTagName(storeTagEnum.getLabel());
            }
        }

    }

    /**
     * 状态编码转中文名称。
     */
    private String resolveStatusName(Integer status) {
        if (Integer.valueOf(STATUS_MISSING).equals(status)) {
            return "缺失";
        }
        if (Integer.valueOf(STATUS_EXPIRED).equals(status)) {
            return "过期";
        }
        if (Integer.valueOf(STATUS_NEAR_EXPIRE).equals(status)) {
            return "临期";
        }
        if (Integer.valueOf(STATUS_NORMAL).equals(status)) {
            return "正常";
        }
        return "-";
    }

    /**
     * 证照类型编码转中文名称。
     */
    private String resolveCertificateTypeName(String certificateType,String templateId,Map<String,String> templateIdAndNames) {
        if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.HEALTH_CERTIFICATE.getType())) {
            return "健康证";
        }
        if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.BUSINESS_LICENSE.getType())) {
            return "营业执照";
        }
        if (StrUtil.equalsIgnoreCase(certificateType, CertificateTypeEnum.HYGIENE_LICENSE.getType())) {
            return "食品经营许可证";
        }
        if (StrUtil.isBlank(certificateType)) {
            return "证照";
        }
        String templateName = templateIdAndNames.get(templateId);
        if(StringUtil.isNotBlank(templateName)){
            return templateName;
        }
        return "";
    }

    /**
     * 用户维度权限范围。
     */
    private static class PermissionUserScope {
        private final Boolean allDataPermission;
        private final List<String> userIds;

        private PermissionUserScope(Boolean allDataPermission, List<String> userIds) {
            this.allDataPermission = allDataPermission;
            this.userIds = userIds;
        }

        public Boolean getAllDataPermission() {
            return allDataPermission;
        }

        public List<String> getUserIds() {
            return userIds;
        }
    }

    /**
     * 组织维度权限范围。
     */
    private static class PermissionOrgScope {
        private final Boolean allDataPermission;
        private final List<String> orgIds;

        private PermissionOrgScope(Boolean allDataPermission, List<String> orgIds) {
            this.allDataPermission = allDataPermission;
            this.orgIds = orgIds;
        }

        public Boolean getAllDataPermission() {
            return allDataPermission;
        }

        public List<String> getOrgIds() {
            return orgIds;
        }
    }
}
