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

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.thinkunion.park.service.common.enums.parking.ReviewStateEnum;
import com.yuchen.saas.park.api.dto.property.*;
import com.yuchen.saas.park.api.entity.property.*;
import com.yuchen.saas.park.api.enums.property.CreateBillTypeEnum;
import com.yuchen.saas.park.api.enums.property.DepositStatusEnum;
import com.yuchen.saas.park.api.enums.property.YesOrNoEnum;
import com.yuchen.saas.park.service.event.property.NotifyOfflinePaymentEvent;
import com.yuchen.saas.park.service.event.property.ProcessOfflinePrePaymentEvent;
import com.yuchen.saas.park.service.event.property.SetCustomerInfoEvent;
import com.yuchen.saas.park.service.event.property.SetHouseNameResourceCodeEvent;
import com.yuchen.saas.park.service.service.property.*;
import com.yuchen.saas.park.service.service.property.bill.PropertyBillFactoryService;
import com.yuchen.saas.park.service.service.property.bill.PropertyBillSearchService;
import com.yuchen.saas.park.service.service.property.bill.PropertyBillService;
import org.nest.springwrap.core.tool.utils.Func;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Service
public class OfflinePaymentEventListener {
    @Resource
    private IPropertyOfflinePaymentRecordService offlinePaymentRecordService;
    @Resource
    private ApplicationContext applicationContext;
    @Resource
    private PropertyCashierOfflineDetailService cashierOfflineDetailService;
    @Resource
    private PropertyTemporaryChargesDetailService propertyTemporaryChargesDetailService;
    @Resource
    private PropertyBillSearchService propertyBillSearchService;
    @Resource
    private PropertyBillService propertyBillService;
    @Resource
    private PropertyBillFactoryService propertyBillFactoryService;
    @Resource
    private PropertyBusinessChargesDetailService propertyBusinessChargesDetailService;
    @Resource
    private PropertyPrepaymentService propertyPrepaymentService;
    @Resource
    private PropertyBusinessChargesService propertyBusinessChargesService;
    @Resource
    private PropertyDepositService propertyDepositService;
    @Resource
    private PropertyDepositHouseService propertyDepositHouseService;

    @EventListener
    public void addOfflinePaymentEvent(NotifyOfflinePaymentEvent event) {
        PropertyOfflinePaymentRecordDto dto = (PropertyOfflinePaymentRecordDto) event.getSource();
        PropertyOfflinePaymentRecord record = new PropertyOfflinePaymentRecord();
        record.setParkId(dto.getParkId());
        record.setHouseId(dto.getHouseId());
        record.setCustomerId(dto.getCustomerId());
        record.setReceivableAmtFen(dto.getReceivableAmtFen());
        record.setPayAmtFen(dto.getPayAmtFen());
        record.setPayUser(dto.getPayUser());
        record.setPayAccount(dto.getPayAccount());
        record.setPayTime(dto.getRecordTime());
        record.setPayType(dto.getPayType());
        record.setPayee(dto.getReceiveUser());
        record.setPayeeAccount(dto.getReceiveAccount());
        record.setPayeeTime(new Date());
        record.setPayeeOrder(dto.getTransactionNum());
        record.setPayeeFile(dto.getFilePath());
        record.setRemark(dto.getRemark());
        record.setRegisterType(1);//登记方式:1管理员登记,2租客登记
        record.setBusinessType(dto.getAccountBizType());
        record.setBusinessId(dto.getRetraceId());

        List<PropertyOfflinePaymentRecord> dataList = new ArrayList<>();
        dataList.add(record);

        applicationContext.publishEvent(new SetCustomerInfoEvent(dataList,List.of(record.getCustomerId())));
        applicationContext.publishEvent(new SetHouseNameResourceCodeEvent(dataList,List.of(record.getHouseId())));

        offlinePaymentRecordService.add(record);

        // 账单锁住审核状态
        if (Func.isNotEmpty(dto.getLockProcessBillIdList())) {
            propertyBillService.lockProcess(dto.getLockProcessBillIdList());
        }

    }


