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

import java.util.List;
import java.util.function.Consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.ecep.contract.ContractFileType;
import com.ecep.contract.IEntityService;
import com.ecep.contract.QueryService;
import com.ecep.contract.ds.contract.repository.ContractFileRepository;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.ContractFile;
import com.ecep.contract.util.SpecificationUtils;
import com.fasterxml.jackson.databind.JsonNode;

@Lazy
@Service
@CacheConfig(cacheNames = "contract-file")
public class ContractFileService implements IEntityService<ContractFile>, QueryService<ContractFile> {
    private static final Logger logger = LoggerFactory.getLogger(ContractFileService.class);
    @Lazy
    @Autowired
    private ContractFileRepository contractFileRepository;

    @Override
    @Cacheable(key = "#p0")
    public ContractFile findById(Integer id) {
        return contractFileRepository.findById(id).orElse(null);
    }

    @Override
    public Specification<ContractFile> getSpecification(String searchText) {
        if (!StringUtils.hasText(searchText)) {
            return null;
        }
        return (root, query, builder) -> {
            return builder.or(
                    builder.like(root.get("fileName"), "%" + searchText + "%"),
                    builder.like(root.get("description"), "%" + searchText + "%"));
        };
    }

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

    @Override
    public Page<ContractFile> findAll(JsonNode paramsNode, Pageable pageable) {
        Specification<ContractFile> spec = null;
        if (paramsNode.has("searchText")) {
            spec = getSpecification(paramsNode.get("searchText").asText());
        }

        // field
        spec = SpecificationUtils.andParam(spec, paramsNode, "contract", "type");

        return findAll(spec, pageable);
    }

    public List<ContractFile> findAll(Specification<ContractFile> spec, Sort by) {
        return contractFileRepository.findAll(spec, by);
    }

    public List<ContractFile> findAllByContractAndFileType(Contract contract, ContractFileType contractFileType) {
        return contractFileRepository.findAllByContractAndType(contract, contractFileType);
    }

    /**
     * 按销售逻辑处理
     */
    @Deprecated
    public void verifyAsCustomer(Contract contract, Consumer<String> status) {

        // 检查 成本审批
        if (!checkFileExist(contract, ContractFileType.CostForm)) {
            status.accept("销售成本审批表未找到");
        }
        // 检查 合同审批表
        if (!checkFileExist(contract, ContractFileType.ContractApprovalForm)) {
            status.accept("销售合同审批表未找到");
        }
        // 检查 合同
        if (!checkFileExist(contract, ContractFileType.Contract)) {
            status.accept("销售合同未找到");
        }
    }

    public boolean checkFileExist(Contract contract, ContractFileType type) {
        List<ContractFile> files = contractFileRepository.findAllByContractAndType(contract, type);
        if (files == null || files.isEmpty()) {
            return false;
        }
        return true;
    }

    /**
     * 按采购逻辑处理
     */
    @Deprecated
    public void verifyAsVendor(Contract contract, Consumer<String> status) {
        // 检查 申请表
        if (!checkFileExist(contract, ContractFileType.PurchaseRequestForm)) {
            status.accept("采购申请表未找到");
        }
        // 检查 合同审批表
        if (!checkFileExist(contract, ContractFileType.PurchaseContractApprovalForm)) {
            status.accept("采购合同审批表未找到");
        }
        // 检查 合同
        if (!checkFileExist(contract, ContractFileType.Contract)) {
            status.accept("采购合同未找到");
        }
        // 检查 提货单
        // contractFileRepository.findAllByContractAndType(contract,
        // ContractFileType.DeliveryOrder);
    }

    @Caching(evict = {
            @CacheEvict(key = "#p0.id"),
            @CacheEvict(key = "'allbycontract-'+#p0.contract.id")
    })
    @Override
    public void delete(ContractFile file) {
        contractFileRepository.deleteById(file.getId());
    }

    @Caching(evict = {
            @CacheEvict(key = "#p0.id"),
            @CacheEvict(key = "'allbycontract-'+#p0.contract.id")
    })
    public ContractFile save(ContractFile contractFile) {
        return contractFileRepository.save(contractFile);
    }

    public void deleteById(int id) {
        contractFileRepository.deleteById(id);
    }

    @Cacheable(key = "'allbycontract-'+#p0.id")
    public List<ContractFile> findAllByContract(Contract contract) {
        return contractFileRepository.findAllByContract(contract);
    }

    public List<ContractFile> searchByContract(Contract contract, String userText) {
        Specification<ContractFile> spec = (root, query, builder) -> {
            return builder.and(
                    builder.equal(root.get("contract"), contract),
                    builder.or(
                            builder.like(root.get("fileName"), "%" + userText + "%"),
                            builder.like(root.get("description"), "%" + userText + "%")));
        };
        return contractFileRepository.findAll(spec);
    }
}
