package com.leromro.core.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leromro.common.core.domain.entity.SysDept;
import com.leromro.common.core.domain.entity.SysUser;
import com.leromro.common.enums.ApplicantTypeEnum;
import com.leromro.common.enums.AreaSettlementStatusEnum;
import com.leromro.common.enums.AuditorStatusEnum;
import com.leromro.common.enums.ServiceCentreSettlementStatusEnum;
import com.leromro.common.exception.ServiceException;
import com.leromro.common.utils.PageUtils;
import com.leromro.common.utils.SecurityUtils;
import com.leromro.core.domain.OrderSettlementApplication;
import com.leromro.core.domain.SecondOrder;
import com.leromro.core.domain.dto.*;
import com.leromro.core.domain.vo.OrderSettlementApplicationDetailVO;
import com.leromro.core.domain.vo.OrderSettlementApplicationListVO;
import com.leromro.core.mapper.OrderSettlementApplicationMapper;
import com.leromro.core.service.IMainOrderService;
import com.leromro.core.service.IOrderSettlementApplicationService;
import com.leromro.core.service.ISecondOrderService;
import com.leromro.system.service.ISysDeptService;
import com.leromro.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单费用结算申请Service业务层处理
 * 
 * @author lsd
 * @date 2025-05-13
 */
@Service
public class OrderSettlementApplicationServiceImpl extends ServiceImpl<OrderSettlementApplicationMapper, OrderSettlementApplication> implements IOrderSettlementApplicationService
{
    @Autowired
    private OrderSettlementApplicationMapper orderSettlementApplicationMapper;
    @Autowired
    private ISysDeptService iSysDeptService;
    @Autowired
    private ISysUserService iSysUserService;
    @Autowired
    private IMainOrderService iMainOrderService;
    @Autowired
    private ISecondOrderService iSecondOrderService;

    /**
     * 查询订单费用结算申请
     * 
     * @param id 订单费用结算申请主键
     * @return 订单费用结算申请
     */
    @Override
    public OrderSettlementApplicationDetailVO selectOrderSettlementApplicationById(Long id)
    {
        return orderSettlementApplicationMapper.selectOrderSettlementApplicationById(id);
    }

    /**
     * 查询订单费用结算申请列表
     * 
     * @param orderSettlementApplicationListDTO 订单费用结算申请
     * @return 订单费用结算申请
     */
    @Override
    public List<OrderSettlementApplicationListVO> selectOrderSettlementApplicationList(OrderSettlementApplicationListDTO orderSettlementApplicationListDTO)
    {
        // 获取当前用户部门id
        Long deptId = SecurityUtils.getDeptId();
        // 获取当前用户部门类型
        String areaType = SecurityUtils.getAreaType();
        // 查询参数拷贝
        AuthOrderSettlementApplicationListDTO authOrderSettlementApplicationListDTO = BeanUtil.copyProperties(orderSettlementApplicationListDTO, AuthOrderSettlementApplicationListDTO.class);
        // 根据部门类型做数据权限控制
        if("3".equals(areaType)){
            // 仅查询区域下级服务中心
            // 获取下级所有服务中心id
            List<SysDept> sysDeptList = iSysDeptService.selectDeptByParentId(deptId,"4");
            authOrderSettlementApplicationListDTO.setDeptIds(sysDeptList.stream().map(SysDept::getDeptId).collect(Collectors.toList()));
        }else if("0".equals(areaType)){
            // 仅查询平台下级区域公司
            // 获取下级所有区域公司id
            List<SysDept> sysDeptList = iSysDeptService.selectDeptByParentId(deptId,"3");
            authOrderSettlementApplicationListDTO.setDeptIds(sysDeptList.stream().map(SysDept::getDeptId).collect(Collectors.toList()));
        }
        PageUtils.startPage();
        PageUtils.orderBy("a.application_time desc");
        return orderSettlementApplicationMapper.selectOrderSettlementApplicationList(authOrderSettlementApplicationListDTO);
    }

    /**
     * 新增订单费用结算申请
     * 
     * @param orderSettlementApplication 订单费用结算申请
     * @return 结果
     */
    @Override
    public Boolean insertOrderSettlementApplication(OrderSettlementApplication orderSettlementApplication)
    {
        return this.save(orderSettlementApplication);
    }

    /**
     * 修改订单费用结算申请
     * 
     * @param orderSettlementApplication 订单费用结算申请
     * @return 结果
     */
    @Override
    public Boolean updateOrderSettlementApplication(OrderSettlementApplication orderSettlementApplication)
    {
        return this.updateById(orderSettlementApplication);
    }

