package com.eshore.gringotts.web.domain.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.eshore.gringotts.web.domain.base.service.CheckingService;
import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport;
import com.eshore.gringotts.web.domain.entity.CheckOrder;
import com.eshore.gringotts.web.domain.entity.CheckOrder_;
import com.eshore.gringotts.web.domain.entity.User;
import com.eshore.gringotts.web.domain.repository.CheckOrderRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
import org.eclipse.collections.api.map.ImmutableMap;
import org.springframework.context.ApplicationContext;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Service;

/**
 * @author lanyuanxiaoyao
 * @date 2024-11-29
 */
@Slf4j
@Service
public class CheckOrderService extends SimpleServiceSupport<CheckOrder> {
    private final ApplicationContext applicationContext;
    private final ObjectMapper mapper;
    private final CheckOrderRepository checkOrderRepository;
    private final UserService userService;

    public CheckOrderService(CheckOrderRepository repository, UserService userService, ApplicationContext applicationContext, Jackson2ObjectMapperBuilder builder) {
        super(repository, userService);
        this.applicationContext = applicationContext;
        this.mapper = builder.build();
        this.checkOrderRepository = repository;
        this.userService = userService;
    }

    @Override
    protected ImmutableList<Predicate> listPredicate(Root<CheckOrder> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
        User user = userService.currentLoginUser();
        if (User.isAdministrator(user)) {
            return Lists.immutable.empty();
        }
        return Lists.immutable.of(builder.or(
                builder.equal(root.get(CheckOrder_.createdUser), user),
                builder.and(
                        builder.equal(root.get(CheckOrder_.target), CheckOrder.Target.USER),
                        builder.equal(root.get(CheckOrder_.targetUser), user)
                ),
                builder.and(
                        builder.equal(root.get(CheckOrder_.target), CheckOrder.Target.ROLE),
                        builder.equal(root.get(CheckOrder_.targetRole), user.getRole())
                )
        ));
    }

    public void operation(Long id, CheckOrder.Operation operation) throws JsonProcessingException {
        CheckOrder order = detailOrThrow(id);
        CheckingService service = applicationContext.getBean(order.getTargetClass(), CheckingService.class);
        if (ObjectUtil.isNull(service)) {
            throw new RuntimeException(StrUtil.format("名为「{}」的服务未找到", order.getTargetClass()));
        }
        ImmutableMap<String, Object> parameters = mapper.readValue(order.getParameters(), new TypeReference<>() {});
        service.onChecked(order, operation, parameters);
    }

    public void retract(Long id) {
        checkOrderRepository.overById(id, CheckOrder.State.RETRACT, userService.currentLoginUser());
    }

    public void over(Long id) {
        checkOrderRepository.overById(id, CheckOrder.State.OVER, userService.currentLoginUser());
    }
}
