package com.openhis.administration.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
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.core.common.exception.ServiceException;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.StringUtils;
import com.openhis.administration.domain.ChargeItem;
import com.openhis.administration.domain.ChargeItemDefinition;
import com.openhis.administration.dto.ChargeItemBaseInfoDto;
import com.openhis.administration.dto.ChargeItemDefInfo;
import com.openhis.administration.mapper.ChargeItemDefinitionMapper;
import com.openhis.administration.mapper.ChargeItemMapper;
import com.openhis.administration.service.IChargeItemService;
import com.openhis.common.enums.ChargeItemContext;
import com.openhis.common.enums.ChargeItemStatus;
import com.openhis.common.enums.DelFlag;

import lombok.AllArgsConstructor;

/**
 * 费用项管理Service业务层处理
 *
 * @author system
 * @date 2025-02-20
 */
@Service
@AllArgsConstructor
public class ChargeItemServiceImpl extends ServiceImpl<ChargeItemMapper, ChargeItem> implements IChargeItemService {

    @Autowired
    ChargeItemDefinitionMapper chargeItemDefinitionMapper;

    /**
     * 创建已计费的采购账单
     *
     * @param chargeItemList 采购账单
     */
    @Override
    public void createBilledPurchaseCharge(List<ChargeItem> chargeItemList) {
        for (ChargeItem chargeItem : chargeItemList) {
            // 此判断是为了避免插入时主键重复
            if (chargeItem.getId() == null) {
                baseMapper.insert(chargeItem);
            }
        }
    }

    /**
     * 门诊挂号时保存 费用项
     *
     * @param chargeItem 费用项
     */
    @Override
    public void saveChargeItemByRegister(ChargeItem chargeItem) {
        chargeItem.setContextEnum(ChargeItemContext.REGISTER.getValue());// 挂号
        baseMapper.insert(chargeItem);
    }

    /**
     * 更改就诊患者账户类型
     *
     * @param encounterId 就诊患者
     * @param accountId 账户id
     * @return 更新结果
     */
    @Override
    public boolean updateAccountType(Long encounterId, Long accountId) {
        int update =
            baseMapper.update(new ChargeItem().setAccountId(accountId),
                new LambdaUpdateWrapper<ChargeItem>().eq(ChargeItem::getEncounterId, encounterId)
                    .in(ChargeItem::getStatusEnum, ChargeItemStatus.DRAFT.getValue(),
                        ChargeItemStatus.PLANNED.getValue(), ChargeItemStatus.BILLABLE.getValue())
                    .eq(ChargeItem::getDeleteFlag, DelFlag.NO.getCode()));
        return update > 0;
    }

    /**
     * 根据收费项目id列表获取收费信息
     *
     * @param chargeItemIdList 收费项目id列表
     * @return 收费信息
     */
    @Override
    public List<ChargeItem> getChargeItemInfo(List<Long> chargeItemIdList) {
        return baseMapper.selectBatchIds(chargeItemIdList);
    }

    /**
     * 更新收费状态：退费中
     *
     * @param chargeItemIdList 收费id列表
     */
    @Override
    public void updateRefundChargeStatus(List<Long> chargeItemIdList) {
        baseMapper.update(new ChargeItem().setStatusEnum(ChargeItemStatus.REFUNDING.getValue()),
            new LambdaUpdateWrapper<ChargeItem>().in(ChargeItem::getId, chargeItemIdList).eq(ChargeItem::getDeleteFlag,
                DelFlag.NO.getCode()));
    }

    /**
     * 更新收费状态
     *
     * @param chargeItemIdList 收费项目id集合
     * @param value 状态值
     */
    @Override
    public void updatePaymentStatus(List<Long> chargeItemIdList, Integer value) {
        baseMapper.update(
            new ChargeItem().setStatusEnum(value).setPerformerId(SecurityUtils.getLoginUser().getPractitionerId()),
            new LambdaUpdateWrapper<ChargeItem>().in(ChargeItem::getId, chargeItemIdList).eq(ChargeItem::getDeleteFlag,
                DelFlag.NO.getCode()));
    }

    /**
     * 根据表名和id删除费用项
     * 
     * @param tableName 表名
     * @param serviceId id
     */
    @Override
    public void deleteByServiceTableAndId(String tableName, Long serviceId) {
        baseMapper.delete(new LambdaQueryWrapper<ChargeItem>().eq(ChargeItem::getServiceTable, tableName)
            .eq(ChargeItem::getServiceId, serviceId));
    }