    /**
     * 批量删除订单费用结算申请
     * 
     * @param ids 需要删除的订单费用结算申请主键
     * @return 结果
     */
    @Override
    public int deleteOrderSettlementApplicationByIds(Long[] ids)
    {
        return orderSettlementApplicationMapper.deleteOrderSettlementApplicationByIds(ids);
    }

    /**
     * 删除订单费用结算申请信息
     * 
     * @param id 订单费用结算申请主键
     * @return 结果
     */
    @Override
    public int deleteOrderSettlementApplicationById(Long id)
    {
        return orderSettlementApplicationMapper.deleteOrderSettlementApplicationById(id);
    }

    @Override
    @Transactional
    public void updateAuditorStatus(Long id, Integer status) {
        this.update(new LambdaUpdateWrapper<OrderSettlementApplication>()
                .set(OrderSettlementApplication::getAuditorStatus, status)
                .eq(OrderSettlementApplication::getId, id)
        );
    }

    @Override
    @Transactional
    public void cancelPendingRecord(List<Long> secondOrderIds) {
        this.update(new LambdaUpdateWrapper<OrderSettlementApplication>()
                .set(OrderSettlementApplication::getAuditorStatus, AuditorStatusEnum.CANCEL.getCode())
                .eq(OrderSettlementApplication::getAuditorStatus, AuditorStatusEnum.AUDITING.getCode())
                .in(OrderSettlementApplication::getOrderId, secondOrderIds)
        );
    }

    @Override
    @Transactional
    public void applyOrderSettlement(SettlementOrderApplyDTO settlementOrderApplyDTO) {
        // 获取当前用户id
        Long userId = SecurityUtils.getUserId();
        // 获取用户信息
        SysUser sysUser = iSysUserService.selectUserById(userId);

        // 获取用户归属部门id（区域公司/服务中心id）
        Long deptId = sysUser.getDeptId();
        if(deptId == null){
            throw new ServiceException("用户没有归属部门");
        }
        // 获取部门信息
        SysDept sysDept = iSysDeptService.selectDeptById(deptId);
        String areaType = sysDept.getAreaType();

        // 获取结算订单信息
        List<SecondOrder> settlementOrderList = iSecondOrderService.list(new LambdaQueryWrapper<SecondOrder>().in(SecondOrder::getSecondOrderId, settlementOrderApplyDTO.getSecondOrderIds()));
        if(CollUtil.isEmpty(settlementOrderList)){
            throw new ServiceException("结算订单不存在");
        }

        // 检查是否存在不能做申请结算操作的订单
        for (SecondOrder settlementOrder : settlementOrderList) {
            // 检查是否存在未完成订单
            if(!"4".equals(settlementOrder.getOrderStatus())){
                throw new ServiceException("存在未完成订单，不能申请结算");
            }

            // 如果订单结算状态不是待结算状态,或审核未通过，则不能申请结算
            if("3".equals(areaType)){
                if(!AreaSettlementStatusEnum.PENDING_SETTLEMENT.getCode().equals(settlementOrder.getAreaSettlementStatus())
                        && !AreaSettlementStatusEnum.REJECTED.getCode().equals(settlementOrder.getAreaSettlementStatus())){
                    throw new ServiceException("订单不能重复申请结算");
                }
            }
            if("4".equals(areaType)){
                if(!ServiceCentreSettlementStatusEnum.PENDING_SETTLEMENT.getCode().equals(settlementOrder.getServiceCentreSettlementStatus())
                        && !ServiceCentreSettlementStatusEnum.REJECTED.getCode().equals(settlementOrder.getServiceCentreSettlementStatus())){
                    throw new ServiceException("订单不能重复申请结算");
                }
            }
        }

        // 取消订单之前正在审核中的结算申请记录
        this.cancelPendingRecord(settlementOrderApplyDTO.getSecondOrderIds());

        // 新增订单结算申请记录
        List<OrderSettlementApplication> orderSettlementApplicationList = new ArrayList<>();
        for (SecondOrder settlementOrder : settlementOrderList) {
            OrderSettlementApplication orderSettlementApplication = OrderSettlementApplication.builder()
                    .orderId(settlementOrder.getSecondOrderId())
                    .applicantType(ApplicantTypeEnum.getCodeByAreaType(areaType))
                    .applicantId(deptId)
                    .amount(getDistributionAmount(areaType, settlementOrder))
                    .applicationUserId(userId)
                    .applicationTime(new Date())
                    .payeeMethod(settlementOrderApplyDTO.getPayeeMethod())
                    .payeeAccount(settlementOrderApplyDTO.getPayeeAccount())
                    .payeeBankName(settlementOrderApplyDTO.getPayeeBankName())
                    .payeeName(settlementOrderApplyDTO.getPayeeName())
                    .payeeRemark(settlementOrderApplyDTO.getPayeeRemark())
                    .build();
            orderSettlementApplicationList.add(orderSettlementApplication);
        }
        this.saveBatch(orderSettlementApplicationList);

        // 变更订单结算状态
        if("3".equals(areaType)){
            iSecondOrderService.updateAreaSettlementInfo(settlementOrderApplyDTO);
        }else if("4".equals(areaType)){
            iSecondOrderService.updateServiceCentreSettlementInfo(settlementOrderApplyDTO);
        }
    }

