package com.yuchen.saas.park.service.service.property.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.read.listener.ReadListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuchen.saas.park.api.dto.property.PropertyCommitteeMemberDto;
import com.yuchen.saas.park.api.dto.property.PropertyCommitteeMemberQueryDto;
import com.yuchen.saas.park.api.entity.park.PmgBatParkInfo;
import com.yuchen.saas.park.api.entity.property.PropertyCommitteeMember;
import com.yuchen.saas.park.api.entity.property.PropertyHouseOwner;
import com.yuchen.saas.park.api.entity.property.PropertyHouses;
import com.yuchen.saas.park.api.enums.property.*;
import com.yuchen.saas.park.api.vo.property.*;
import com.yuchen.saas.park.service.mapper.property.PropertyCommitteeMemberMapper;
import com.yuchen.saas.park.service.service.PmgBatParkInfoService;
import com.yuchen.saas.park.service.service.property.IPropertyCommitteeMemberService;
import com.yuchen.saas.park.service.service.property.IPropertyHouseOwnerService;
import com.yuchen.saas.park.service.service.property.PropertyHousesService;
import lombok.extern.slf4j.Slf4j;
import org.nest.springwrap.core.log.exception.ServiceException;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.mp.support.Condition;
import org.nest.springwrap.core.mp.support.NestPage;
import org.nest.springwrap.core.tool.utils.BeanUtil;
import org.nest.springwrap.core.tool.utils.Func;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author 蔡文强
 * @Date 2023/11/28 10:56
 * @Description 委员会成员表 服务实现类
 */
@Slf4j
@Service
public class PropertyCommitteeMemberServiceImpl extends BaseServiceImpl<PropertyCommitteeMemberMapper, PropertyCommitteeMember> implements IPropertyCommitteeMemberService {

    @Resource
    private PmgBatParkInfoService parkInfoService;

    @Resource
    private PropertyHousesService housesService;

    @Resource
    private IPropertyHouseOwnerService houseOwnerService;

    @Override
    public Boolean saveOrUpdateCommitteeMember(PropertyCommitteeMemberDto committeeMemberDto) {
        PropertyCommitteeMember committeeMember = BeanUtil.copyProperties(committeeMemberDto, PropertyCommitteeMember.class);
        return saveOrUpdate(committeeMember);
    }

    @Override
    public Boolean deleteCommitteeMember(Long id) {
        return removeById(id);
    }

    @Override
    public PropertyCommitteeMemberVo getCommitteeMemberById(Long id) {
        PropertyCommitteeMemberVo committeeMemberVo = BeanUtil.copyProperties(getById(id), PropertyCommitteeMemberVo.class);
        return committeeMemberVo;
    }

