package jnpf.culture.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jnpf.authority.service.FtbPermissionOrganizeService;
import jnpf.authority.service.FtbPermissionUsersService;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.culture.mapper.CultureClockInMapper;
import jnpf.culture.mapper.CultureClockInStatMapper;
import jnpf.culture.service.CultureStatService;
import jnpf.entity.culture.CultureClockIn;
import jnpf.entity.culture.CultureClockInStat;
import jnpf.enums.attendance.StatisticsEnumUtil;
import jnpf.model.culture.dto.StatQueryDto;
import jnpf.model.culture.vo.CultureStatVo;
import jnpf.model.personnels.dto.staff.roster.FtbPersonnelsStaffRosterDto;
import jnpf.model.personnels.req.roster.StaffRosterReq;
import jnpf.permission.V2OrganizeApi;
import jnpf.permission.vo.v2.organzie.OrganizeGeneralDetailVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.personnels.service.FtbPersonnelsStaffRosterService;
import jnpf.util.*;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 文化打卡 - 统计 服务实现
 *
 * @author yanwenfu
 * @create 2025-12-23
 */
@Service
public class CultureStatServiceImpl implements CultureStatService {

    @Resource
    private CultureClockInStatMapper cultureClockInStatMapper;
    @Resource
    private CultureClockInMapper cultureClockInMapper;
    @Resource
    private FtbPersonnelsStaffRosterService staffRosterService;
    @Autowired
    private V2OrganizeApi v2OrganizeApi;
    @Autowired
    private FtbPermissionOrganizeService ftbPermissionOrganizeService;
    @Autowired
    private FtbPermissionUsersService ftbPermissionUsersService;

    @Override
    public PageInfo<CultureStatVo> getStatPage(StatQueryDto queryDto) {

        List<String> orgIds = getOrgAndChildren(queryDto.getOrgIds());
        List<FtbPersonnelsStaffRosterDto> data = null;
        List<String> userIdList = new ArrayList<>();
        // 查询用户权限
        List<UserBoundVO> list = ftbPermissionUsersService.authGetAllUserInfoBatch();
        if (null == list || list.isEmpty()) {
            PageInfo<CultureStatVo> page = new PageInfo<>();
            page.setPageSize(queryDto.getPageSize());
            page.setPageNum(queryDto.getCurrentPage());
            return page;
        }
        List<String> authUserIds = list.stream().map(UserBoundVO::getId).collect(Collectors.toList());
        if (StringUtil.isNotEmpty(queryDto.getUserName()) || (null != orgIds && !orgIds.isEmpty())) {
            StaffRosterReq req = new StaffRosterReq();
            req.setKeyWords(queryDto.getUserName());
            req.setOrgIds(orgIds);
            req.setUserIds(authUserIds);
            data = staffRosterService.queryWithUserIdsPost(req);
            if (null == data || data.isEmpty()) {
                PageInfo<CultureStatVo> page = new PageInfo<>();
                page.setPageSize(queryDto.getPageSize());
                page.setPageNum(queryDto.getCurrentPage());
                return page;
            }
            List<String> collect = data.stream().map(FtbPersonnelsStaffRosterDto::getUserId).collect(Collectors.toList());
            userIdList.addAll(collect);
        } else {
            userIdList.addAll(authUserIds);
        }
        // 查询每个员工的最近打卡
        PageHelper.startPage(queryDto.getCurrentPage(), queryDto.getPageSize());
        PageInfo<CultureClockIn> page = new PageInfo<>(cultureClockInMapper.getClockInList(queryDto.getStartDate(), queryDto.getEndDate(), userIdList));
        if (page.getList().isEmpty()) {
            PageInfo<CultureStatVo> pageInfo = new PageInfo<>();
            pageInfo.setPageSize(queryDto.getPageSize());
            pageInfo.setPageNum(queryDto.getCurrentPage());
            return pageInfo;
        }
        // 转换分页对象
        PageInfo<CultureStatVo> returnPage = new PageInfo<>();
        List<CultureStatVo> returnList = new ArrayList<>();
        page.getList().forEach(v -> returnList.add(new CultureStatVo(v.getUserId(), v.getClockInTime())));
        returnPage.setList(returnList);
        returnPage.setTotal(page.getTotal());
        returnPage.setPageNum(page.getPageNum());
        returnPage.setPageSize(page.getPageSize());
        // 填充用户信息
        List<String> userIds = page.getList().stream().map(CultureClockIn::getUserId).collect(Collectors.toList());
        if (data == null) {
            StaffRosterReq req = new StaffRosterReq();
            req.setUserIds(userIds);
            data = staffRosterService.queryWithUserIdsPost(req);
        }
        if (null != data && !data.isEmpty()) {
            Map<String, FtbPersonnelsStaffRosterDto> userMap = data.stream().collect(Collectors.toMap(FtbPersonnelsStaffRosterDto::getUserId, Function.identity()));
            returnPage.getList().forEach(v -> {
                FtbPersonnelsStaffRosterDto user = userMap.get(v.getUserId());
                if (null != user) {
                    v.setUserName(user.getName());
                    v.setOrgName(user.getCurrOrgName());
                    if (user.getEnabledMark() == ConstantUtil.NUM_TRUE) {
                        v.setUserName(v.getUserName() + "（已删除）");
                    } else {
                        if (user.getWorkerStatus().equals(StatisticsEnumUtil.WorkStatusEnum.LZ.getCode())) {
                            v.setUserName(v.getUserName() + "（已离职）");
                        }
                    }
                }
            });
        }
        // 填充统计信息
        LambdaQueryWrapper<CultureClockInStat> queryWrapper = new LambdaQueryWrapper<CultureClockInStat>()
                .in(CultureClockInStat::getUserId, userIds)
                .eq(CultureClockInStat::getDeleteMark, ConstantUtil.NUM_FALSE);
        List<CultureClockInStat> statList = cultureClockInStatMapper.selectList(queryWrapper);
        Map<String, CultureClockInStat> map = statList.stream().collect(Collectors.toMap(CultureClockInStat::getUserId, Function.identity()));
        returnPage.getList().forEach(v -> {
            CultureClockInStat stat = map.get(v.getUserId());
            if (null == stat) {
                v.setTotalDays(0);
                v.setMaxContinuousDays(0);
                v.setMaxMissDays(0);
            } else {
                v.setTotalDays(stat.getTotalDays());
                v.setMaxContinuousDays(stat.getMaxContinuousDays());
                int realMaxMissDays = stat.getMaxMissDays();
                LocalDate yesterday = LocalDate.now().minusDays(1);
                if (stat.getLastClockInDate() != null && !stat.getLastClockInDate().equals(yesterday)) {
                    int currentMissDays = DateDetail.calculateDayDiff(stat.getLastClockInDate(), LocalDate.now()) - 1;
                    realMaxMissDays = Math.max(currentMissDays, realMaxMissDays);
                }
                v.setMaxMissDays(realMaxMissDays);
            }
        });
        return returnPage;
    }