    @Override
    @Transactional
    public void auditorOrderSettlement(SettlementOrderAuditorDTO settlementOrderAuditorDTO) {
        // 如果审核不通过，则审核备注必须填写
        if(AuditorStatusEnum.AUDIT_NOT_PASS.getCode().equals(settlementOrderAuditorDTO.getAuditorStatus())
                && StrUtil.isBlank(settlementOrderAuditorDTO.getAuditorRemark())){
            throw new ServiceException("审核不通过，审核备注必须填写");
        }

        // 获取当前用户id
        Long userId = SecurityUtils.getUserId();
        // 获取用户信息
        SysUser sysUser = iSysUserService.selectUserById(userId);

        // 获取用户归属部门id（区域公司/服务中心id）
        Long deptId = sysUser.getDeptId();
        if(deptId == null){
            throw new ServiceException("用户没有归属部门");
        }
        // 获取部门信息
        SysDept sysDept = iSysDeptService.selectDeptById(deptId);
        String areaType = sysDept.getAreaType();

        // 获取所有的申请记录
        List<OrderSettlementApplication> orderSettlementApplicationList = this.list(new LambdaQueryWrapper<OrderSettlementApplication>()
                .in(OrderSettlementApplication::getId, settlementOrderAuditorDTO.getIds()));
        if(CollUtil.isEmpty(orderSettlementApplicationList)){
            throw new ServiceException("申请记录不存在");
        }
        // 检查是否所有记录都是待审核状态
        if(!orderSettlementApplicationList.stream().allMatch(
                orderSettlementApplication -> AuditorStatusEnum.AUDITING.getCode().equals(orderSettlementApplication.getAuditorStatus()))){
            throw new ServiceException("存在非审核中的申请记录，不能操作审核");
        }

        // 更新订单结算申请记录
        this.update(new LambdaUpdateWrapper<OrderSettlementApplication>()
                .set(OrderSettlementApplication::getAuditorUserId, userId)
                .set(OrderSettlementApplication::getAuditorStatus, settlementOrderAuditorDTO.getAuditorStatus())
                .set(OrderSettlementApplication::getAuditorRemark, settlementOrderAuditorDTO.getAuditorRemark())
                .set(OrderSettlementApplication::getAuditorTime, new Date())
                .in(OrderSettlementApplication::getId, settlementOrderAuditorDTO.getIds())
        );

        // 获取所有审核记录对应的订单id
        List<Long> secondOrderIds = orderSettlementApplicationList.stream().map(OrderSettlementApplication::getOrderId).collect(Collectors.toList());

        // 更新区域/服务中心结算状态,当前是平台，则默认结算的是区域，当前如果是区域公司，默认结算的是服务中心
        if("0".equals(areaType)){
            iSecondOrderService.updateAreaSettlementStatus(secondOrderIds
                    , AuditorStatusEnum.AUDIT_PASS.getCode().equals(settlementOrderAuditorDTO.getAuditorStatus())? AreaSettlementStatusEnum.PENDING_PAYMENT.getCode() : AreaSettlementStatusEnum.REJECTED.getCode());
        }else if("3".equals(areaType)){
            iSecondOrderService.updateServiceCentreSettlementStatus(secondOrderIds
                    , AuditorStatusEnum.AUDIT_PASS.getCode().equals(settlementOrderAuditorDTO.getAuditorStatus())? ServiceCentreSettlementStatusEnum.PENDING_PAYMENT.getCode() : ServiceCentreSettlementStatusEnum.REJECTED.getCode());
        }
    }

    /**
     * 获取抽成金额
     * @param areaType
     * @param settlementOrder
     * @return
     */
    private BigDecimal getDistributionAmount(String areaType, SecondOrder settlementOrder) {
        BigDecimal distributionAmount = BigDecimal.ZERO;
        // 区域公司抽成
        if("3".equals(areaType)){
            distributionAmount = settlementOrder.getAreaDistributionAmount();
        }
        // 服务中心抽成
        if("4".equals(areaType)){
            distributionAmount = settlementOrder.getServiceCentreDistributionAmount();
        }
        return distributionAmount;
    }
}
