package com.ecep.contract.cloud.u8;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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 com.ecep.contract.IEntityService;
import com.ecep.contract.QueryService;
import com.ecep.contract.cloud.CloudInfo;
import com.ecep.contract.cloud.CloudInfoRepository;
import com.ecep.contract.cloud.u8.ctx.AbstractYongYouU8Ctx;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.other.service.EmployeeService;
import com.ecep.contract.ds.vendor.service.CompanyVendorService;
import com.ecep.contract.model.CloudYu;
import com.ecep.contract.model.Company;
import com.fasterxml.jackson.databind.JsonNode;

@Lazy
@Service
// @ConditionalOnProperty(name = "cloud.u8.enabled", havingValue = "true")          
public class YongYouU8Service implements IEntityService<CloudYu>, QueryService<CloudYu> {
    private static final Logger logger = LoggerFactory.getLogger(YongYouU8Service.class);

    public static final String KEY_HOST_IP = "u8.db.server.ip";
    public static final String KEY_DATABASE = "u8.db.database";
    public static final String KEY_USER_NAME = "u8.db.server.name";
    public static final String KEY_PASSWORD = "u8.db.server.password";

    @Lazy
    @Autowired
    private YongYouU8Repository repository;
    @Lazy
    @Autowired
    private CloudInfoRepository cloudInfoRepository;
    @Lazy
    @Autowired
    private CompanyService companyService;
    @Lazy
    @Autowired
    private CompanyVendorService companyVendorService;
    @Lazy
    @Autowired
    private CloudYuRepository cloudYuRepository;
    @Lazy
    @Autowired
    private EmployeeService employeeService;
    @Lazy
    @Autowired
    private CompanyCustomerService companyCustomerService;

    public YongYouU8Service() {

    }

    public CloudYu findById(Integer id) {
        return cloudYuRepository.findById(id).orElse(null);
    }

    /**
     * 创建
     *
     * @param info 供应商信息
     * @return 供应商对象
     */
    public CloudYu getOrCreateCloudYu(CloudInfo info) {
        Optional<CloudYu> optional = cloudYuRepository.findById(info.getId());
        return optional.orElseGet(() -> getOrCreateCloudYu(info.getCompany()));
    }

    /**
     * 创建或获取供应商云信息
     *
     * @param company 公司
     * @return 供应商云信息
     */
    public CloudYu getOrCreateCloudYu(Company company) {
        Integer companyId = company.getId();
        List<CloudYu> list = cloudYuRepository.findAllByCompanyId(companyId);
        if (list.isEmpty()) {
            CloudYu cloudYu = new CloudYu();
            cloudYu.setCompany(company);
            cloudYu.setExceptionMessage("");
            cloudYu.setVendorUpdateDate(null);
            cloudYu.setCustomerUpdateDate(null);
            cloudYu.setCloudLatest(null);
            return cloudYuRepository.save(cloudYu);
        }

        // 只有匹配到一条有 CloudId 的记录
        if (list.size() == 1) {
            // 保留匹配的记录，其他删除
            CloudYu rk = list.removeFirst();
            list.remove(rk);
            cloudYuRepository.deleteAll(list);
            return rk;
        }

        return list.getFirst();
    }

    /**
     * 保存 Cloud Yu
     *
     * @param cloudYu Cloud Yu 对象
     * @return 更新的 Cloud Yu
     */
    public CloudYu save(CloudYu cloudYu) {
        return cloudYuRepository.save(cloudYu);
    }

    @Override
    public void delete(CloudYu entity) {
        cloudYuRepository.delete(entity);
    }

    public void deleteByCompany(Company company) {
        int deleted = cloudYuRepository.deleteAllByCompany(company);
        if (deleted > 0) {
            if (logger.isInfoEnabled()) {
                logger.info("Delete {} records by company:#{}", deleted, company.getId());
            }
        }
    }

    public void resetTo(Company from, Company to) {
        List<CloudYu> list = cloudYuRepository.findAllByCompanyId(from.getId());
        for (CloudYu item : list) {
            item.setCompany(to);
        }
        cloudYuRepository.saveAll(list);
    }

    public Page<CloudYu> findAll(Specification<CloudYu> spec, Pageable pageable) {
        return cloudYuRepository.findAll(spec, pageable);
    }

    @Override
    public Page<CloudYu> findAll(JsonNode paramsNode, Pageable pageable) {
        Specification<CloudYu> spec = null;
        return findAll(spec, pageable);
    }

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

    public List<Map<String, Object>> queryAllContractKind() {
        return repository.queryAllContractKind();
    }

    public List<Map<String, Object>> queryAllVendorClass() {
        return repository.queryAllVendorClass();
    }

    public List<Map<String, Object>> queryAllCustomerClass() {
        return repository.queryAllCustomerClass();
    }

    public List<Map<String, Object>> queryAllContractType() {
        return repository.queryAllContractType();
    }

    public List<Map<String, Object>> queryAllContractGroup() {
        return repository.queryAllContractGroup();
    }

    public Long countAllCustomers() {
        return repository.countAllCustomers();
    }

    public Stream<Map<String, Object>> queryAllCustomerForStream() {
        return repository.queryAllCustomerForStream();
    }

    public List<Map<String, Object>> queryAllPerson() {
        return repository.queryAllPerson();
    }

    public Map<String, Object> findVendorByVendCode(String unit) {
        return repository.findVendorByVendCode(unit);
    }

    public Map<String, Object> findCustomerByCusCode(String unit) {
        return repository.findCustomerByCusCode(unit);
    }

    public void initialize(AbstractYongYouU8Ctx ctx) {
        ctx.setRepository(repository);
        ctx.setCompanyService(companyService);
        ctx.setEmployeeService(employeeService);
        ctx.setCompanyVendorService(companyVendorService);
        ctx.setCompanyCustomerService(companyCustomerService);
    }

    public Iterable<CloudInfo> findAllCloudYu() {
        return cloudInfoRepository.findAll();
    }
}