    @EventListener
    public void processOfflinePrePaymentEvent(ProcessOfflinePrePaymentEvent event) {
        PropertyOfflinePaymentProcessDto dto = (PropertyOfflinePaymentProcessDto) event.getSource();
        List<Long> billIdList = new ArrayList<>();
        if (ReviewStateEnum.PASS_THE_AUDIT.getCode().equals(dto.getReviewState())) { // 线下收款审核通过
            switch (dto.getAccountBizTypeEnum()) {
                case CASHIER_OFFLINE:
                    List<PropertyCashierOfflineDetail> OfflineDetails = cashierOfflineDetailService.listDetail(dto.getBusinessId());
                    OfflineDetails.forEach(detail -> {
                        propertyBillService.pay(detail.getBillId(),detail.getNoPayAmtFen());
                        billIdList.add(detail.getBillId());
                    });
                    break;
                case PREPAYMENT:
                    LambdaUpdateWrapper<PropertyPrepayment> uw = new LambdaUpdateWrapper<>();
                    uw.eq(PropertyPrepayment::getId,dto.getBusinessId());
                    uw.set(PropertyPrepayment::getStatus, YesOrNoEnum.YES.getValue());
                    propertyPrepaymentService.update(uw);
                    break;
                case DEPOSIT:
                    PropertyDeposit deposit = propertyDepositService.getById(dto.getBusinessId());
                    CreateBillDto createBillDto = CreateBillDto.create();
                    PropertyDepositCreateBillDto depositCreateBillDto = new PropertyDepositCreateBillDto();
                    BeanUtil.copyProperties(deposit,depositCreateBillDto);
                    depositCreateBillDto.setDepositId(deposit.getId());
                    List<Long> houseIdList = propertyDepositHouseService.listHouseId(dto.getBusinessId());
                    if (Func.isNotEmpty(houseIdList) && houseIdList.size() == 1) {
                        depositCreateBillDto.setHouseId(houseIdList.get(0));
                    }
                    createBillDto.setDepositCreateBillDto(depositCreateBillDto);
                    createBillDto.setCreateBillTypeEnum(CreateBillTypeEnum.DEPOSIT);
                    propertyBillFactoryService.createBill(createBillDto);

                    propertyBillSearchService.listBillByRetraceId(dto.getBusinessId()).forEach(bill-> {
                        propertyBillService.pay(bill.getId(),bill.getNoPayAmtFen()); // 账单缴费
                    });

                    deposit.setDepositStatus(DepositStatusEnum.PAID.getValue());
                    propertyDepositService.updateById(deposit);
                    break;
                case TEMPORARY:
                    List<PropertyTemporaryChargesDetail> tempDetails = propertyTemporaryChargesDetailService
                            .lambdaQuery().eq(PropertyTemporaryChargesDetail::getTemporaryChargesId,dto.getBusinessId()).list();
                    List<PropertyTempBillCreateDto> tempList = BeanUtil.copyToList(tempDetails,PropertyTempBillCreateDto.class);

                    CreateBillDto tempCreateBillDto = new CreateBillDto();
                    tempCreateBillDto.setTempBillCreateDtoList(tempList);
                    tempCreateBillDto.setCreateBillTypeEnum(CreateBillTypeEnum.TEMPORARY);
                    propertyBillFactoryService.createBill(tempCreateBillDto); // 生成账单

                    propertyBillSearchService.listBillByRetraceId(dto.getBusinessId()).forEach(bill-> {
                        propertyBillService.pay(bill.getId(),bill.getNoPayAmtFen()); // 账单缴费
                    });

                    break;
                case BUSINESS:
                    List<PropertyBusinessChargesDetail> busiDetailList = propertyBusinessChargesDetailService
                            .lambdaQuery().eq(PropertyBusinessChargesDetail::getBusinessChargesId,dto.getBusinessId()).list();
                    List<PropertyBusinessCreateBillDto> busiList = BeanUtil.copyToList(busiDetailList,PropertyBusinessCreateBillDto.class);

                    CreateBillDto busiCreateBillDto = new CreateBillDto();
                    busiCreateBillDto.setBusinessCreateBillDtoList(busiList);
                    busiCreateBillDto.setCreateBillTypeEnum(CreateBillTypeEnum.BUSINESS);
                    propertyBillFactoryService.createBill(busiCreateBillDto); // 生成账单

                    propertyBillSearchService.listBillByRetraceId(dto.getBusinessId()).forEach(bill-> {
                        propertyBillService.pay(bill.getId(),bill.getNoPayAmtFen()); // 账单缴费
                    });
                    LambdaUpdateWrapper<PropertyBusinessCharges> bcUw = new LambdaUpdateWrapper<>();
                    bcUw.eq(PropertyBusinessCharges::getId,dto.getBusinessId());
                    bcUw.set(PropertyBusinessCharges::getStatus, DepositStatusEnum.PAID.getValue());
                    propertyBusinessChargesService.update(bcUw);
                    break;

            }
        } else if (ReviewStateEnum.REFUSED.getCode().equals(dto.getReviewState())) { // 线下收款审核不通过
            switch (dto.getAccountBizTypeEnum()) {
                case DEPOSIT:
                    PropertyDeposit deposit = propertyDepositService.getById(dto.getBusinessId());
                    deposit.setDepositStatus(DepositStatusEnum.REJECTED.getValue());
                    propertyDepositService.updateById(deposit);
                    break;
                case BUSINESS:
                    LambdaUpdateWrapper<PropertyBusinessCharges> bcUw = new LambdaUpdateWrapper<>();
                    bcUw.eq(PropertyBusinessCharges::getId,dto.getBusinessId());
                    bcUw.set(PropertyBusinessCharges::getStatus, DepositStatusEnum.REJECTED.getValue());
                    propertyBusinessChargesService.update(bcUw);
                    break;
            }
        }

        // 账单解除审核状态
        if (Func.isNotEmpty(billIdList)) {
            propertyBillService.releaseProcess(billIdList);
        }

    }

}
