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.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuchen.saas.integration.feign.api.util.PageConverterUtils;
import com.yuchen.saas.manage.user.api.entity.UserDetail;
import com.yuchen.saas.manage.user.api.feign.IUserClient;
import com.yuchen.saas.park.api.dto.property.PropertyEnterpriseMemberDto;
import com.yuchen.saas.park.api.dto.property.PropertyEnterpriseMemberQueryDto;
import com.yuchen.saas.park.api.dto.property.PropertyEnterpriseMemberSyncDto;
import com.yuchen.saas.park.api.entity.park.PmgBatParkInfo;
import com.yuchen.saas.park.api.entity.property.PropertyCustomerArchives;
import com.yuchen.saas.park.api.entity.property.PropertyHouseEnterprise;
import com.yuchen.saas.park.api.entity.property.PropertyEnterpriseMember;
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.PropertyEnterpriseMemberMapper;
import com.yuchen.saas.park.service.service.PmgBatParkInfoService;
import com.yuchen.saas.park.service.service.property.IPropertyCustomerArchivesService;
import com.yuchen.saas.park.service.service.property.IPropertyEnterpriseMemberService;
import com.yuchen.saas.park.service.service.property.IPropertyHouseEnterpriseService;
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.NestPage;
import org.nest.springwrap.core.secure.ContextUser;
import org.nest.springwrap.core.secure.utils.AuthUtil;
import org.nest.springwrap.core.tool.api.R;
import org.nest.springwrap.core.tool.utils.BeanUtil;
import org.nest.springwrap.core.tool.utils.Func;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
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 PropertyEnterpriseMemberServiceImpl extends BaseServiceImpl<PropertyEnterpriseMemberMapper, PropertyEnterpriseMember> implements IPropertyEnterpriseMemberService {

    @Resource
    private PmgBatParkInfoService parkInfoService;
    @Resource
    private PropertyHousesService housesService;
    @Resource
    private IPropertyCustomerArchivesService customerArchivesService;
    @Lazy
    @Resource
    private IPropertyHouseEnterpriseService enterpriseService;
    @Resource
    private IUserClient userClient;

    @Override
    public Boolean saveOrUpdateEnterpriseMember(PropertyEnterpriseMemberDto enterpriseMemberDto) {
        PropertyEnterpriseMember enterpriseMember = BeanUtil.copyProperties(enterpriseMemberDto, PropertyEnterpriseMember.class);
        PropertyHouseEnterprise houseEnterprise = enterpriseService.getById(enterpriseMemberDto.getEnterpriseId());
        if (Func.isEmpty(enterpriseMemberDto.getId())) {
            ContextUser contextUser = AuthUtil.getUser();
            if (Func.isEmpty(contextUser)) {
                throw new ServiceException("用户不存在");
            }
            enterpriseMember.setCreateType(CreateTypeEnum.AUTO_SYNC.getValue());
            Long registerPeopleId = contextUser.getUserDetailId();
            enterpriseMember.setCreatePeopleId(registerPeopleId);
            enterpriseMember.setMemberStatus(houseEnterprise.getEntryStatus() == EntryStatusEnum.ENTRY.getValue() ? MemberStatusEnum.NORMAL.getValue() : MemberStatusEnum.INVALID.getValue());
            save(enterpriseMember);
        } else {
            updateById(enterpriseMember);
        }
        //同步客户档案
        PropertyCustomerArchives customerArchives = customerArchivesService.getCustomerArchivesById(enterpriseMemberDto.getCustomerArchivesId());
        Integer count = customerArchivesService.lambdaQuery().eq(PropertyCustomerArchives::getCustomerType, CustomerTypeEnum.PERSON.getValue())
                .eq(PropertyCustomerArchives::getLinkPhoneOne, enterpriseMemberDto.getLinkPhone())
                .ne(PropertyCustomerArchives::getId, customerArchives.getId()).count();
        if (count > 0) {
            throw new ServiceException("个人类型客户该手机号已存在，不能重复添加");
        }
        customerArchives.setIdType(enterpriseMemberDto.getIdType());
        customerArchives.setIdNo(enterpriseMemberDto.getIdNo());
        customerArchives.setFacePhoto(enterpriseMemberDto.getFacePhoto());
        customerArchives.setLinkPhoneOne(enterpriseMemberDto.getLinkPhone());
        customerArchives.setIsLink(YesOrNoEnum.YES.getValue());
        return customerArchivesService.updateById(customerArchives);
    }

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

    @Override
    public PropertyEnterpriseMemberVo getEnterpriseMemberById(Long id) {
        PropertyEnterpriseMember enterpriseMember = getById(id);
        if (Func.isEmpty(enterpriseMember)) {
            throw new ServiceException("入驻企业成员不存在");
        }
        PropertyEnterpriseMemberVo enterpriseMemberVo = BeanUtil.copyProperties(enterpriseMember, PropertyEnterpriseMemberVo.class);
        PropertyHouseEnterprise enterprise = enterpriseService.getById(enterpriseMemberVo.getEnterpriseId());
        if (Func.isEmpty(enterprise)) {
            throw new ServiceException("入驻企业不存在");
        }
        PropertyCustomerArchives enterpriseCustomerArchives = customerArchivesService.getCustomerArchivesById(enterprise.getCustomerArchivesId());
        if (Func.isEmpty(enterpriseCustomerArchives)) {
            throw new ServiceException("企业客户档案不存在");
        }
        enterpriseMemberVo.setEnterpriseName(enterpriseCustomerArchives.getCustomerName());

        PropertyCustomerArchives customerArchives = customerArchivesService.getCustomerArchivesById(enterpriseMemberVo.getCustomerArchivesId());
        if (Func.isEmpty(customerArchives)) {
            throw new ServiceException("企业成员客户档案不存在");
        }
        enterpriseMemberVo.setMemberName(customerArchives.getCustomerName());
        enterpriseMemberVo.setLinkPhone(customerArchives.getLinkPhoneOne());
        enterpriseMemberVo.setIdType(customerArchives.getIdType());
        enterpriseMemberVo.setIdNo(customerArchives.getIdNo());
        enterpriseMemberVo.setFacePhoto(customerArchives.getFacePhoto());
        return enterpriseMemberVo;
    }

    @Override
    public NestPage<PropertyEnterpriseMemberListVo> getEnterpriseMemberPageList(PropertyEnterpriseMemberQueryDto queryDto) {
        // 分页获取数据
        Page<PropertyEnterpriseMemberListVo> page = new Page<>(queryDto.getCurrent(), queryDto.getSize());
        page = baseMapper.getEnterpriseMemberPageList(page, queryDto);
        List<PropertyEnterpriseMemberListVo> list = page.getRecords();
        Map<Long, String> parkMap = getParkMap();
        for (PropertyEnterpriseMemberListVo vo : list) {
            vo.setParkName(parkMap.get(vo.getParkId()));
            PropertyHouseEnterprise enterprise = enterpriseService.getById(vo.getEnterpriseId());
            if (Func.isEmpty(enterprise)) {
                throw new ServiceException("所属企业不存在");
            }
            PropertyCustomerArchives enterpriseCustomerArchives = customerArchivesService.getCustomerArchivesById(enterprise.getCustomerArchivesId());
            if (Func.isEmpty(enterpriseCustomerArchives)) {
                throw new ServiceException("企业客户档案不存在");
            }
            vo.setEnterpriseName(enterpriseCustomerArchives.getCustomerName());
            R<UserDetail> userDetailR = userClient.userDetailById(vo.getCreatePeopleId());
            if (userDetailR.isSuccess() && Func.isNotEmpty(userDetailR.getData())) {
                vo.setCreatePeopleName(userDetailR.getData().getName());
            }
        }
        page.setRecords(list);
        return PageConverterUtils.convert(page);
    }

    @Override
    public PropertyEnterpriseMemberImportResVo importEnterpriseMember(MultipartFile file) {
        if (!(file.getOriginalFilename().endsWith(".xlsx") || file.getOriginalFilename().endsWith(".xls"))) {
            throw new ServiceException("请选择正确的excel文件");
        }
        PropertyEnterpriseMemberImportResVo vo = new PropertyEnterpriseMemberImportResVo();
        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(),
                    PropertyEnterpriseMemberImportExcelVo.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() - 1;
                            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);
                            PropertyEnterpriseMemberImportExcelVo importVo = (PropertyEnterpriseMemberImportExcelVo) 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(PropertyEnterpriseMemberImportExcelVo importVo, Map<String, PmgBatParkInfo> parkMap, Map<String, PropertyHouses> houseMap) {
        PropertyEnterpriseMember enterpriseMember = new PropertyEnterpriseMember();
        BeanUtils.copyProperties(importVo, enterpriseMember);
        if (Func.isBlank(importVo.getParkName())) {
            throw new ServiceException("园区不能为空");
        }
        if (Func.isBlank(importVo.getEnterpriseName())) {
            throw new ServiceException("入驻企业名称不能为空");
        }
        if (Func.isBlank(importVo.getMemberName())) {
            throw new ServiceException("人员姓名不能为空");
        }
        if (Func.isBlank(importVo.getLinkPhone())) {
            throw new ServiceException("联系电话不能为空");
        }

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

        String houseCode = importVo.getHouseCode().replaceAll("\\s*", "");
        Long houseId;
        if (houseMap.containsKey(houseCode)) {
            PropertyHouses houses = houseMap.get(houseCode);
            houseId = houses.getId();
            PropertyHousesVo propertyHousesVo = housesService.getPropertyHousesDetail(houseId);
            //拼接显示楼栋+单元+楼层+房间名称。
            enterpriseMember.setAddress(propertyHousesVo.getBuildingName() + "-" + propertyHousesVo.getUnitNum() + "-" + propertyHousesVo.getFloorNum() + "-" + propertyHousesVo.getHouseName());
        } else {
            throw new ServiceException("房间不存在");
        }
        //企业名称
        String enterprseName = importVo.getEnterpriseName();
        List<PropertyCustomerArchives> list = customerArchivesService.lambdaQuery().eq(PropertyCustomerArchives::getCustomerName, enterprseName).eq(PropertyCustomerArchives::getCustomerType, CustomerTypeEnum.ORGAN.getValue()).list();
        if (Func.isEmpty(list)) {
            throw new ServiceException("入驻企业不存在");
        }
        List<Long> idList = list.stream().map(PropertyCustomerArchives::getId).collect(Collectors.toList());
        PropertyHouseEnterprise houseEnterprise = enterpriseService.lambdaQuery().in(PropertyHouseEnterprise::getCustomerArchivesId, idList).eq(PropertyHouseEnterprise::getHouseId, houseId).one();
        if (Func.isEmpty(houseEnterprise)) {
            throw new ServiceException("入驻企业不存在");
        }
        enterpriseMember.setEnterpriseId(houseEnterprise.getId());

        ContextUser contextUser = AuthUtil.getUser();
        if (Func.isEmpty(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        //同步客户档案
        PropertyCustomerArchives customerArchives = customerArchivesService.lambdaQuery().eq(PropertyCustomerArchives::getCustomerType, CustomerTypeEnum.PERSON.getValue())
                .eq(PropertyCustomerArchives::getLinkPhoneOne, importVo.getLinkPhone()).one();
        if (Func.isNotEmpty(customerArchives)) {
            customerArchives.setIdType(2);
            if (Func.isNotEmpty(importVo.getIdNo())) customerArchives.setIdNo(importVo.getIdNo());
            customerArchives.setIsLink(YesOrNoEnum.YES.getValue());
            customerArchivesService.updateById(customerArchives);
            enterpriseMember.setCustomerArchivesId(customerArchives.getId());
        } else {
            PropertyCustomerArchives add = new PropertyCustomerArchives();
            add.setParkId(enterpriseMember.getParkId());
            add.setCustomerType(CustomerTypeEnum.PERSON.getValue());
            add.setCustomerCategory(CustomerCategoryEnum.TENANT_MEMBER.getValue());
            add.setCustomerName(importVo.getMemberName());
            add.setIdType(IdTypeEnum.ID_CARD.getValue());
            add.setIdNo(importVo.getIdNo());
            add.setLinkManOne(importVo.getMemberName());
            add.setLinkPhoneOne(importVo.getLinkPhone());
            add.setCreateType(CreateTypeEnum.AUTO_SYNC.getValue());
            add.setCreatePeopleId(contextUser.getUserDetailId());
            add.setIsLink(YesOrNoEnum.YES.getValue());
            customerArchivesService.save(add);
            enterpriseMember.setCustomerArchivesId(add.getId());
        }
        enterpriseMember.setMemberStatus(houseEnterprise.getEntryStatus() == EntryStatusEnum.ENTRY.getValue() ? MemberStatusEnum.NORMAL.getValue() : MemberStatusEnum.INVALID.getValue());
        enterpriseMember.setCreateType(CreateTypeEnum.BACK_ADD.getValue());
        enterpriseMember.setCreatePeopleId(contextUser.getUserDetailId());
        //判断企业是否存在
        LambdaQueryWrapper<PropertyEnterpriseMember> isExitQuery = Wrappers.lambdaQuery();
        isExitQuery.eq(PropertyEnterpriseMember::getParkId, enterpriseMember.getParkId());
        isExitQuery.eq(PropertyEnterpriseMember::getAddress, enterpriseMember.getAddress());
        isExitQuery.eq(PropertyEnterpriseMember::getEnterpriseId, enterpriseMember.getEnterpriseId());
        isExitQuery.eq(PropertyEnterpriseMember::getCustomerArchivesId, enterpriseMember.getCustomerArchivesId());
        PropertyEnterpriseMember isExit = this.getOne(isExitQuery);
        if (Func.isNotEmpty(isExit)) {
            removeById(isExit.getId());
        }
        this.save(enterpriseMember);
    }


    @Override
    public void exportEnterpriseMember(PropertyEnterpriseMemberQueryDto queryDto, HttpServletResponse response) {
        List<PropertyEnterpriseMemberListVo> list = baseMapper.getEnterpriseMemberList(queryDto);
        List<PropertyEnterpriseMemberExcelVo> excelVoList = BeanUtil.copyProperties(list, PropertyEnterpriseMemberExcelVo.class);
        Map<Long, String> parkMap = getParkMap();
        excelVoList.forEach(excelVo -> {
            excelVo.setParkName(parkMap.get(excelVo.getParkId()));
            PropertyHouseEnterprise enterprise = enterpriseService.getById(excelVo.getEnterpriseId());
            if (Func.isEmpty(enterprise)) {
                throw new ServiceException("所属企业不存在");
            }
            PropertyCustomerArchives enterpriseCustomerArchives = customerArchivesService.getCustomerArchivesById(enterprise.getCustomerArchivesId());
            if (Func.isEmpty(enterpriseCustomerArchives)) {
                throw new ServiceException("企业客户档案不存在");
            }
            excelVo.setEnterpriseName(enterpriseCustomerArchives.getCustomerName());
            R<UserDetail> userDetailR = userClient.userDetailById(excelVo.getCreatePeopleId());
            if (userDetailR.isSuccess() && Func.isNotEmpty(userDetailR.getData())) {
                excelVo.setCreatePeopleName(userDetailR.getData().getName());
            }
            //证件类型
            excelVo.setIdTypeName(IdTypeEnum.getDescByCode(excelVo.getIdType()));
            excelVo.setCreateTypeName(CreateTypeEnum.getDescByCode(excelVo.getCreateType()));
        });
        try {
            String fileName = URLEncoder.encode("入驻企业成员表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), PropertyEnterpriseMemberExcelVo.class)
                    .sheet("入驻企业成员表")
                    .doWrite(excelVoList); //最终处理好的数据结果集list
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }


    @Override
    public Long syncEnterpriseMember(PropertyEnterpriseMemberSyncDto syncDto) {
        PropertyEnterpriseMember enterpriseMember = BeanUtil.copyProperties(syncDto, PropertyEnterpriseMember.class);
        PropertyHouseEnterprise houseEnterprise = enterpriseService.getById(syncDto.getEnterpriseId());
        if (Func.isEmpty(houseEnterprise)) {
            throw new ServiceException("入驻企业不存在");
        }
        ContextUser contextUser = AuthUtil.getUser();
        if (Func.isEmpty(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        Long createPeopleId = contextUser.getUserDetailId();
        //同步客户档案
        PropertyCustomerArchives customerArchives = customerArchivesService.lambdaQuery().eq(PropertyCustomerArchives::getCustomerType, CustomerTypeEnum.PERSON.getValue())
                .eq(PropertyCustomerArchives::getLinkPhoneOne, syncDto.getLinkPhone()).one();
        if (Func.isEmpty(customerArchives)) {
            customerArchives = new PropertyCustomerArchives();
            customerArchives.setParkId(syncDto.getParkId());
            customerArchives.setCustomerType(CustomerTypeEnum.PERSON.getValue());
            customerArchives.setCustomerCategory(CustomerCategoryEnum.TENANT_MEMBER.getValue());
            customerArchives.setCustomerName(syncDto.getUserName());
            customerArchives.setFacePhoto(syncDto.getFacePhoto());
            customerArchives.setLinkManOne(syncDto.getUserName());
            customerArchives.setLinkPhoneOne(syncDto.getLinkPhone());
            customerArchives.setIsLink(YesOrNoEnum.YES.getValue());
            customerArchives.setCreateType(CreateTypeEnum.AUTO_SYNC.getValue());
            customerArchives.setCreatePeopleId(createPeopleId);
            customerArchivesService.save(customerArchives);
        }
        enterpriseMember.setCustomerArchivesId(customerArchives.getId());
        enterpriseMember.setMemberStatus(houseEnterprise.getEntryStatus() == EntryStatusEnum.ENTRY.getValue() ? MemberStatusEnum.NORMAL.getValue() : MemberStatusEnum.INVALID.getValue());
        enterpriseMember.setCreateType(CreateTypeEnum.AUTO_SYNC.getValue());
        enterpriseMember.setCreatePeopleId(createPeopleId);
        enterpriseMember.setRegisterStatus(RegisterStatusEnum.REGISTERED.getValue());
        save(enterpriseMember);
        return enterpriseMember.getId();
    }

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

}
