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

import java.util.List;

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 com.ecep.contract.IEntityService;
import com.ecep.contract.QueryService;
import com.ecep.contract.SpringApp;
import com.ecep.contract.ds.contract.repository.PurchaseOrderRepository;
import com.ecep.contract.ds.other.service.EmployeeService;
import com.ecep.contract.ds.contract.model.Contract;
import com.ecep.contract.ds.vendor.model.PurchaseOrder;
import com.ecep.contract.service.ServiceException;
import com.ecep.contract.service.VoableService;
import com.ecep.contract.util.SpecificationUtils;
import com.ecep.contract.vo.PurchaseOrderVo;
import com.fasterxml.jackson.databind.JsonNode;

/**
 * 采购订单服务
 */
@Lazy
@Service
@CacheConfig(cacheNames = "contract-purchase-order")
public class PurchaseOrdersService implements IEntityService<PurchaseOrder>, QueryService<PurchaseOrderVo>,
        VoableService<PurchaseOrder, PurchaseOrderVo> {
    private static final Logger logger = LoggerFactory.getLogger(PurchaseOrdersService.class);

    @Lazy
    @Autowired
    private PurchaseOrderRepository repository;

    @Lazy
    @Autowired
    private EmployeeService employeeService;

    @Override
    public PurchaseOrder getById(Integer id) {
        return repository.findById(id).orElse(null);
    }

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

    @Override
    public Specification<PurchaseOrder> getSpecification(String searchText) {
        return (root, query, builder) -> {
            return builder.or(
                    builder.like(root.get("code"), "%" + searchText + "%"),
                    builder.like(root.get("description"), "%" + searchText + "%"));
        };
    }

    @Cacheable(key = "'code-'+#p0")
    public PurchaseOrderVo findByCode(String code) {
        return repository.findByCode(code).map(PurchaseOrder::toVo).orElse(null);
    }

    @Cacheable(key = "'refId-'+#p0")
    public PurchaseOrderVo findByRefId(Integer refId) {
        return repository.findByRefId(refId).map(PurchaseOrder::toVo).orElse(null);
    }
    public PurchaseOrder getByRefId(Integer refId) {
        return repository.findByRefId(refId).orElse(null);
    }

    /**
     * 保存实体对象，异步方法
     *
     * @param order 要保存的实体对象
     * @return 返回异步调用
     */
    @Caching(evict = {
            @CacheEvict(key = "#p0.id"),
            @CacheEvict(key = "'code-'+#p0.code"),
            @CacheEvict(key = "'refId-'+#p0.refId")
    })
    @Override
    public PurchaseOrder save(PurchaseOrder order) {
        return repository.save(order);
    }

    @Caching(evict = {
            @CacheEvict(key = "#p0.id"),
            @CacheEvict(key = "'code-'+#p0.code"),
            @CacheEvict(key = "'refId-'+#p0.refId")
    })
    @Override
    public void delete(PurchaseOrder order) {
        repository.delete(order);
    }

    public long count() {
        return repository.count();
    }

    public long count(Specification<PurchaseOrder> spec) {
        return repository.count(spec);
    }

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

    @Override
    public Page<PurchaseOrderVo> findAll(JsonNode paramsNode, Pageable pageable) {
        Specification<PurchaseOrder> spec = null;
        if (paramsNode.has("searchText")) {
            spec = getSpecification(paramsNode.get("searchText").asText());
        }
        spec = SpecificationUtils.andParam(spec, paramsNode, "contract");
        return findAll(spec, pageable).map(PurchaseOrder::toVo);
    }

    public List<PurchaseOrder> findAll(Specification<PurchaseOrder> spec, Sort sort) {
        return repository.findAll(spec, sort);
    }

    public List<PurchaseOrder> findAllByContract(Contract contract) {
        return repository.findAllByContract(contract);
    }

    public List<PurchaseOrder> search(String searchText) {
        Specification<PurchaseOrder> spec = (root, query, builder) -> {
            return builder.or(
                    builder.like(root.get("name"), "%" + searchText + "%"),
                    builder.like(root.get("code"), "%" + searchText + "%"));
        };
        return repository.findAll(spec, Pageable.ofSize(10)).getContent();
    }

    @Override
    public void updateByVo(PurchaseOrder model, PurchaseOrderVo vo) {
        if (model == null || vo == null) {
            throw new ServiceException("实体或VO对象不能为空");
        }

        // 设置基础属性
        model.setCode(vo.getCode());
        model.setRefId(vo.getRefId());
        model.setVendorCode(vo.getVendorCode());
        model.setDescription(vo.getDescription());

        // 处理关联实体 - 合同
        if (vo.getContractId() == null) {
            model.setContract(null);
        } else {
            ContractService contractService = SpringApp.getBean(ContractService.class);
            if (model.getContract() == null || !model.getContract().getId().equals(vo.getContractId())) {
                model.setContract(contractService.getById(vo.getContractId()));
            }
        }
        EmployeeService employeeService = SpringApp.getBean(EmployeeService.class);
        // 处理关联实体 - 采购人
        if (vo.getEmployeeId() == null) {
            model.setEmployee(null);
        } else {
            if (model.getEmployee() == null || !model.getEmployee().getId().equals(vo.getEmployeeId())) {
                model.setEmployee(employeeService.getById(vo.getEmployeeId()));
            }
        }
        // 处理关联实体 - 制单人
        if (vo.getMakerId() == null) {
            model.setMaker(null);
        } else {
            if (model.getMaker() == null || !model.getMaker().getId().equals(vo.getMakerId())) {
                model.setMaker(employeeService.getById(vo.getMakerId()));
            }
        }
        model.setMakerDate(vo.getMakerDate());
        model.setModifyDate(vo.getModifyDate());

        // 处理关联实体 - 审核人
        if (vo.getVerifierId() == null) {
            model.setVerifier(null);
        } else {
            if (model.getVerifier() == null || !model.getVerifier().getId().equals(vo.getVerifierId())) {
                model.setVerifier(employeeService.getById(vo.getVerifierId()));
            }
        }
        model.setVerifierDate(vo.getVerifierDate());

        // 处理关联实体 - 关闭人
        if (vo.getCloserId() == null) {
            model.setCloser(null);
        } else {
            if (model.getCloser() == null || !model.getCloser().getId().equals(vo.getCloserId())) {
                model.setCloser(employeeService.getById(vo.getCloserId()));
            }
        }
        model.setCloserDate(vo.getCloserDate());
    }

}