    /**
     * 根据就诊id查询患者因退费重新生成的账单
     *
     * @param encounterId 就诊id
     * @return 重新生成的账单列表
     */
    @Override
    public List<String> getRegenerateCharge(Long encounterId) {
        List<ChargeItem> chargeItemList =
            baseMapper.selectList(new LambdaUpdateWrapper<ChargeItem>().eq(ChargeItem::getEncounterId, encounterId)
                .eq(ChargeItem::getStatusEnum, ChargeItemStatus.PLANNED.getValue()).isNotNull(ChargeItem::getRefundId));
        List<String> chargeItemIdList = new ArrayList<>();
        if (chargeItemList != null) {
            chargeItemIdList =
                chargeItemList.stream().map(item -> item.getId().toString()).collect(Collectors.toList());
        }
        return chargeItemIdList;
    }

    /**
     * 根据请求编号列表查询收费项目信息
     *
     * @param requestIdList 请求id列表
     * @return 收费项目信息
     */
    @Override
    public List<ChargeItem> getChargeItemInfoByReqId(List<Long> requestIdList) {
        return baseMapper.selectList(new LambdaQueryWrapper<ChargeItem>().in(ChargeItem::getServiceId, requestIdList)
            .eq(ChargeItem::getDeleteFlag, DelFlag.NO.getCode()));
    }

    /**
     * 收费项基础信息集合
     *
     * @param collect 集合
     * @return 集合
     */
    @Override
    public List<ChargeItemBaseInfoDto> getChargeItemBaseInfoByIds(List<Long> collect) {
        return baseMapper.getChargeItemBaseInfoByIds(collect);
    }

    /**
     * 收费项关联Def项目集合
     *
     * @param chargeItemIds 集合
     * @return 集合
     */
    @Override
    public List<ChargeItemDefInfo> getChargeItemDefInfoByIds(List<Long> chargeItemIds) {
        return baseMapper.getChargeItemDefInfoByIds(chargeItemIds);
    }

    /**
     * 收费项关联Def项目集合(带组套)
     *
     * @param chargeItemIds 集合
     * @return 集合
     */
    @Override
    public List<ChargeItemDefInfo> getChargeItemDefInfoByIdList(List<Long> chargeItemIds) {
        List<ChargeItemDefInfo> chargeItemDefInfos = baseMapper.getChargeItemDefInfoByIds(chargeItemIds);
        List<ChargeItemDefInfo> chargeItemDefInfoChildren = new ArrayList<>();
        ChargeItemDefInfo chargeItemDefInfo;
        for (ChargeItemDefInfo chargeItemDefInfoById : chargeItemDefInfos) {

            if (!StringUtils.isEmpty(chargeItemDefInfoById.getChildrenJson())) {
                List<ChargeItem> childrenList =
                    JSON.parseArray(chargeItemDefInfoById.getChildrenJson(), ChargeItem.class);
                for (ChargeItem chargeItem : childrenList) {

                    ChargeItemDefinition chargeItemDefinition =
                        chargeItemDefinitionMapper.selectById(chargeItem.getDefinitionId());

                    if (chargeItemDefinition == null) {
                        throw new ServiceException("未查询到定价信息！提示信息：" + chargeItemDefInfoById.getChargeName() + "子项信息--"
                            + chargeItem.getDefinitionId());
                    }
                    chargeItemDefInfo = new ChargeItemDefInfo();

                    BeanUtils.copyProperties(chargeItem, chargeItemDefInfo);
                    BeanUtils.copyProperties(chargeItemDefinition, chargeItemDefInfo);

                    chargeItemDefInfoChildren.add(chargeItemDefInfo);
                }

            }
        }
        if (!chargeItemDefInfoChildren.isEmpty()) {
            chargeItemDefInfos.addAll(chargeItemDefInfoChildren);
        }
        return chargeItemDefInfos;
    }

    /**
     * 根据执行id查询收费项目信息
     *
     * @param procedureIdList 执行id列表
     * @return 收费项目信息
     */
    @Override
    public List<ChargeItem> getChargeItemByProcedureId(List<Long> procedureIdList) {
        return baseMapper.selectList(new LambdaQueryWrapper<ChargeItem>()
            .in(ChargeItem::getProcedureId, procedureIdList).eq(ChargeItem::getDeleteFlag, DelFlag.NO.getCode()));
    }

    /**
     * 根据执行id列表更新账单状态为：待收费
     *
     * @param procedureIdList 执行id列表
     */
    @Override
    public void updatePlannedChargeStatus(List<Long> procedureIdList) {
        for (Long procedureId : procedureIdList) {
            baseMapper.update(new ChargeItem().setStatusEnum(ChargeItemStatus.PLANNED.getValue()),
                new LambdaUpdateWrapper<ChargeItem>().eq(ChargeItem::getProcedureId, procedureId)
                    .eq(ChargeItem::getDeleteFlag, DelFlag.NO.getCode()));
        }
    }
}
