package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.AlarmTargetCatalog;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.ims.entity.common.Tenant;
import com.bocloud.ims.entity.common.User;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.Cluster;
import com.bocloud.ims.entity.resource.ResourceAlarm;
import com.bocloud.ims.interfaces.resource.ResourceAlarmService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ClusterRepository;
import com.bocloud.ims.repository.resource.ResourceAlarmRepository;
import com.bocloud.ims.service.internal.SmsTenantService;
import com.bocloud.ims.service.internal.SmsUserService;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author songsong
 */
@Service("resourceAlarmService")
public class ResourceAlarmServiceImpl implements ResourceAlarmService {

	private static Logger logger = LoggerFactory.getLogger(ResourceAlarmServiceImpl.class);
	@Autowired
	private ResourceAlarmRepository alarmRepository;
	@Autowired
	private SmsUserService smsUserService;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private ClusterRepository clusterRepository;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private SmsTenantService smsTenantService;

	@Override
	public BocloudResult<GridBean<ResourceAlarm>> list(Pager pager)
			throws Exception {
		List<ResourceAlarm> list = null;
		List<SimpleBean> beans = null;
		int total = 0;
		GridBean gridBean = null;
		try {

			int page = pager.getPage();
			int rows = pager.getRows();
			List<Param> params = pager.getParams();
			Map<String, String> sorter = pager.getSorter();
			boolean simple = pager.getSimple();

			if (null == params) {
				params = new ArrayList<>();
			}
			if (null == sorter) {
				sorter = Maps.newHashMap();
			}
			sorter.put("gmtTrigger", Common.ONE);// edit 触发时间排序
			total = this.alarmRepository.count(params);
			if (simple) {
				beans = this.alarmRepository.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				list = this.alarmRepository.list(page, rows, params, sorter);
				// 设置告警目标名称
				for (ResourceAlarm alarm : list) {
					if (null != alarm.getType() && null != alarm.getEventAlarm() && alarm.getEventAlarm()) {
						if (alarm.getType().equals(AlarmTargetCatalog.VENDOR.name())) {
							CloudVendor vendor = cloudVendorRepository.query(Long.valueOf(alarm.getTarget()));
							if (null != vendor) {
								alarm.setTargetName(vendor.getName());
							}
							String alarmVal = alarm.getAlarmVal();
							if (StringUtils.isNotEmpty(alarmVal)) {
								alarm.setAlarmVal(Double.valueOf(alarmVal) * 100 + "%");
							}
						} else if (alarm.getType().equals(AlarmTargetCatalog.CLUSTER.name())) {
							Cluster cluster = clusterRepository.query(Long.valueOf(alarm.getTarget()));
							if (null != cluster) {
								alarm.setTargetName(cluster.getName());
							}
							String alarmVal = alarm.getAlarmVal();
							if (StringUtils.isNotEmpty(alarmVal)) {
								alarm.setAlarmVal(Double.valueOf(alarmVal) * 100 + "%");
							}
						} else if ("VM".equals(alarm.getType())) {
							alarm.setTargetName(alarm.getTarget() == null ? null : alarm.getTarget().toString());
						} else if ("FLOW".equals(alarm.getType())) {
							alarm.setTargetName(alarm.getTarget() == null ? null : alarm.getTarget().toString());
						} else if ("PMINSTALL".equals(alarm.getType())) {
							alarm.setTargetName(alarm.getTarget() == null ? null : alarm.getTarget().toString());
						} else if ("SCP".equals(alarm.getType())) {
							alarm.setTargetName(alarm.getTarget() == null ? null : alarm.getTarget().toString());
						} else if ("TENANT".equals(alarm.getType())) {
							BocloudResult<Tenant> result = smsTenantService.detail(alarm.getTarget());
							if (result.isSuccess()) {
								alarm.setTargetName(result.getData().getName());
							} else {
								logger.error("从Soc获取租户信息失败:{}{}", result.getMessage(), result.getErrorMsg());
							}
							try {
								String alarmVal = alarm.getAlarmVal();
								if (StringUtils.isNotEmpty(alarmVal)) {
									alarm.setAlarmVal(Double.valueOf(alarmVal) * 100 + "%");
								}
							} catch (Exception e) {
								logger.error("获取租户告警值失败:", e);
							}
						}
					}
				}
			}
			gridBean = GridHelper.getBean(page, rows, total, list);
			return new BocloudResult<>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("List alarm fail:", e);
			return new BocloudResult<>(false, "查询失败", null, null);
		}
	}

	@Override
	public BocloudResult<ResourceAlarm> create(ResourceAlarm alarm) {
		try {
			alarm.setStatus(BocloudStatus.Alarm.UNCONFIRMED.name());
			alarm.setCreatorId(1L);
			alarm.setGmtCreate(new Date());
			alarm.setDeleted(false);
			alarmRepository.save(alarm);
			return new BocloudResult<>(true, alarm, "创建成功!");
		} catch (Exception e) {
			logger.error("create alarm error:", e);
			return new BocloudResult<>(false, "创建失败!");
		}
	}