    @Override
    public NestPage<PropertyCommitteeMemberListVo> getCommitteeMemberPageList(PropertyCommitteeMemberQueryDto queryDto) {
        if (Func.isNotEmpty(queryDto.getBuildingId()) && Func.isEmpty(queryDto.getHouseId())) {
            List<Long> houseIdList = housesService.listByBuildingId(queryDto.getBuildingId()).stream().map(PropertyHouses::getId).collect(Collectors.toList());
            queryDto.setHouseIdList(houseIdList);
        }
        LambdaQueryWrapper<PropertyCommitteeMember> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Func.isNotEmpty(queryDto.getParkId()), PropertyCommitteeMember::getParkId, queryDto.getParkId());
        queryWrapper.eq(Func.isNotEmpty(queryDto.getHouseId()), PropertyCommitteeMember::getHouseId, queryDto.getHouseId());
        queryWrapper.in(Func.isNotEmpty(queryDto.getHouseIdList()), PropertyCommitteeMember::getHouseId, queryDto.getHouseIdList());
        queryWrapper.like(Func.isNotEmpty(queryDto.getMemberName()), PropertyCommitteeMember::getMemberName, queryDto.getMemberName());
        queryWrapper.eq(Func.isNotEmpty(queryDto.getSex()), PropertyCommitteeMember::getSex, queryDto.getSex());
        queryWrapper.eq(Func.isNotEmpty(queryDto.getPosition()), PropertyCommitteeMember::getPosition, queryDto.getPosition());
        queryWrapper.like(Func.isNotEmpty(queryDto.getLinkPhone()), PropertyCommitteeMember::getLinkPhone, queryDto.getLinkPhone());
        queryWrapper.orderByDesc(PropertyCommitteeMember::getCreateTime);
        IPage<PropertyCommitteeMember> page = this.page(Condition.getPage(queryDto), queryWrapper);
        IPage<PropertyCommitteeMemberListVo> result = new Page<>(queryDto.getCurrent(), queryDto.getSize());
        List<PropertyCommitteeMember> recordList = page.getRecords();
        List<PropertyCommitteeMemberListVo> list = BeanUtil.copyProperties(recordList, PropertyCommitteeMemberListVo.class);
        Map<Long, String> parkMap = getParkMap();
        for(PropertyCommitteeMemberListVo vo : list) {
            vo.setParkName(parkMap.get(vo.getParkId()));
            PropertyHousesVo propertyHousesVo = housesService.getPropertyHousesDetail(vo.getHouseId());
            vo.setHouseName(propertyHousesVo.getHouseName());
            vo.setBuildingName(propertyHousesVo.getBuildingName());
        }
        result.setRecords(list);
        result.setTotal(page.getTotal());
        return NestPage.of(result);
    }

    @Override
    public PropertyCommitteeMemberImportResVo importCommitteeMember(MultipartFile file) {
        if (!(file.getOriginalFilename().endsWith(".xlsx") || file.getOriginalFilename().endsWith(".xls"))) {
            throw new ServiceException("请选择正确的excel文件");
        }
        PropertyCommitteeMemberImportResVo vo = new PropertyCommitteeMemberImportResVo();
        vo.setImportSize(0);
        vo.setFailSize(0);
        vo.setSuccessSize(0);
        List<String> msg = new ArrayList<>();
        vo.setMsg(msg);
        List<PmgBatParkInfo> list = parkInfoService.list();
        Map<String, PmgBatParkInfo> parkMap = list.stream().collect(Collectors.toMap(PmgBatParkInfo::getParkName, a -> a));
        List<PropertyHouses> houseList = housesService.list();
        Map<String, PropertyHouses> houseMap = houseList.stream().collect(Collectors.toMap(PropertyHouses::getResourceCode, a -> a));
        try {
            EasyExcel.read(file.getInputStream(),
                    PropertyCommitteeMemberImportExcelVo.class, new ReadListener() {

                        @Override
                        public void onException(Exception exception, AnalysisContext context) throws Exception {
                            log.error("导出异常", exception);
                            log.info("context", context);
                            vo.setFailSize(vo.getFailSize() + 1);
                            Integer rowIndex = context.readRowHolder().getRowIndex();
                            vo.getMsg().add(String.format("第%s条导入失败,失败原因:%s;", rowIndex, exception.getMessage()));
                        }

                        @Override
                        public void invokeHead(Map headMap, AnalysisContext context) {
                            log.info("context", context);
                            log.info("headMap", headMap);
                        }

                        @Override
                        public void invoke(Object o, AnalysisContext analysisContext) {
                            vo.setImportSize(vo.getImportSize() + 1);
                            PropertyCommitteeMemberImportExcelVo importVo = (PropertyCommitteeMemberImportExcelVo) o;
                            saveImport(importVo, parkMap, houseMap);
                        }

                        @Override
                        public void extra(CellExtra extra, AnalysisContext context) {
                            log.info("extra", context);
                        }

                        @Override
                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                            log.info("analysisContext", analysisContext);
                        }

                        @Override
                        public boolean hasNext(AnalysisContext context) {
                            return true;
                        }
                    }).sheet().doRead();
        } catch (IOException e) {
            log.info("导入异常", e);
        }

        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveImport(PropertyCommitteeMemberImportExcelVo importVo, Map<String, PmgBatParkInfo> parkMap, Map<String, PropertyHouses> houseMap) {
        PropertyCommitteeMember committeeMember = new PropertyCommitteeMember();
        BeanUtils.copyProperties(importVo, committeeMember);
        if (Func.isBlank(importVo.getParkName())) {
            throw new ServiceException("园区不能为空");
        }
        if (Func.isBlank(importVo.getHouseCode())) {
            throw new ServiceException("房间代码不能为空");
        }
        if (Func.isBlank(importVo.getMemberName())) {
            throw new ServiceException("姓名不能为空");
        }

        String parkName = importVo.getParkName().replaceAll("\\s*", "");
        if (parkMap.containsKey(parkName)) {
            PmgBatParkInfo parkInfo = parkMap.get(parkName);
            committeeMember.setParkId(parkInfo.getId());
        } else {
            throw new ServiceException("园区名称不存在");
        }

        String houseCode = importVo.getHouseCode().replaceAll("\\s*", "");
        if (houseMap.containsKey(houseCode)) {
            PropertyHouses houses = houseMap.get(houseCode);
            committeeMember.setHouseId(houses.getId());
        } else {
            throw new ServiceException("房间不存在");
        }

        PropertyHouseOwner houseOwner = houseOwnerService.lambdaQuery().eq(PropertyHouseOwner::getHouseId, committeeMember.getHouseId())
                .orderByDesc(PropertyHouseOwner::getCreateTime).last("LIMIT 1").one();
        if (Func.isEmpty(houseOwner)) {
            throw new ServiceException("房间业主不存在");
        }
        committeeMember.setOwnerId(houseOwner.getId());

        String sexName = importVo.getSexName().replaceAll("\\s*", "");
        if (sexName.equals(SexEnum.getDescByCode(SexEnum.MALE.getValue()))) {
            committeeMember.setSex(SexEnum.MALE.getValue());
        } else if (sexName.equals(SexEnum.getDescByCode(SexEnum.FEMALE.getValue()))) {
            committeeMember.setSex(SexEnum.FEMALE.getValue());
        } else {
            throw new ServiceException("性别不存在");
        }

        String positionName = importVo.getPositionName().replaceAll("\\s*", "");
        if (Func.isNotEmpty(positionName)) {
            if (positionName.equals(PositionEnum.getDescByCode(PositionEnum.DIRECTOR.getValue()))) {
                committeeMember.setPosition(PositionEnum.DIRECTOR.getValue());
            } else if (positionName.equals(PositionEnum.getDescByCode(PositionEnum.DEPUTY_DIRECTOR.getValue()))) {
                committeeMember.setPosition(PositionEnum.DEPUTY_DIRECTOR.getValue());
            } else if (positionName.equals(PositionEnum.getDescByCode(PositionEnum.MEMBER.getValue()))) {
                committeeMember.setPosition(PositionEnum.MEMBER.getValue());
            } else {
                throw new ServiceException("职位不存在");
            }
        }

        this.save(committeeMember);
    }


    @Override
    public void exportCommitteeMember(PropertyCommitteeMemberQueryDto queryDto, HttpServletResponse response) {
        if (Func.isNotEmpty(queryDto.getBuildingId()) && Func.isEmpty(queryDto.getHouseId())) {
            List<Long> houseIdList = housesService.listByBuildingId(queryDto.getBuildingId()).stream().map(PropertyHouses::getId).collect(Collectors.toList());
            queryDto.setHouseIdList(houseIdList);
        }
        LambdaQueryWrapper<PropertyCommitteeMember> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Func.isNotEmpty(queryDto.getParkId()), PropertyCommitteeMember::getParkId, queryDto.getParkId());
        queryWrapper.eq(Func.isNotEmpty(queryDto.getHouseId()), PropertyCommitteeMember::getHouseId, queryDto.getHouseId());
        queryWrapper.in(Func.isNotEmpty(queryDto.getHouseIdList()), PropertyCommitteeMember::getHouseId, queryDto.getHouseIdList());
        queryWrapper.like(Func.isNotEmpty(queryDto.getMemberName()), PropertyCommitteeMember::getMemberName, queryDto.getMemberName());
        queryWrapper.eq(Func.isNotEmpty(queryDto.getSex()), PropertyCommitteeMember::getSex, queryDto.getSex());
        queryWrapper.eq(Func.isNotEmpty(queryDto.getPosition()), PropertyCommitteeMember::getPosition, queryDto.getPosition());
        queryWrapper.like(Func.isNotEmpty(queryDto.getLinkPhone()), PropertyCommitteeMember::getLinkPhone, queryDto.getLinkPhone());
        queryWrapper.orderByDesc(PropertyCommitteeMember::getCreateTime);
        List<PropertyCommitteeMember> recordList = this.list(queryWrapper);
        List<PropertyCommitteeMemberExcelVo> excelVoList = BeanUtil.copyProperties(recordList, PropertyCommitteeMemberExcelVo.class);
        Map<Long, String> parkMap = getParkMap();
        excelVoList.forEach(excelVo -> {
            excelVo.setParkName(parkMap.get(excelVo.getParkId()));
            PropertyHousesVo propertyHousesVo = housesService.getPropertyHousesDetail(excelVo.getHouseId());
            excelVo.setBuildingName(propertyHousesVo.getBuildingName());
            excelVo.setHouseName(propertyHousesVo.getHouseName());
            excelVo.setSexName(SexEnum.getDescByCode(excelVo.getSex()));
            excelVo.setPositionName(PositionEnum.getDescByCode(excelVo.getPosition()));
        });
        try {
            String fileName = URLEncoder.encode("委员会成员表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), PropertyCommitteeMemberExcelVo.class)
                    .sheet("委员会成员表")
                    .doWrite(excelVoList); //最终处理好的数据结果集list
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }


    }

    /**
     * @description 获取园区信息列表Map
     */
    private Map<Long, String> getParkMap() {
        List<PmgBatParkInfo> parkList = parkInfoService.getAllPark();
        return parkList.stream().collect(Collectors.toMap(PmgBatParkInfo::getId, PmgBatParkInfo::getParkName));
    }

}
