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


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.manage.system.api.entity.NestOrgUser;
import com.yuchen.saas.manage.system.api.feign.ISysClient;
import com.yuchen.saas.park.api.dto.property.PropertyOfflinePaymentProcessDto;
import com.yuchen.saas.park.api.dto.property.PropertyOfflinePaymentRecordAuditDto;
import com.yuchen.saas.park.api.dto.property.PropertyOfflinePaymentRecordQueryDto;
import com.yuchen.saas.park.api.entity.park.PmgBatParkInfo;
import com.yuchen.saas.park.api.entity.property.PropertyHouses;
import com.yuchen.saas.park.api.entity.property.PropertyOfflinePaymentRecord;
import com.yuchen.saas.park.api.enums.property.AccountBizTypeEnum;
import com.yuchen.saas.park.api.vo.property.PropertyOfflinePaymentRecordDetailVo;
import com.yuchen.saas.park.api.vo.property.PropertyOfflinePaymentRecordExcelVO;
import com.yuchen.saas.park.api.vo.property.PropertyOfflinePaymentRecordPageVo;
import com.yuchen.saas.park.service.event.property.ProcessOfflinePrePaymentEvent;
import com.yuchen.saas.park.service.mapper.property.PropertyOfflinePaymentRecordMapper;
import com.yuchen.saas.park.service.service.PmgBatParkInfoService;
import com.yuchen.saas.park.service.service.property.IPropertyOfflinePaymentRecordService;
import com.yuchen.saas.park.service.service.property.PropertyHousesService;
import org.nest.springwrap.core.excel.util.ExcelUtil;
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.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.Func;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 线下缴费记录(线下缴费审核) 服务实现类
 * </p>
 *
 * @author cxj
 * @since 2023-12-14
 */
@Service
public class PropertyOfflinePaymentRecordServiceImpl extends BaseServiceImpl<PropertyOfflinePaymentRecordMapper, PropertyOfflinePaymentRecord> implements IPropertyOfflinePaymentRecordService {

    @Resource
    private ISysClient iSysClient;

    @Resource
    private PmgBatParkInfoService  parkInfoService;
    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private PropertyHousesService housesService;

    @Override
    public NestPage<PropertyOfflinePaymentRecordPageVo> getPage(PropertyOfflinePaymentRecordQueryDto dto) {
        IPage<PropertyOfflinePaymentRecord> page = this.page(Condition.getPage(dto), buildQueryWrappers(dto));
        IPage<PropertyOfflinePaymentRecordPageVo> result=new Page<>();
        Func.copy(page,result);
        //todo hasBill是否有关联的账单要填充
        List<PropertyOfflinePaymentRecordPageVo> list= page.getRecords().stream().map(a->{
            PropertyOfflinePaymentRecordPageVo vo=  Func.copy(a, PropertyOfflinePaymentRecordPageVo.class);
            PmgBatParkInfo byId = parkInfoService.getById(vo.getParkId());
            if(Func.isNotEmpty(byId)){
                vo.setParkName(byId.getParkName());
            }
            return vo;
        }).collect(Collectors.toList());
        result.setRecords(list);
        return NestPage.of(result);
    }

