package cn.stylefeng.team.project.modular.filing.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.pidset.ParentIdParseUtil;
import cn.stylefeng.roses.kernel.sys.api.OrganizationServiceApi;
import cn.stylefeng.roses.kernel.sys.api.pojo.org.HrOrganizationDTO;
import cn.stylefeng.team.form.api.FormModelServiceApi;
import cn.stylefeng.team.meta.api.DiagramServiceApi;
import cn.stylefeng.team.meta.api.MetaModelServiceApi;
import cn.stylefeng.team.meta.api.UserDictServiceApi;
import cn.stylefeng.team.project.modular.filing.entity.BusinessFilingLog;
import cn.stylefeng.team.project.modular.filing.mapper.BusinessDesignMapper;
import cn.stylefeng.team.project.modular.filing.pojo.businesscount.BusinessCountResult;
import cn.stylefeng.team.project.modular.filing.pojo.page.BusinessDesignPageRequest;
import cn.stylefeng.team.project.modular.filing.pojo.page.BusinessDesignPageResultVo;
import cn.stylefeng.team.project.modular.filing.pojo.queryvo.BusinessDesignQueryVo;
import cn.stylefeng.team.project.modular.filing.pojo.userfiling.TableFilingItemVo;
import cn.stylefeng.team.project.modular.filing.service.BusinessDesignService;
import cn.stylefeng.team.project.modular.filing.service.BusinessExcelService;
import cn.stylefeng.team.project.modular.filing.service.BusinessFilingLogService;
import cn.stylefeng.team.project.modular.filing.service.BusinessFlowService;
import cn.stylefeng.team.view.api.ViewApi;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

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

@Service
public class BusinessDesignServiceImpl implements BusinessDesignService {

    @Resource
    private OrganizationServiceApi organizationServiceApi;

    @Resource
    private BusinessDesignMapper businessDesignMapper;

    @Resource
    private MetaModelServiceApi metaModelServiceApi;

    @Resource
    private FormModelServiceApi formModelServiceApi;

    @Resource
    private UserDictServiceApi userDictServiceApi;

    @Resource
    private ViewApi viewApi;

    @Resource
    private BusinessFilingLogService businessFilingLogService;

    @Resource
    private DiagramServiceApi diagramServiceApi;

    @Resource
    private BusinessFlowService businessFlowService;

    @Resource
    private BusinessExcelService businessExcelService;

    @Override
    public PageResult<BusinessDesignPageResultVo> pageList(BusinessDesignPageRequest tableFilingRequest) {

        BusinessDesignQueryVo businessDesignQueryVo = this.createTableFilingParam(tableFilingRequest);

        Page<BusinessDesignPageResultVo> page = PageFactory.defaultPage();
        List<BusinessDesignPageResultVo> resultVoList = this.businessDesignMapper.queryTableDesignPageList(page, businessDesignQueryVo);

        this.fillCountStat(resultVoList);

        page.setRecords(resultVoList);
        return PageResultFactory.createPageResult(page);

    }

    @Override
    public BusinessDesignQueryVo createTableFilingParam(BusinessDesignPageRequest businessDesignPageRequest) {

        BusinessDesignQueryVo businessDesignQueryVo = new BusinessDesignQueryVo();

        businessDesignQueryVo.setOwnershipDeptId(businessDesignPageRequest.getOwnershipDeptId());
        businessDesignQueryVo.setSearchText(businessDesignPageRequest.getSearchText());
        businessDesignQueryVo.setBusinessCategoryId(businessDesignPageRequest.getBusinessCategoryId());

        Long userId = LoginContext.me().getLoginUser().getUserId();
        Long currentOrgId = LoginContext.me().getLoginUser().getCurrentOrgId();
        businessDesignQueryVo.setPointScopeBusinessIdList(currentOrgId == null ? CollectionUtil.set(false, userId) : CollectionUtil.set(false, userId, currentOrgId));

        if (currentOrgId != null) {
            HrOrganizationDTO orgInfo = this.organizationServiceApi.getOrgInfo(currentOrgId);
            List<Long> parentIdList = ParentIdParseUtil.parseToPidList(orgInfo.getOrgPids());
            parentIdList.add(currentOrgId);
            businessDesignQueryVo.setPointAndSubBusinessIdList(new HashSet<>(parentIdList));
        }
        businessDesignQueryVo.setCurrentUserId(userId);

        return businessDesignQueryVo;

    }

