package com.ecep.contract.ds.customer.service;

import com.ecep.contract.IEntityService;
import com.ecep.contract.QueryService;
import com.ecep.contract.constant.ServiceConstant;
import com.ecep.contract.ds.customer.repository.CustomerCatalogRepository;
import com.ecep.contract.model.CustomerCatalog;
import com.ecep.contract.service.ServiceException;
import com.ecep.contract.service.VoableService;
import com.ecep.contract.util.SpecificationUtils;
import com.ecep.contract.vo.CustomerCatalogVo;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * 客户分类服务
 */
@Lazy
@Service
@CacheConfig(cacheNames = "customer-catalog")
public class CustomerCatalogService implements IEntityService<CustomerCatalog>, QueryService<CustomerCatalogVo>,
        VoableService<CustomerCatalog, CustomerCatalogVo> {
    @Lazy
    @Autowired
    private CustomerCatalogRepository repository;

    /**
     * 根据 id 查找 CustomerCatalog
     */
    @Override
    public CustomerCatalog getById(Integer id) {
        return repository.findById(id).orElse(null);
    }

    @Cacheable(key = "#p0")
    @Override
    public CustomerCatalogVo findById(Integer id) {
        return repository.findById(id).map(CustomerCatalog::toVo).orElse(null);
    }

    /**
     * 根据 code 查找 CustomerCatalog
     */
    @Cacheable(key = "'code-'+#p0")
    public CustomerCatalogVo findByCode(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        return repository.findByCode(code).map(CustomerCatalog::toVo).orElse(null);
    }

    /**
     * 根据 name 查找 CustomerCatalog
     */
    @Cacheable(key = "'name-'+#p0")
    public CustomerCatalogVo findByName(String name) {
        if (!StringUtils.hasText(name)) {
            return null;
        }
        return repository.findByName(name).map(CustomerCatalog::toVo).orElse(null);
    }

    /**
     * 查找所有 CustomerCatalog
     */
    @Cacheable(key = "'all'")
    public List<CustomerCatalogVo> findAll() {
        return repository.findAll().stream().map(CustomerCatalog::toVo).toList();
    }

    /**
     * 保存 CustomerCatalog
     */
    @Caching(evict = {
            @CacheEvict(key = "#p0.id"),
            @CacheEvict(key = "'code-'+#p0.code"),
            @CacheEvict(key = "'name-'+#p0.name"),
            @CacheEvict(key = "'all'")
    })
    @Override
    public CustomerCatalog save(CustomerCatalog catalog) {
        return repository.save(catalog);
    }

    /**
     * 删除 CustomerCatalog
     */
    @Caching(evict = {
            @CacheEvict(key = "#p0.id"),
            @CacheEvict(key = "'code-'+#p0.code"),
            @CacheEvict(key = "'name-'+#p0.name"),
            @CacheEvict(key = "'all'")
    })
    @Override
    public void delete(CustomerCatalog catalog) {
        repository.delete(catalog);
    }

    /**
     * 分页查询 CustomerCatalog
     */
    @Override
    public Page<CustomerCatalogVo> findAll(JsonNode paramsNode, Pageable pageable) {
        Specification<CustomerCatalog> spec = null;
        if (paramsNode.has(ServiceConstant.KEY_SEARCH_TEXT)) {
            spec = getSpecification(paramsNode.get(ServiceConstant.KEY_SEARCH_TEXT).asText());
        }

        // 字段等值查询
        spec = SpecificationUtils.andFieldEqualParam(spec, paramsNode, "code", "name", "description");
        return repository.findAll(spec, pageable).map(CustomerCatalog::toVo);
    }

    /**
     * 根据搜索文本创建查询条件
     */
    public Specification<CustomerCatalog> getSpecification(String searchText) {
        if (!StringUtils.hasText(searchText)) {
            return null;
        }
        String likeText = "%" + searchText + "%";
        return (root, query, builder) -> {
            return builder.or(
                    builder.like(root.get("code"), likeText),
                    builder.like(root.get("name"), likeText),
                    builder.like(root.get("description"), likeText));
        };
    }

    /**
     * 搜索 CustomerCatalog
     */
    public List<CustomerCatalog> search(String searchText) {
        return repository.findAll(getSpecification(searchText), Pageable.ofSize(10)).getContent();
    }

    @Override
    public Page<CustomerCatalog> findAll(Specification<CustomerCatalog> spec, Pageable pageable) {
        return repository.findAll(spec, pageable);
    }

    @Override
    public void updateByVo(CustomerCatalog model, CustomerCatalogVo vo) {
        // 参数校验
        if (model == null) {
            throw new ServiceException("实体对象不能为空");
        }
        if (vo == null) {
            throw new ServiceException("VO对象不能为空");
        }

        // 映射基本属性
        model.setCode(vo.getCode());
        model.setName(vo.getName());
        model.setDescription(vo.getDescription());
    }
}