package cn.iocoder.yudao.module.expense.service.expensetype;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.employee.api.EmployeeApi;
import cn.iocoder.yudao.module.employee.api.dto.EmployeeRespDTO;
import cn.iocoder.yudao.module.expense.controller.admin.expensetype.vo.ExpenseTypePageReqVO;
import cn.iocoder.yudao.module.expense.controller.admin.expensetype.vo.ExpenseTypeSaveReqVO;
import cn.iocoder.yudao.module.expense.dal.dataobject.expenseitem.ExpenseItemDO;
import cn.iocoder.yudao.module.expense.dal.dataobject.expensetype.ExpenseTypeDO;
import cn.iocoder.yudao.module.expense.dal.mysql.expenseitem.ExpenseItemMapper;
import cn.iocoder.yudao.module.expense.dal.mysql.expensetype.ExpenseTypeMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.employee.enums.ErrorCodeConstants.EMPLOYEE_INFO_NOT_EXISTS;
import static cn.iocoder.yudao.module.expense.enums.ErrorCodeConstants.EXPENSE_ITEM_EXISTS;
import static cn.iocoder.yudao.module.expense.enums.ErrorCodeConstants.EXPENSE_TYPE_NOT_EXISTS;

/**
 * 报销类型信息 Service 实现类
 *
 * @author dp
 */
@Service
@Validated
public class ExpenseTypeServiceImpl implements ExpenseTypeService {

    @Resource
    private ExpenseTypeMapper typeMapper;
    @Resource
    private ExpenseItemMapper itemMapper;

    @Resource
    private EmployeeApi employeeApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createType(ExpenseTypeSaveReqVO createReqVO) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        EmployeeRespDTO loginEmp = employeeApi.getEmployeeByUserId(loginUserId);
        if (Objects.isNull(loginEmp)) {
            throw exception(EMPLOYEE_INFO_NOT_EXISTS);
        }
        // 插入
        ExpenseTypeDO type = BeanUtils.toBean(createReqVO, ExpenseTypeDO.class);
        type.setExpenseTypeUuid(IdUtil.fastSimpleUUID());
        type.setCreator(String.valueOf(loginEmp.getId()));
        typeMapper.insert(type);

        // // 插入子表
        // createItemList(type.getId(), createReqVO.getItems());
        // 返回
        return type.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateType(ExpenseTypeSaveReqVO updateReqVO) {
        // 校验存在
        validateTypeExists(updateReqVO.getId());
        // 更新
        ExpenseTypeDO updateObj = BeanUtils.toBean(updateReqVO, ExpenseTypeDO.class);
        typeMapper.updateById(updateObj);

        // // 更新子表
        // updateItemList(updateReqVO.getId(), updateReqVO.getItems());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteType(Long id) {
        // 校验存在
        validateTypeExists(id);
        validateTypeItemExists(id);
        // 删除
        typeMapper.deleteById(id);

        // // 删除子表
        // deleteItemByExpenseTypeId(id);
    }

    private void validateTypeItemExists(Long id) {
        List<ExpenseItemDO> expenseItemDOList = itemMapper.selectListByExpenseTypeId(id);
        if (CollectionUtil.isNotEmpty(expenseItemDOList)) {
            throw exception(EXPENSE_ITEM_EXISTS);
        }
    }

    private void validateTypeExists(Long id) {
        if (typeMapper.selectById(id) == null) {
            throw exception(EXPENSE_TYPE_NOT_EXISTS);
        }
    }

    @Override
    public ExpenseTypeDO getType(Long id) {
        return typeMapper.selectById(id);
    }

    @Override
    public PageResult<ExpenseTypeDO> getTypePage(ExpenseTypePageReqVO pageReqVO) {
        return typeMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ExpenseTypeDO> getTypeList() {
        LambdaQueryWrapper<ExpenseTypeDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(ExpenseTypeDO::getId);
        return typeMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public List<ExpenseTypeDO> getExpenseTypeList(Collection<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return typeMapper.selectBatchIds(ids);
    }

    // ==================== 子表（报销费用项目信息） ====================

    @Override
    public List<ExpenseItemDO> getItemListByExpenseTypeId(Long expenseTypeId) {
        if (expenseTypeId != null && expenseTypeId == 0L) {
            // 约定：前端传0，表示未选择报销类型，此时费用项目返回空集合
            return new ArrayList<>();
        }
        return itemMapper.selectListByExpenseTypeId(expenseTypeId);
    }

    private void createItemList(Long expenseTypeId, List<ExpenseItemDO> list) {
        list.forEach(o -> o.setExpenseTypeId(expenseTypeId));
        itemMapper.insertBatch(list);
    }

    private void updateItemList(Long expenseTypeId, List<ExpenseItemDO> list) {
        deleteItemByExpenseTypeId(expenseTypeId);
		list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下：1）id 冲突；2）updateTime 不更新
        createItemList(expenseTypeId, list);
    }

    private void deleteItemByExpenseTypeId(Long expenseTypeId) {
        itemMapper.deleteByExpenseTypeId(expenseTypeId);
    }

}