package cn.lihongjie.coal.empSalarySysItem.service;

import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.dbFunctions.DbFunctionService;
import cn.lihongjie.coal.empSalaryItem.entity.EmpSalaryItemEntity;
import cn.lihongjie.coal.empSalaryItem.service.EmpSalaryItemService;
import cn.lihongjie.coal.empSalarySysItem.dto.CreateEmpSalarySysItemDto;
import cn.lihongjie.coal.empSalarySysItem.dto.EmpSalarySysItemDto;
import cn.lihongjie.coal.empSalarySysItem.dto.UpdateEmpSalarySysItemDto;
import cn.lihongjie.coal.empSalarySysItem.entity.EmpSalarySysItemEntity;
import cn.lihongjie.coal.empSalarySysItem.mapper.EmpSalarySysItemMapper;
import cn.lihongjie.coal.empSalarySysItem.repository.EmpSalarySysItemRepository;
import cn.lihongjie.coal.exception.BizException;
import cn.lihongjie.coal.organization.service.OrganizationService;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;

@Service
@Slf4j
@Transactional
public class EmpSalarySysItemService
        extends BaseService<EmpSalarySysItemEntity, EmpSalarySysItemRepository> {
    @Autowired private EmpSalarySysItemRepository repository;

    @Autowired private EmpSalarySysItemMapper mapper;

    @Autowired private ConversionService conversionService;

    @Autowired private DbFunctionService dbFunctionService;

    public EmpSalarySysItemDto create(CreateEmpSalarySysItemDto request) {
        EmpSalarySysItemEntity entity = mapper.toEntity(request);

        this.repository.save(entity);
        return getById(entity.getId());
    }

    @Autowired OrganizationService organizationService;

    @Autowired EmpSalaryItemService empSalaryItemService;

    public EmpSalarySysItemDto update(UpdateEmpSalarySysItemDto request) {
        EmpSalarySysItemEntity entity = this.repository.get(request.getId());

        // 发生名称变更时, 同步更新关联的工资项目

        if (ObjectUtils.notEqual(request.getName(), entity.getName())) {
            List<EmpSalaryItemEntity> items =
                    empSalaryItemService.findAllBy(null, null, Collections.singletonList(entity.getCode()));
            if (CollectionUtils.isNotEmpty(items)) {
                items.forEach(
                        x -> {
                            x.setFormulaShow(
                                    x.getFormulaShow()
                                            .replace(entity.getName(), request.getName()));
                        });
            }
        }

        // 发生编码变更时, 同步更新关联的工资项目

        if (ObjectUtils.notEqual(request.getCode(), entity.getCode())) {
            List<EmpSalaryItemEntity> items =
                    empSalaryItemService.findAllBy(null, null, Collections.singletonList(entity.getCode()));
            if (CollectionUtils.isNotEmpty(items)) {
                items.forEach(
                        x -> {
                            if (CollectionUtils.containsAny(
                                    x.getDependOnSysItem(), entity.getCode())) {
                                x.getDependOnSysItem().remove(entity.getCode());
                                x.getDependOnSysItem().add(request.getCode());
                            }
                        });
            }
        }

        this.mapper.updateEntity(entity, request);

        this.repository.save(entity);

        empSalaryItemService.clearCacheAll();

        return getById(entity.getId());
    }

    public void delete(IdRequest request) {
        boolean linked = this.repository.isLinked(request.getIds());

        if (linked) {
            throw new BizException("数据已被关联，无法删除");
        }

        List<EmpSalarySysItemEntity> toDelete = this.repository.findAllById(request.getIds());

        // 如果被依赖, 无法删除

        empSalaryItemService
                .findAllBy(
                        null, null, toDelete.stream().map(EmpSalarySysItemEntity::getCode).toList())
                .forEach(
                        x -> {
                            if (CollectionUtils.containsAny(
                                    x.getDependOnSysItem(),
                                    toDelete.stream()
                                            .map(EmpSalarySysItemEntity::getCode)
                                            .toList())) {
                                throw new BizException("数据已被关联，无法删除");
                            }
                        });

        empSalaryItemService.clearCacheAll();
        this.repository.deleteAllById(request.getIds());
    }

    public EmpSalarySysItemDto getById(String id) {
        EmpSalarySysItemEntity entity = repository.get(id);

        return mapper.toDto(entity);
    }

    public Page<EmpSalarySysItemDto> list(CommonQuery query) {
        Page<EmpSalarySysItemEntity> page =
                repository.findAll(
                        query.specification(conversionService),
                        PageRequest.of(
                                query.getPageNo(),
                                query.getPageSize(),
                                Sort.by(query.getOrders())));

        return page.map(this.mapper::toDto);
    }
}
