package com.gree.mall.manager.logic.order;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.order.LeaseOrderBean;
import com.gree.mall.manager.bean.order.LeaseOrderVO;
import com.gree.mall.manager.commonmapper.CommonMapper;
import com.gree.mall.manager.enums.LeaseOrderStatusEnum;
import com.gree.mall.manager.enums.material.PayTypeEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class LeaseOrderLogic {

    private final CommonLogic commonLogic;
    private final CommonMapper commonMapper;
    private final LeaseOrderService leaseOrderService;
    private final LeaseOrderItemService leaseOrderItemService;
    private final LeaseOrderPayRecordService leaseOrderPayRecordService;
    private final GoodsLeaseService goodsLeaseService;
    private final PgOrderBaseService pgOrderBaseService;


    public IPage<LeaseOrderVO> page(String orderId, String goodsName, String userName, String userMobile, LeaseOrderStatusEnum status, Date startDate, Date endDate, Date startPayDate, Date endPayDate, Integer pageNum, Integer pageSize, HttpServletRequest request) {
        //获取当前登录微信企业微信id
        AdminUserCom adminUser = commonLogic.getAdminUser(request);
        List<String> companyWechatIds = adminUser.getCompanyWechatIds();

        IPage<LeaseOrderVO> page = commonMapper.leaseOrderList(new Page<>(pageNum, pageSize), orderId, goodsName, userName,
                userMobile, Objects.nonNull(status) ? status.getKey() : null, startDate, endDate, startPayDate, endPayDate, companyWechatIds);

        return page;
    }

    public LeaseOrderBean detail(String id) {
        final LeaseOrder order = leaseOrderService.getById(id);
        LeaseOrderBean bean = new LeaseOrderBean();
        BeanUtils.copyProperties(order, bean);

        final List<LeaseOrderItem> items = leaseOrderItemService.lambdaQuery()
                .eq(LeaseOrderItem::getLeaseOrderId, id)
                .list();
        bean.setItems(items);

        final List<LeaseOrderPayRecord> records = leaseOrderPayRecordService.lambdaQuery()
                .eq(LeaseOrderPayRecord::getLeaseOrderId, id)
                .eq(LeaseOrderPayRecord::getPayStatus, true)
                .list();
        bean.setRecords(records);

        final List<PgOrderBase> orderBases = pgOrderBaseService.lambdaQuery()
                .eq(PgOrderBase::getSaleOrderId, id)
                .list();

        bean.setOrderBases(orderBases);

        return bean;
    }

    @Transactional
    public void add(LeaseOrderBean bean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        if (Objects.isNull(adminUser.getAdminCompanyWechat())) {
            throw new RemoteServiceException("平台账号不能新增");
        }
        if (StringUtils.isBlank(bean.getUserName())) {
            throw new RemoteServiceException("客户名称不能为空");
        }
        if (StringUtils.isBlank(bean.getUserMobile())) {
            throw new RemoteServiceException("客户电话不能为空");
        }
        if (StringUtils.isBlank(bean.getUserAddress())
                || StringUtils.isBlank(bean.getProvince())
                || StringUtils.isBlank(bean.getArea())
                || StringUtils.isBlank(bean.getCity())
                || StringUtils.isBlank(bean.getStreet())) {
            throw new RemoteServiceException("用户地址不能为空");
        }
        if (CollectionUtil.isEmpty(bean.getItems())) {
            throw new RemoteServiceException("商品信息不能为空");
        }
        try {
            final Map<String, LeaseOrderItem> itemMap = bean.getItems().stream()
                    .collect(Collectors.toMap(LeaseOrderItem::getGoodsLeaseId, Function.identity()));
        } catch (Exception e) {
            throw new RemoteServiceException("重复商品请合并");
        }
        for (LeaseOrderItem item : bean.getItems()) {
            final String id = commonLogic.generateNo("ZP", "LEASE_ORDER", 13);
            final GoodsLease goodsLease = goodsLeaseService.getById(item.getGoodsLeaseId());
            LeaseOrder order = new LeaseOrder();
            BeanUtils.copyProperties(bean, order);
            order.setId(id)
                    .setPayStatus(true)
                    .setCompanyWechatId(adminUser.getAdminCompanyWechat().getCompanyWechatId())
                    .setCompanyWechatName(adminUser.getAdminCompanyWechat().getCompanyName())
                    .setOnLineBill(false)
                    .setBookAmount(BigDecimal.valueOf(item.getQty()).multiply(goodsLease.getDepositPrice()))
                    .setPayType(PayTypeEnum.LINE.getKey())
                    .insert();

            item.setCompanyWechatId(order.getCompanyWechatId())
                    .setCompanyWechatName(order.getCompanyWechatName())
                    .setLeaseOrderId(order.getId())
                    .setLeasePrice(goodsLease.getLeasePrice())
                    .setDepositPrice(goodsLease.getDepositPrice())
                    .insert();

            LeaseOrderBean confirmBean = new LeaseOrderBean();
            BeanUtils.copyProperties(order, confirmBean);
            confirmBean.setItems(new ArrayList<LeaseOrderItem>() {{ this.add(item); }});
            // 调确认
            this.confirm(confirmBean);
        }
    }

    @Transactional
    public void cancel(String id) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        leaseOrderService.lambdaUpdate()
                .set(LeaseOrder::getCancelBy, adminUser.getNickName())
                .set(LeaseOrder::getCancelTime, DateUtil.date())
                .set(LeaseOrder::getStatus, LeaseOrderStatusEnum.CANCEL.getKey())
                .eq(LeaseOrder::getStatus, LeaseOrderStatusEnum.WAIT.getKey())
                .eq(LeaseOrder::getId, id)
                .update();
    }

    @Transactional
    public void confirm(LeaseOrderBean bean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        final LeaseOrder oldOrder = leaseOrderService.getById(bean.getId());
        if (!oldOrder.getStatus().equals(LeaseOrderStatusEnum.WAIT.getKey())) {
            throw new RemoteServiceException("订单非“待确认”状态，请刷新页面");
        }

        final List<LeaseOrderItem> itemList = leaseOrderItemService.lambdaQuery()
                .eq(LeaseOrderItem::getLeaseOrderId, bean.getId())
                .list();

        this.handleParams(bean);

        final Map<String, LeaseOrderItem> itemMap = itemList.stream().collect(Collectors.toMap(LeaseOrderItem::getId, Function.identity()));

        // 总租金
        BigDecimal totalAmount = BigDecimal.ZERO;
        // 总押金
        BigDecimal depositAmount = BigDecimal.ZERO;
        // 总订金
        BigDecimal bookAmount = BigDecimal.ZERO;
        for (LeaseOrderItem item : bean.getItems()) {
            if (itemMap.containsKey(item.getId())) {
                final LeaseOrderItem leaseOrderItem = itemMap.get(item.getId());
                if (!oldOrder.getOnLineBill()) {
                    leaseOrderItem.setDepositPrice(item.getDepositPrice());
                }
                leaseOrderItem.setQty(item.getQty())
                        .setLeasePrice(item.getLeasePrice())
                        .setStartDate(item.getStartDate())
                        .setEndDate(item.getEndDate())
                        .setDepositAmount(item.getDepositAmount())
                        .setRenewalPrice(item.getRenewalPrice())
                        .setLeaseAmount(item.getLeaseAmount())
                        .setLeaseDay(item.getLeaseDay());

                totalAmount = totalAmount.add(item.getLeaseAmount());
                depositAmount = depositAmount.add(item.getDepositAmount());
                bookAmount = bookAmount.add(leaseOrderItem.getDepositPrice().multiply(BigDecimal.valueOf(leaseOrderItem.getQty())));
            }
        }

        oldOrder.setStatus(LeaseOrderStatusEnum.WAIT_START.getKey());

        final DateTime curTimeDate = DateUtil.parseDate(DateUtil.formatDate(DateUtil.date()));
        if (!bean.getItems().get(0).getStartDate().after(curTimeDate) || bean.getItems().get(0).getStartDate().getTime() == curTimeDate.getTime()) {
            oldOrder.setStatus(LeaseOrderStatusEnum.LEASE.getKey());
        }

        if (!oldOrder.getOnLineBill()) {
            oldOrder.setBookAmount(bookAmount);

            LeaseOrderPayRecord record = new LeaseOrderPayRecord();
            record.setLeaseOrderId(oldOrder.getId())
                    .setCompanyWechatId(oldOrder.getCompanyWechatId())
                    .setCompanyWechatName(oldOrder.getCompanyWechatName())
                    .setPayTime(DateUtil.date())
                    .setPayValue(BigDecimal.ZERO)
                    .setOrderType("FIRST")
                    .setStartDate(itemList.get(0).getStartDate())
                    .setEndDate(itemList.get(0).getEndDate())
                    .setPayStatus(true)
                    .setSort(1)
                    .insert();
        } else {
            LeaseOrderPayRecord record = leaseOrderPayRecordService.lambdaQuery()
                    .eq(LeaseOrderPayRecord::getLeaseOrderId, oldOrder.getId())
                    .eq(LeaseOrderPayRecord::getOrderType, "FIRST")
                    .eq(LeaseOrderPayRecord::getPayStatus, true)
                    .one();
            if (Objects.isNull(record)) {
                throw new RemoteServiceException("线上订单，初次租赁记录为空，数据异常");
            }
            if (record.getStartDate().compareTo(itemList.get(0).getStartDate()) != 0
                    || record.getEndDate().compareTo(itemList.get(0).getStartDate()) != 0) {
                record.setStartDate(itemList.get(0).getStartDate())
                        .setEndDate(itemList.get(0).getEndDate())
                        .updateById();
            }
        }

        oldOrder.setUserName(bean.getUserName())
                .setUserMobile(bean.getUserMobile())
                .setProvinceId(bean.getProvinceId())
                .setProvince(bean.getProvince())
                .setAreaId(bean.getAreaId())
                .setArea(bean.getArea())
                .setCityId(bean.getCityId())
                .setCity(bean.getCity())
                .setStreetId(bean.getStreetId())
                .setStreet(bean.getStreet())
                .setUserAddress(bean.getUserAddress())
                .setTotalAmount(totalAmount)
                .setDepositAmount(depositAmount)
                .setFileUrl(bean.getFileUrl())
                .setConfirmBy(adminUser.getNickName())
                .setConfirmTime(DateUtil.date());

        oldOrder.updateById();
        leaseOrderItemService.saveOrUpdateBatch(itemList);
    }

    private void handleParams(LeaseOrderBean bean) {
        if (StringUtils.isBlank(bean.getUserName())) {
            throw new RemoteServiceException("客户名称不能为空");
        }
        if (StringUtils.isBlank(bean.getUserMobile())) {
            throw new RemoteServiceException("客户电话不能为空");
        }
        if (StringUtils.isBlank(bean.getUserAddress())) {
            throw new RemoteServiceException("用户地址不能为空");
        }
        if (StringUtils.isBlank(bean.getFileUrl())) {
            throw new RemoteServiceException("租赁合同不能为空");
        }
        if (CollectionUtil.isEmpty(bean.getItems())) {
            throw new RemoteServiceException("租赁商品不能为空");
        }
        for (LeaseOrderItem item : bean.getItems()) {
            if (Objects.isNull(item.getDepositPrice())) {
                throw new RemoteServiceException("订金不能为空");
            }
            if (Objects.isNull(item.getLeasePrice())) {
                throw new RemoteServiceException("租价不能为空");
            }
            if (Objects.isNull(item.getQty()) || item.getQty() <= 0) {
                throw new RemoteServiceException("数量不能少于0");
            }
            if (Objects.isNull(item.getStartDate())) {
                throw new RemoteServiceException("起租日期不能为空");
            }
            if (Objects.isNull(item.getEndDate())) {
                throw new RemoteServiceException("到期日期不能为空");
            }
            final DateTime curTimeDate = DateUtil.parseDate(DateUtil.formatDate(DateUtil.date()));
            if (item.getEndDate().getTime() < curTimeDate.getTime()) {
                throw new RemoteServiceException("到期日期必须大于或等于当前日期");
            }
            if (item.getStartDate().getTime() > item.getEndDate().getTime()) {
                throw new RemoteServiceException("起租日期不能大于到期日期");
            }
            if (Objects.isNull(item.getDepositAmount())) {
                throw new RemoteServiceException("押金不能为为空");
            }
            if (Objects.isNull(item.getRenewalPrice())) {
                throw new RemoteServiceException("续期单价不能为为空");
            }
            long leaseDay = DateUtil.betweenDay(item.getStartDate(), item.getEndDate(), true) + 1;
            // 总租金=数量*租价/30天*（到期日期-起租日期）
            BigDecimal leaseAmount = BigDecimal.valueOf(item.getQty())
                    .multiply(item.getLeasePrice())
                    .divide(BigDecimal.valueOf(30L), 2, BigDecimal.ROUND_HALF_UP)
                    .multiply(BigDecimal.valueOf(leaseDay));

            leaseAmount = leaseAmount.compareTo(BigDecimal.ZERO) <= 0 ? item.getLeasePrice().multiply(BigDecimal.valueOf(leaseDay)) : leaseAmount;

            leaseAmount = leaseAmount.compareTo(BigDecimal.ZERO) <= 0 ? item.getLeasePrice() : leaseAmount;

            item.setLeaseAmount(leaseAmount);
            item.setLeaseDay(Math.toIntExact(leaseDay));
        }
    }


    @Transactional
    public void recover(String id, Date realEndDate) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        final LeaseOrder order = leaseOrderService.getById(id);
        String curStatus = LeaseOrderStatusEnum.LEASE.getKey() + "|" + LeaseOrderStatusEnum.OVER.getKey();
        if (!curStatus.contains(order.getStatus())) {
            throw new RemoteServiceException("租赁订单非“租赁中”或“已到期,待回收”状态，确定回收失败");
        }
        leaseOrderService.lambdaUpdate()
                .set(LeaseOrder::getRecoverBy, adminUser.getNickName())
                .set(LeaseOrder::getRecoverTime, DateUtil.date())
                .set(LeaseOrder::getRecoverMobile, adminUser.getLinkPhone())
                .set(LeaseOrder::getStatus, LeaseOrderStatusEnum.RECOVER.getKey())
                .eq(LeaseOrder::getId, id)
                .update();
        leaseOrderItemService.lambdaUpdate()
                .set(LeaseOrderItem::getRealEndDate, realEndDate)
                .eq(LeaseOrderItem::getLeaseOrderId, id)
                .update();
    }

    @Transactional
    public void renewal(String id, Date realEndDate) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        final LeaseOrder order = leaseOrderService.getById(id);
        final LeaseOrderItem item = leaseOrderItemService.lambdaQuery()
                .eq(LeaseOrderItem::getLeaseOrderId, id)
                .last("limit 1")
                .one();
        String curStatus = LeaseOrderStatusEnum.LEASE.getKey() + "|" + LeaseOrderStatusEnum.OVER.getKey();
        if (!curStatus.contains(order.getStatus())) {
            throw new RemoteServiceException("租赁订单非“租赁中”或“已到期,待回收”状态，续期失败");
        }

        if (Objects.nonNull(item.getRealEndDate()) && item.getRealEndDate().after(DateUtil.date())) {
            throw new RemoteServiceException("上次续租日期未到期，请到期后操作");
        }

        Date useEndDate = Objects.isNull(item.getRealEndDate()) ? item.getEndDate() : item.getRealEndDate();
        if (realEndDate.getTime() <= useEndDate.getTime()) {
            throw new RemoteServiceException("实际到期日期必须大于到期日期");
        }
        // 续租总租金=数量*续租单价/30天*（实际到期日期-到期日期）
        long leaseDay = DateUtil.betweenDay(useEndDate, realEndDate, true);
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal renewalLeaseAmount = BigDecimal.ZERO;

        totalAmount = BigDecimal.valueOf(item.getQty())
                .multiply(item.getRenewalPrice())
                .divide(BigDecimal.valueOf(30L), 2, BigDecimal.ROUND_HALF_UP)
                .multiply(BigDecimal.valueOf(leaseDay));

        totalAmount = totalAmount.compareTo(BigDecimal.ZERO) <= 0 ? item.getRenewalPrice().multiply(BigDecimal.valueOf(leaseDay)) : totalAmount;

        totalAmount = totalAmount.compareTo(BigDecimal.ZERO) <= 0 ? item.getRenewalPrice() : totalAmount;

        renewalLeaseAmount = totalAmount;

        totalAmount = totalAmount.add(order.getTotalAmount());
        leaseOrderService.lambdaUpdate()
                .set(LeaseOrder::getUpdateBy, adminUser.getNickName())
                .set(LeaseOrder::getUpdateTime, DateUtil.date())
                .set(order.getStatus().equals(LeaseOrderStatusEnum.OVER.getKey()), LeaseOrder::getStatus, LeaseOrderStatusEnum.LEASE.getKey())
                .set(LeaseOrder::getTotalAmount, totalAmount)
                .eq(LeaseOrder::getId, id)
                .update();

        leaseOrderItemService.lambdaUpdate()
                .set(LeaseOrderItem::getRenewalLeaseAmount, renewalLeaseAmount)
                .set(LeaseOrderItem::getRealEndDate, realEndDate)
                .set(LeaseOrderItem::getLeaseDay, item.getLeaseDay() + leaseDay)
                .eq(LeaseOrderItem::getId, item.getId())
                .update();
        final Integer count = leaseOrderPayRecordService.lambdaQuery()
                .eq(LeaseOrderPayRecord::getLeaseOrderId, id)
                .count();
        LeaseOrderPayRecord record = new LeaseOrderPayRecord();
        record.setLeaseOrderId(order.getId())
                .setCompanyWechatId(order.getCompanyWechatId())
                .setCompanyWechatName(order.getCompanyWechatName())
                .setPayStatus(true)
                .setOrderType("RENEWAL")
                .setStartDate(DateUtil.offsetDay(useEndDate, 1))
                .setEndDate(realEndDate)
                .setSort(count)
                .setRenewalPrice(item.getRenewalPrice())
                .insert();
    }

    public BigDecimal computeAmount(Boolean isRenewal, Date startDate, Date endDate, BigDecimal qty, BigDecimal price) {
        long leaseDay = DateUtil.betweenDay(startDate, endDate, true);
        if (!isRenewal) {
            leaseDay++;
        }
        BigDecimal amount = qty.multiply(price)
                .divide(BigDecimal.valueOf(30L), 2, BigDecimal.ROUND_HALF_UP)
                .multiply(BigDecimal.valueOf(leaseDay));

        amount = amount.compareTo(BigDecimal.ZERO) <= 0 ? price.multiply(BigDecimal.valueOf(leaseDay)) : amount;

        return amount.compareTo(BigDecimal.ZERO) <= 0 ? price : amount;
    }
}