    @Override
    public List<BusinessCountResult> getBusinessStatInfo(Set<Long> businessIdList) {
        List<BusinessCountResult> businessCountResults = new ArrayList<>();

        if (ObjectUtil.isEmpty(businessIdList)) {
            return businessCountResults;
        }

        Map<Long, Integer> modelNumber = this.metaModelServiceApi.statModelNumber(businessIdList);

        Map<Long, Integer> formNumber = this.formModelServiceApi.statFormNumber(businessIdList);

        Map<Long, Integer> dictNumber = this.userDictServiceApi.statDictNumber(businessIdList);

        Map<Long, Integer> viewNumber = this.viewApi.statViewNumber(businessIdList);

        Map<Long, Integer> diagramNumber = this.diagramServiceApi.statBusinessDiagramNumber(businessIdList);

        Map<Long, Integer> businessFlowNumber = this.businessFlowService.statBusinessFlowNumber(businessIdList);

        Map<Long, Integer> statExcelNumber = this.businessExcelService.statExcelNumber(businessIdList);

        for (Long businessId : businessIdList) {
            BusinessCountResult businessCountResult = new BusinessCountResult();
            businessCountResult.setBusinessId(businessId);
            businessCountResult.setTableCount(modelNumber.get(businessId) == null ? 0 : modelNumber.get(businessId));
            businessCountResult.setFormCount(formNumber.get(businessId) == null ? 0 : formNumber.get(businessId));
            businessCountResult.setDictCount(dictNumber.get(businessId) == null ? 0 : dictNumber.get(businessId));
            businessCountResult.setViewCount(viewNumber.get(businessId) == null ? 0 : viewNumber.get(businessId));
            businessCountResult.setDiagramCount(diagramNumber.get(businessId) == null ? 0 : diagramNumber.get(businessId));
            businessCountResult.setFlowCount(businessFlowNumber.get(businessId) == null ? 0 : businessFlowNumber.get(businessId));
            businessCountResult.setExcelCount(statExcelNumber.get(businessId) == null ? 0 : statExcelNumber.get(businessId));
            businessCountResults.add(businessCountResult);
        }

        return businessCountResults;
    }

    @Override
    public PageResult<TableFilingItemVo> getUserFilingPageList(BusinessDesignPageRequest businessDesignPageRequest) {

        BusinessDesignQueryVo businessDesignQueryVo = this.createTableFilingParam(businessDesignPageRequest);

        Page<TableFilingItemVo> page = PageFactory.defaultPage();
        List<TableFilingItemVo> resultVoList = this.businessDesignMapper.queryUserNeedFilingPageList(page, businessDesignQueryVo);
        if (ObjectUtil.isEmpty(resultVoList)) {
            return PageResultFactory.createPageResult(page);
        }

        List<Long> businessIdList = resultVoList.stream().map(TableFilingItemVo::getBusinessId).toList();
        Long userId = LoginContext.me().getLoginUser().getUserId();
        Long currentOrgId = LoginContext.me().getLoginUser().getCurrentOrgId();
        List<BusinessFilingLog> userFilingLogList = this.businessFilingLogService.getUserFilingLogList(userId, currentOrgId, businessIdList);

        this.getFilingStatus(resultVoList, userFilingLogList);

        page.setRecords(resultVoList);
        return PageResultFactory.createPageResult(page);
    }

    private void fillCountStat(List<BusinessDesignPageResultVo> businessDesignPageResultVoList) {
        Set<Long> businessIdList = businessDesignPageResultVoList.stream().map(BusinessDesignPageResultVo::getBusinessId).collect(Collectors.toSet());
        List<BusinessCountResult> businessStatInfo = this.getBusinessStatInfo(businessIdList);

        for (BusinessDesignPageResultVo businessDesignPageResultVo : businessDesignPageResultVoList) {
            for (BusinessCountResult businessCountResult : businessStatInfo) {
                if (businessDesignPageResultVo.getBusinessId().equals(businessCountResult.getBusinessId())) {
                    businessDesignPageResultVo.setTableCount(businessCountResult.getTableCount());
                    businessDesignPageResultVo.setFormCount(businessCountResult.getFormCount());
                    businessDesignPageResultVo.setDictCount(businessCountResult.getDictCount());
                    businessDesignPageResultVo.setViewCount(businessCountResult.getViewCount());
                }
            }
        }
    }

    private void getFilingStatus(List<TableFilingItemVo> resultVoList, List<BusinessFilingLog> userFilingLogList) {
        for (TableFilingItemVo itemVo : resultVoList) {

            List<BusinessFilingLog> relatedLogs = userFilingLogList.stream()
                    .filter(log -> log.getBusinessId().equals(itemVo.getBusinessId()))
                    .sorted((log1, log2) -> log2.getReportTime().compareTo(log1.getReportTime()))
                    .toList();

            if (!relatedLogs.isEmpty()) {
                BusinessFilingLog latestLog = relatedLogs.get(0);
                itemVo.setLastFilingTime(latestLog.getReportTime());
            }
        }
    }

}