	@Override
	public BocloudResult<ResourceAlarm> detail(Long id) {
		try {
			ResourceAlarm alarm = alarmRepository.query(id);
			if (null == alarm) {
				return new BocloudResult<>(false, "数据不存在");
			}
			return new BocloudResult<>(true, alarm, "查询详情成功");
		} catch (Exception e) {
			logger.error("query alarm detail fail:", e);
			return new BocloudResult<>(false, "查询详情失败", "", "");
		}
	}

	@Override
	public BocloudResult<String> remove(Long id, Long userId) {
		String path = ResourceAlarm.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			ResourceAlarm object = this.alarmRepository.query(id);
			Assert.notNull(object, "告警数据不存在！");
			alarmRepository.delete(id, userId);
			return new BocloudResult<>(true, "删除成功");
		} catch (Exception e) {
			logger.error("Remove alarm error:{}", e.getMessage());
			return new BocloudResult<>(false, "删除失败", null, null);
		}
	}

	@Override
	public List<ResourceAlarm> unconfirms(Boolean existRuleId) {
		try {
			return this.alarmRepository.unconfirms(existRuleId);
		} catch (Exception e) {
			logger.error("Query alarm unconfim list error：", e);
			return Lists.newArrayList();
		}
	}

	@Override
	public BocloudResult<String> confirm(Long id, Long userId) {
		String path = ResourceAlarm.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			ResourceAlarm object = this.alarmRepository.query(id);
			Assert.notNull(object, "告警数据不存在！");
			BocloudResult<User> result = smsUserService.detail(userId);
			Assert.isTrue(result.isSuccess(), result.getMessage());
			User user = result.getData();
			Assert.notNull(user, "用户不存在，请联系管理员");
			alarmRepository.updateStatus(id, userId, BocloudStatus.Alarm.CONFIRMED.name(), user.getAccount());
			return new BocloudResult<>(true, "告警已确认", "", "");
		} catch (Exception e) {
			logger.error("Remove alarm error:{}", e.getMessage());
			return new BocloudResult<>(false, "确认告警失败", "", "");
		}
	}

	@Override
	public BocloudResult<String> action(Long id, String action, String params, Long userId) {
		JSONObject object = new JSONObject();
		if (!StringUtils.isEmpty(params)) {
			object = JSONObject.parseObject(params);
			if (null == object) {
				return new BocloudResult<>(false, "参数格式错误");
			}
		}
		switch (action) {
		case "confirm":
			return this.confirm(id, userId);
		case "solve":
			return this.solve(id, userId, object.getString("dealResult"));
		case "updatelevel":
			return this.updateLevel(JSONObject.parseObject(params, ResourceAlarm.class));
		default:
			return new BocloudResult<>(false, "暂不支持");
		}
	}

	@Override
	public BocloudResult<String> solve(Long id, Long userId, String dealResult) {
		String path = ResourceAlarm.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			ResourceAlarm object = this.alarmRepository.query(id);
			Assert.notNull(object, "告警数据不存在！");
			BocloudResult<User> result = smsUserService.detail(userId);
			Assert.isTrue(result.isSuccess(), result.getMessage());
			User user = result.getData();
			Assert.notNull(user, "用户不存在，请联系管理员");
			alarmRepository.solve(id, userId, user.getAccount(), dealResult);
			return new BocloudResult<>(true, "解决告警成功", "", "");
		} catch (Exception e) {
			logger.error("solve alarm error:{}", e.getMessage());
			return new BocloudResult<>(false, "解决告警失败", "", "");
		}
	}

	@Override
	public BocloudResult<String> updateLevel(ResourceAlarm alarm) {
		String path = ResourceAlarm.class.getSimpleName() + "_" + alarm.getId();
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			ResourceAlarm object = this.alarmRepository.query(alarm.getId());
			Assert.notNull(object, "告警数据不存在！");
			object.setLevel(alarm.getLevel());
			alarmRepository.update(object);
			return new BocloudResult<>(true, "告警级别已更新");
		} catch (Exception e) {
			logger.error("Update alarm level error:{}", e.getMessage());
			return new BocloudResult<>(false, "告警级别更新失败");
		}
	}

	@Override
	public BocloudResult<String> removeByTarget(String target, String type) {
		try {
			boolean flag = alarmRepository.removeByTarget(target, type);
			if (flag) {
				return new BocloudResult<>(true, "删除成功");
			} else {
				return new BocloudResult<>(false, "删除失败");
			}
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult<>(false, "删除失败");
		}
	}
}
