package com.yihu.hos.system.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yihu.hos.common.constants.ContextAttributes;
import com.yihu.hos.config.MongoConfig;
import com.yihu.hos.core.log.Logger;
import com.yihu.hos.core.log.LoggerFactory;
import com.yihu.hos.interceptor.LocalContext;
import com.yihu.hos.system.dao.AppDao;
import com.yihu.hos.system.dao.AppServiceDao;
import com.yihu.hos.system.model.SystemApp;
import com.yihu.hos.system.model.SystemServiceEndpoint;
import com.yihu.hos.web.framework.constant.EndPointConstant;
import com.yihu.hos.web.framework.model.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zbus.broker.ZbusBroker;
import org.zbus.mq.Producer;
import org.zbus.net.http.Message;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Created by chenweida on 2016/1/21.
 */

@Service("appManager")
public class AppManager {
    public static final String BEAN_ID = "appManager";
    static final Logger logger = LoggerFactory.getLogger(AppManager.class);
    @Resource(name = AppDao.BEAN_ID)
    private AppDao appDao;

    @Value("${spring.data.mongodb.gridFsDatabase}")
    private String dbName;

    @Resource(name = AppServiceDao.BEAN_ID)
    private AppServiceDao appServiceDao;

    @Autowired
    private MongoConfig mongoConfig;

    @Autowired
    private ObjectMapper objectMapper;

    private ZbusBroker zbusBroker;

    @Autowired
    public void setZbusBroker(ZbusBroker zbusBroker) {
        this.zbusBroker = zbusBroker;
    }


    public Result getAppList(Map<String, Object> params) throws Exception {
        return appDao.getAppList(params);
    }


    public SystemApp getAppById(String id) throws Exception {
        return appDao.getEntity(SystemApp.class, id);
    }

    public List<SystemApp> getAppByCode(String code) throws Exception {
        return appDao.findByCode(code);
    }

    @Transactional
    public Result addApp(SystemApp obj) throws Exception {
        List<SystemApp> appByCode = getAppByCode(obj.getCode());
        if (appByCode == null || appByCode.size() == 0) {
            appDao.saveEntity(obj);
            return Result.success("保存成功");
        } else {
            return Result.error("保存失败，应用Code已存在");
        }

    }

    @Transactional
    public Result updateApp(SystemApp obj) throws Exception {
        List<SystemApp> appByCode = getAppByCode(obj.getCode());
        if (appByCode == null || appByCode.size() <= 1) {
            SystemApp systemApp = appDao.getEntity(SystemApp.class, obj.getId());
            systemApp.setName(obj.getName());
            systemApp.setCode(obj.getCode());
            systemApp.setAppKey(obj.getAppKey());
            systemApp.setAppSecret(obj.getAppSecret());
            systemApp.setAppUrl(obj.getAppUrl());
            systemApp.setDeveloper(obj.getDeveloper());
            systemApp.setIcon(obj.getIcon());
            systemApp.setStatus(obj.getStatus());
            return Result.success("更新成功");
        } else {
            return Result.error("更新失败，应用Code已存在");
        }
    }

    @Transactional
    public Result deleteApp(String id) throws Exception {
        SystemApp systemApp = appDao.getEntity(SystemApp.class, id);
        appDao.deleteEntity(systemApp);
        return Result.success("删除成功");
    }




    /* ==============================服务模块=================================  */


    public Result getAppServiceList(Map<String, Object> params) throws Exception {
        return appServiceDao.getAppServiceList(params);
    }


    public SystemServiceEndpoint getAppServiceById(String id) throws Exception {
        SystemServiceEndpoint serviceEndpoint = appServiceDao.getEntity(SystemServiceEndpoint.class, id);
        serviceEndpoint.setRequesModule(serviceEndpoint.getRequesModule().replaceAll("\n", "<br>"));
        serviceEndpoint.setResponeResult(serviceEndpoint.getResponeResult().replaceAll("\n", "<br>"));
        serviceEndpoint.setResponeError(serviceEndpoint.getResponeError().replaceAll("\n", "<br>"));

        return serviceEndpoint;
    }

    @Transactional
    public Result addAppService(SystemServiceEndpoint endpoint) throws Exception {
        appServiceDao.saveEntity(endpoint);
        this.sendMsg(EndPointConstant.ADD_ENDPOINT, endpoint);
        return Result.success("保存成功");
    }

    @Transactional
    public Result updateAppService(SystemServiceEndpoint obj) throws Exception {
        SystemServiceEndpoint endpoint = appServiceDao.getEntity(SystemServiceEndpoint.class, obj.getId());
        endpoint.setName(obj.getName());
        endpoint.setCode(obj.getCode());
        endpoint.setValid(obj.getValid());
        endpoint.setVersion(obj.getVersion());
        endpoint.setDescription(obj.getDescription());
        endpoint.setEndpoint(obj.getEndpoint());
        endpoint.setRequesModule(obj.getRequesModule());
        endpoint.setRequestProtocol(obj.getRequestProtocol());
        endpoint.setResponeError(obj.getResponeError());
        endpoint.setResponeResult(obj.getResponeResult());
        endpoint.setRequestMethod(obj.getRequestMethod());
        endpoint.setRequestParameterList(obj.getRequestParameterList());
        endpoint.setHealthEndpoint(obj.getHealthEndpoint());
        endpoint.setHealthReportType(obj.getHealthReportType());
        endpoint.setMetricsEndpoint(obj.getMetricsEndpoint());
        endpoint.setMetricsReportType(obj.getMetricsReportType());
        endpoint.setAppId(obj.getAppId());
        endpoint.setRequestFormat(obj.getRequestFormat());
        this.sendMsg(EndPointConstant.ADD_ENDPOINT, endpoint);
        return Result.success("更新成功");
    }

    @Transactional
    public Result deleteAppService(String id) throws Exception {
        SystemServiceEndpoint endpoint = appServiceDao.getEntity(SystemServiceEndpoint.class, id);
        appServiceDao.deleteEntity(endpoint);
        this.sendMsg(EndPointConstant.DELETE_ENDPOINT, endpoint);
        return Result.success("删除成功");
    }

    private void sendMsg(String event, SystemServiceEndpoint endpoint) {
        if (zbusBroker == null) {
            logger.error("zbusBroker is null.");
            return;
        }

        try {
            String msg = objectMapper.writeValueAsString(endpoint);
            String tenant = LocalContext.getContext().getAttachment(ContextAttributes.TENANT_NAME);

            Producer producer = new Producer(zbusBroker, EndPointConstant.ZBUS_MQ + "@" + tenant);
            producer.createMQ();    //确定为创建消息队列需要显示调用
            Message message = new Message();
            message.setHead("event", event);
            message.setHead("tenant", tenant);
            message.setMethod("POST");
            message.setBody(msg);
            producer.sendSync(message);
        } catch (IOException | InterruptedException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
    }
}