    private List<String> getOrgAndChildren(List<String> orgIds) {

        // 查询用户权限
        List<OrganizeGeneralDetailVO> orgList = ftbPermissionOrganizeService.authOrganizesByUserBound(List.of(), null, false, false);
        if (null == orgList || orgList.isEmpty()) {
            return null;
        }
        // 用户所有可查看的组织
        List<String> orgIdList = orgList.stream().map(OrganizeGeneralDetailVO::getId).collect(Collectors.toList());
        List<String> intersection = getAuthOrgList(orgIdList, orgIds);
        ActionResult<List<OrganizeGeneralDetailVO>> listActionResult = v2OrganizeApi.organizesOrHaveChildByOrganizeIds(intersection, true, UserProvider.getUser().getTenantId());
        if (null != listActionResult && 200 == listActionResult.getCode()) {
            List<String> collect = listActionResult.getData().stream().map(OrganizeGeneralDetailVO::getId).collect(Collectors.toList());
            return getAuthOrgList(orgIdList, collect);
        }
        return null;
    }

    private List<String> getAuthOrgList(List<String> authList, List<String> orgIds) {

        List<String> intersection;
        if (null != orgIds && !orgIds.isEmpty()) {
            Set<String> setB = new HashSet<>(orgIds);
            intersection = authList.stream().filter(setB::contains).collect(Collectors.toList());
            if (intersection.isEmpty()) {
                return null;
            }
        } else {
            intersection = authList;
        }
        return intersection;
    }

    @Override
    public Workbook getStatWorkbook(StatQueryDto queryDto) {

        queryDto.setCurrentPage(1);
        queryDto.setPageSize(999999);
        PageInfo<CultureStatVo> statPage = getStatPage(queryDto);
        // 生成工作簿
        TemplateWorkSheet workSheet = new TemplateWorkSheet();
        workSheet.setSheetName(ConstantUtil.CULTURE_CLOCK_IN_FORM);
        // 生成表头
        workSheet.setRowNames(ConstantUtil.TITLE_CULTURE_CLOCK_IN_TABLE);
        workSheet.setTitleNum(1);
        int len = workSheet.getRowNames().length;
        // 生成数据
        List<Object[]> dataList = new ArrayList<>();
        if (!statPage.getList().isEmpty()) {
            for (int i = 0; i < statPage.getList().size(); i++) {
                Object[] array = new Object[len];
                CultureStatVo stat = statPage.getList().get(i);
                for (int j = 0; j < len; j++) {
                    switch (j) {
                        case 0:
                            array[j] = stat.getUserName();
                            break;
                        case 1:
                            array[j] = stat.getOrgName();
                            break;
                        case 2:
                            array[j] = null == stat.getLastClockInTime() ? null : DateDetail.getDate2Str(stat.getLastClockInTime(), DateDetail.DF4);
                            break;
                        case 3:
                            array[j] = stat.getTotalDays();
                            break;
                        case 4:
                            array[j] = stat.getMaxContinuousDays();
                            break;
                        case 5:
                            array[j] = stat.getMaxMissDays();
                            break;
                        default:
                            break;
                    }
                }
                dataList.add(array);
            }
        }
        workSheet.setDataList(dataList);
        return TemplateExcelUtils.createWorkBook(List.of(workSheet), true);
    }
}
