package cn.lihongjie.coal.weightColumnConfig.service;

import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.common.Ctx;
import cn.lihongjie.coal.common.GroovyScriptUtils;
import cn.lihongjie.coal.dbFunctions.DbFunctionService;
import cn.lihongjie.coal.weightColumnConfig.dto.CreateWeightColumnConfigDto;
import cn.lihongjie.coal.weightColumnConfig.dto.UpdateWeightColumnConfigDto;
import cn.lihongjie.coal.weightColumnConfig.dto.WeightColumnConfigDto;
import cn.lihongjie.coal.weightColumnConfig.entity.WeightColumnConfigEntity;
import cn.lihongjie.coal.weightColumnConfig.mapper.WeightColumnConfigMapper;
import cn.lihongjie.coal.weightColumnConfig.repository.WeightColumnConfigRepository;
import cn.lihongjie.coal.weightDeviceData.service.WeightDeviceDataService;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.List;

@Service
@Slf4j
@Transactional
public class WeightColumnConfigService
        extends BaseService<WeightColumnConfigEntity, WeightColumnConfigRepository> {
    @Autowired private WeightColumnConfigRepository repository;

    @Autowired private WeightColumnConfigMapper mapper;

    @Autowired private ConversionService conversionService;

    @Autowired private DbFunctionService dbFunctionService;

    public WeightColumnConfigDto create(CreateWeightColumnConfigDto request) {
        WeightColumnConfigEntity entity = mapper.toEntity(request);

        this.repository.save(entity);
        return getById(entity.getId());
    }

    @Autowired WeightDeviceDataService weightDeviceDataService;

    public WeightColumnConfigDto update(UpdateWeightColumnConfigDto request) {

        if (StringUtils.isBlank(request.getScript())){
            request.setScript(null);

        }

        WeightColumnConfigEntity entity = this.repository.get(request.getId());



        this.validateScript(request);

        this.mapper.updateEntity(entity, request);

        this.repository.save(entity);

        return getById(entity.getId());
    }

    @PersistenceContext EntityManager em;

    private void validateScript(UpdateWeightColumnConfigDto request) {

        if (StringUtils.isBlank(request.getScript())) {
            return;
        }

        String script = request.getScript();

        GroovyScriptUtils.validate(script);

        List<String> variables = GroovyScriptUtils.variables(request.getScript());

        if (CollectionUtils.isNotEmpty(variables)) {


            for (String variable : variables) {


                Long cnt = (Long) em.createQuery("select count(*) from WeightColumnConfigEntity where code = :variable and status = 1 and organizationId = :organizationId")
                        .setParameter("variable", variable)
                        .setParameter("organizationId", Ctx.currentUser().getOrganizationId())
                        .getSingleResult();

                if ( cnt == null ||  cnt == 0) {
                    throw new RuntimeException("变量不存在或者被禁用: " + variable);
                }


            }

        }
    }

    public void runScriptOnOldData(IdRequest request) {

        WeightColumnConfigEntity entity = this.repository.get(request.getIds().get(0));

        if (StringUtils.isBlank(entity.getScript())) {
            return;
        }

        String script = entity.getScript();
    }

    public void delete(IdRequest request) {
        this.repository.deleteAllById(request.getIds());
    }

    public WeightColumnConfigDto getById(String id) {
        WeightColumnConfigEntity entity = repository.get(id);

        return mapper.toDto(entity);
    }

    public Page<WeightColumnConfigDto> list(CommonQuery query) {
        Page<WeightColumnConfigEntity> page =
                repository.findAll(
                        query.specification(conversionService),
                        PageRequest.of(
                                query.getPageNo(),
                                query.getPageSize(),
                                Sort.by(query.getOrders())));

        if (!page.hasContent()) {
            initDefault(Ctx.currentUser().getOrganizationId());
            return list(query);
        }

        return page.map(this.mapper::toDto);
    }

    @SneakyThrows
    public void initDefault(String organizationId) {

        this.repository.deleteByOrganizationId(organizationId);

        ClassPathResource classPathResource =
                new ClassPathResource("/config/weightColumnConfig.json");

        ObjectMapper mapper = new ObjectMapper();
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        List<WeightColumnConfigEntity> data;

        try (InputStream inputStream = classPathResource.getInputStream()) {
            data =
                    mapper.readValue(
                            inputStream, new TypeReference<List<WeightColumnConfigEntity>>() {});
        }

        data.forEach(x -> x.setOrganizationId(organizationId));
        data.forEach(x -> x.setScript(""));

        this.repository.saveAll(data);
    }
}
