package com.ecep.contract.service;

import com.ecep.contract.PageArgument;
import com.ecep.contract.PageContent;
import com.ecep.contract.WebSocketClientService;
import com.ecep.contract.model.SysConf;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

@Service
@CacheConfig(cacheNames = "sys_conf")
public class SysConfService {
    @Autowired
    protected WebSocketClientService webSocketService;
    @Autowired
    protected ObjectMapper objectMapper;

    public CompletableFuture<SysConf> asyncFindById(String id) {
        return webSocketService.invoke(getBeanName(), "findById", id).handle((response, ex) -> {
            if (ex != null) {
                throw new RuntimeException("远程方法+findById+调用失败", ex);
            }
            SysConf newEntity = new SysConf();
            try {
                objectMapper.updateValue(newEntity, response);
            } catch (JsonMappingException e) {
                throw new RuntimeException(response.toString(), e);
            }
            return newEntity;
        });
    }

    public SysConf findById(String key) {
        try {
            return asyncFindById(key).get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public CompletableFuture<Page<SysConf>> asyncFindAll(Map<String, Object> params, Pageable pageable) {
        return webSocketService.invoke(getBeanName(), "findAll", params, PageArgument.of(pageable)).handle((response, ex) -> {
            if (ex != null) {
                throw new RuntimeException("远程方法+findAll+调用失败", ex);
            }
            try {
                PageContent<SysConf> pageContent = QueryService.of(response, objectMapper, SysConf::new);
                return pageContent.toPage();
            } catch (Exception e) {
                throw new RuntimeException(response.toString(), e);
            }
        });
    }

    public Page<SysConf> findAll(Map<String, Object> params, Pageable pageable) {
        try {
            return asyncFindAll(params, pageable).get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Cacheable(key = "#p0")
    public boolean getBoolean(String key) {
        return get(key, false);
    }

    public boolean get(String key, boolean defaultValue) {
        SysConf conf = findById(key);
        if (conf == null) {
            return defaultValue;
        } else {
            if (Boolean.parseBoolean(conf.getValue())) {
                return true;
            }
            return "1".equalsIgnoreCase(conf.getValue());
        }
    }

    @CacheEvict(key = "#p0")
    public SysConf set(String key, String value) {
        SysConf conf = findById(key);
        if (conf == null) {
            conf = new SysConf();
            conf.setId(key);
            conf.setCreated(LocalDateTime.now());
        }
        conf.setValue(value);
        conf.setModified(LocalDateTime.now());
        return save(conf);
    }

    @Cacheable(key = "#p0")
    public String getString(String key) {
        return get(key, null);
    }

    public String get(String key, String defaultValue) {
        SysConf conf = findById(key);
        if (conf == null) {
            return defaultValue;
        } else {
            return conf.getValue();
        }
    }

    @Cacheable(key = "#p0")
    public long getLong(String key) {
        return get(key, 0);
    }

    public long get(String key, long defaultValue) {
        SysConf conf = findById(key);
        if (conf == null) {
            return defaultValue;
        } else {
            return Long.parseLong(conf.getValue());
        }
    }

    @Cacheable(key = "#p0")
    public int getInt(String key) {
        return get(key, 0);
    }

    public int get(String key, int defaultValue) {
        SysConf conf = findById(key);
        if (conf == null) {
            return defaultValue;
        } else {
            return Integer.parseInt(conf.getValue());
        }
    }

    @CacheEvict(key = "#p0.id")
    public SysConf save(SysConf entity) {
        try {
            return webSocketService.invoke(getBeanName(), "save", entity).handle((response, ex) -> {
                if (ex != null) {
                    throw new RuntimeException("远程方法+save+调用失败", ex);
                }
                if (response != null) {
                    try {
                        objectMapper.updateValue(entity, response);
                    } catch (JsonMappingException e) {
                        throw new RuntimeException(e);
                    }
                }
                return entity;
            }).get();
        } catch (Exception e) {
            throw new RuntimeException("保存实体失败", e);
        }
    }

    public String getBeanName() {
        return "sysConfService";
    }

}