    private LambdaQueryWrapper<PropertyOfflinePaymentRecord> buildQueryWrappers(PropertyOfflinePaymentRecordQueryDto dto){
        LambdaQueryWrapper<PropertyOfflinePaymentRecord> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(PropertyOfflinePaymentRecord::getParkId,dto.getParkId())
                .like(Func.isNotEmpty(dto.getCustomerName()),PropertyOfflinePaymentRecord::getCustomerName,dto.getCustomerName())
                .eq(Func.isNotEmpty(dto.getCustomerType()),PropertyOfflinePaymentRecord::getCustomerType,dto.getCustomerType())
                .like(Func.isNotEmpty(dto.getResourceCode()),PropertyOfflinePaymentRecord::getResourceCode,dto.getResourceCode())
                .like(Func.isNotEmpty(dto.getPayeeAccount()),PropertyOfflinePaymentRecord::getPayeeAccount,dto.getPayeeAccount())
                .like(Func.isNotEmpty(dto.getPayee()),PropertyOfflinePaymentRecord::getPayee,dto.getPayee())
                .eq(Func.isNotEmpty(dto.getPayType()),PropertyOfflinePaymentRecord::getPayType,dto.getPayType())
                .eq(Func.isNotEmpty(dto.getRegisterType()),PropertyOfflinePaymentRecord::getRegisterType,dto.getRegisterType())
                .between((Func.isNotEmpty(dto.getPayTimeStart())&&Func.isNotEmpty(dto.getPayTimeEnd())),PropertyOfflinePaymentRecord::getPayTime,dto.getPayTimeStart(),dto.getPayTimeEnd())
                .between((Func.isNotEmpty(dto.getCreateTimeStart())&&Func.isNotEmpty(dto.getCreateTimeEnd())),PropertyOfflinePaymentRecord::getCreateTime,dto.getCreateTimeStart(),dto.getCreateTimeEnd())
                .orderByDesc(PropertyOfflinePaymentRecord::getCreateTime);
        return queryWrapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean audit(PropertyOfflinePaymentRecordAuditDto dto) {
        PropertyOfflinePaymentRecord offlinePaymentRecord = getById(dto.getId());
        if(Func.isEmpty(offlinePaymentRecord)){
            throw new ServiceException("所选数据已不存在!");
        }
        if(Func.isNotEmpty(offlinePaymentRecord.getReviewState())&&offlinePaymentRecord.getReviewState()!=0){
            throw new ServiceException("待确认的数据才能进行操作!");
        }
        offlinePaymentRecord.setReviewState(dto.getReviewState());
        offlinePaymentRecord.setReviewTime(new Date());
        ContextUser user = AuthUtil.getUser();
        if(Func.isNotEmpty(user)){
            offlinePaymentRecord.setReviewUserId(user.getUserId());
            if(Func.isNotEmpty(user.getOrgUserId())){
                R<NestOrgUser> orgUserById = iSysClient.getOrgUserById(user.getOrgUserId());
                if(orgUserById.isSuccess()&&Func.isNotEmpty(orgUserById.getData())){
                    offlinePaymentRecord.setReviewUserName(orgUserById.getData().getName());
                }
            }
        }
        if(updateById(offlinePaymentRecord)){
            //todo 查询关联账单,对账单操作,分下面两种情况
//            if(ReviewStateEnum.PASS_THE_AUDIT.getCode().equals(dto.getReviewState())){
//                //该线下缴费申请，为已出账单。确认之后，账单状态变更为：已缴费。请确认实际已收到款项。
//                //该线下缴费申请，为临时添加账单。确认之后，系统将自动创建对应账单，同时账单状态变更为：已缴费。请确认实际已收到款项。
//            }else if(ReviewStateEnum.REFUSED.getCode().equals(dto.getReviewState())){
//                //该线下缴费申请，为已出账单。驳回之后，该账单状态恢复到：未缴费。请确认实际未收到款项。
//                //该线下缴费申请，为临时添加账单。确认之后，系统将自动创建对应账单，同时账单状态变更为：已缴费。请确认实际已收到款项。
//            }
            PropertyOfflinePaymentProcessDto processDto = new PropertyOfflinePaymentProcessDto();
            processDto.setBusinessId(offlinePaymentRecord.getBusinessId());
            processDto.setReviewState(dto.getReviewState());
            processDto.setAccountBizTypeEnum(AccountBizTypeEnum.convert(offlinePaymentRecord.getBusinessType()));
            applicationContext.publishEvent(new ProcessOfflinePrePaymentEvent(processDto));
        }
        return true;
    }

    @Override
    public void export(PropertyOfflinePaymentRecordQueryDto queryDTO, HttpServletResponse response) {
        List<PropertyOfflinePaymentRecord> list = list(buildQueryWrappers(queryDTO));
        List<PropertyOfflinePaymentRecordExcelVO> excelVO= list.stream().map(a->{
            PropertyOfflinePaymentRecordExcelVO vo=Func.copy(a, PropertyOfflinePaymentRecordExcelVO.class);
            PmgBatParkInfo byId = parkInfoService.getById(a.getParkId());
            if(Func.isNotEmpty(byId)){
                vo.setParkName(byId.getParkName());
            }
            return vo;
        }).collect(Collectors.toList());
        String fileName = URLEncoder.encode("线下缴费审核导出", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        ExcelUtil.export(response, fileName, "线下缴费审核导出", excelVO, PropertyOfflinePaymentRecordExcelVO.class);
    }

    @Override
    public PropertyOfflinePaymentRecordDetailVo getDetailById(Long id) {
        PropertyOfflinePaymentRecord byId = getById(id);
        if(Func.isEmpty(byId)){
            throw new ServiceException("所选数据已不存在!");
        }
        if(Func.isEmpty(byId.getResourceCode())){
            PropertyHouses houses = housesService.getById(byId.getHouseId());
            if(Func.isNotEmpty(houses)){
                byId.setResourceCode(houses.getResourceCode());
            }
        }
        //todo 明细关联账单列表
        return Func.copy(byId,PropertyOfflinePaymentRecordDetailVo.class);
    }

    @Override
    public Boolean add(PropertyOfflinePaymentRecord dto) {
        return save(dto);
    }

    @Override
    public void removeByBusinessId(long businessId) {
        LambdaQueryWrapper<PropertyOfflinePaymentRecord> qw = new LambdaQueryWrapper<>();
        qw.eq(PropertyOfflinePaymentRecord::getBusinessId,businessId);
        this.remove(qw);
    }
}
