package com.kuyuntech.vrv.coreservice.service.core.impl;


import com.kuyuntech.vrv.coreapi.service.core.DeviceService;
import com.kuyuntech.vrv.coreapi.service.core.GatewayService;
import com.kuyuntech.vrv.coreapi.service.core.OperatorService;
import com.kuyuntech.vrv.coreapi.service.core.ProjectService;
import com.kuyuntech.vrv.coreservice.dao.core.DeviceDao;
import com.kuyuntech.vrv.coreservice.dao.core.GatewayDao;
import com.kuyuntech.vrv.coreservice.dao.core.OperatorDao;
import com.kuyuntech.vrv.coreservice.dao.core.ProjectDao;
import com.kuyuntech.vrv.coreservice.domain.core.Gateway;
import com.kuyuntech.vrv.coreservice.domain.core.Operator;
import com.kuyuntech.vrv.coreservice.domain.core.Project;
import org.hibernate.criterion.MatchMode;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.kuyuntech.vrv.coreapi.bean.core.DeviceBean;
import com.kuyuntech.vrv.coreservice.domain.core.Device;
import com.wbspool.fastboot.core.common.bean.PagerBean;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;

import java.util.ArrayList;

import org.hibernate.criterion.Order;
import com.wbspool.fastboot.core.jpa.service.AbstractFastbootService;
import org.springframework.util.Assert;

import static com.wbspool.fastboot.core.jpa.constant.DataValidTypes.*;


/**
 * DeviceService
 */
@Service("deviceService")
@Transactional(rollbackFor = Exception.class, transactionManager = "vrvCoreServiceTransactionManager")
public class DeviceServiceImpl extends AbstractFastbootService<Device, DeviceBean> implements DeviceService {

    private static final Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class);

    @Autowired
    DeviceDao deviceDao;
    @Autowired
    OperatorDao operatorDao;
    @Autowired
    ProjectDao projectDao;
    @Autowired
    GatewayDao gatewayDao;


    @Override
    public DeviceBean add(DeviceBean deviceBean) {

        Device device = new Device();
        beanToDomain(deviceBean, device, "id");

        String operatorNumber = deviceBean.getOperatorNumber();
        String projectNumber = deviceBean.getProjectNumber();
        String gatewayNumber = deviceBean.getGatewayNumber();

        if ((operatorNumber == null || operatorNumber == "") && (projectNumber == null || projectNumber == "") && (gatewayNumber == null || gatewayNumber == "")) {

            deviceDao.save(device);

            domainToBean(device, deviceBean);

            return deviceBean;
        }

        Operator operator = operatorDao.findByNumberAndValid(operatorNumber, VALID);
        Project project = projectDao.findByNumberAndValid(projectNumber, VALID);
        Gateway gateway = gatewayDao.findByNumberAndValid(gatewayNumber, VALID);

        device.setOperatorCode(operator.getCode());
        device.setProjectCode(project.getCode());
        device.setGatewayCode(gateway.getCode());

        deviceDao.save(device);

        domainToBean(device, deviceBean);

        return deviceBean;

    }

    @Override
    public DeviceBean update(DeviceBean deviceBean) {

        if (deviceBean == null) {
            return null;
        }


        Device device = deviceDao.findByCodeAndValid(deviceBean.getCode(), VALID);


        if (device == null) {
            return null;
        }

        beanToDomain(deviceBean, device, "id", "code", "version", "createTime", "updateTime", "valid");

        String operatorNumber = deviceBean.getOperatorNumber();
        String projectNumber = deviceBean.getProjectNumber();
        String gatewayNumber = deviceBean.getGatewayNumber();

        Operator operator = operatorDao.findByNumberAndValid(operatorNumber, VALID);
        Project project = projectDao.findByNumberAndValid(projectNumber, VALID);
        Gateway gateway = gatewayDao.findByNumberAndValid(gatewayNumber, VALID);

        if (operatorNumber == null || operatorNumber == "") {

            deviceDao.save(device);

            domainToBean(device, deviceBean);

            return deviceBean;
        }
        if (projectNumber == null || projectNumber == "") {

            deviceDao.save(device);

            domainToBean(device, deviceBean);

            return deviceBean;
        }
        if (gatewayNumber == null || gatewayNumber == "") {

            deviceDao.save(device);

            domainToBean(device, deviceBean);

            return deviceBean;
        }


        device.setOperatorCode(operator.getCode());
        device.setProjectCode(project.getCode());
        device.setGatewayCode(gateway.getCode());

        deviceDao.save(device);

        domainToBean(device, deviceBean);

        return deviceBean;
    }

    @Override
    public DeviceBean delete(DeviceBean deviceBean) {

        if (deviceBean == null) {
            return null;
        }


        Device device = deviceDao.findByCodeAndValid(deviceBean.getCode(), VALID);


        if (device == null) {
            return null;
        }


        device.setValid(INVALID);
        deviceDao.save(device);


        domainToBean(device, deviceBean);

        return deviceBean;
    }

    @Override
    public DeviceBean find(DeviceBean deviceBean) {
        if (deviceBean == null) {
            return null;
        }


        Device device = deviceDao.findByCodeAndValid(deviceBean.getCode(), VALID);


        if (device == null) {
            return null;
        }
        BeanUtils.copyProperties(device, deviceBean);
        return deviceBean;
    }

    @Override
    public DeviceBean find(String code) {
        return this.find(DeviceBean.builder().code(code).build());
    }

    @Override
    public List<DeviceBean> findAll(DeviceBean deviceBean, PagerBean pagerBean) {
        List<DeviceBean> deviceBeans = new ArrayList<>();
        DetachedCriteria detachedCriteria = createListCriteria(deviceBean);
        List<Device> devices = deviceDao.findAll(detachedCriteria, pagerBean);
        for (Device device : devices) {
            DeviceBean deviceBeanTemp = new DeviceBean();
            domainToBean(device, deviceBeanTemp);
            deviceBeans.add(deviceBeanTemp);
        }
        return deviceBeans;
    }

    @Override
    public List<DeviceBean> findAll(DeviceBean deviceBean) {
        return this.findAll(deviceBean, null);
    }

    @Override
    public Long countAll(DeviceBean deviceBean) {
        DetachedCriteria detachedCriteria = createListCriteria(deviceBean);
        return deviceDao.countAll(detachedCriteria);
    }

    @Override
    public PagerBean<DeviceBean> findPager(DeviceBean deviceBean, PagerBean pagerBean) {
        List<DeviceBean> deviceBeans = this.findAll(deviceBean, pagerBean);
        Long count = this.countAll(deviceBean);
        PagerBean<DeviceBean> devicePageBean = new PagerBean<>();
        BeanUtils.copyProperties(pagerBean, devicePageBean);
        devicePageBean.setItemCount(count.intValue());
        devicePageBean.init();
        devicePageBean.setItems(deviceBeans);
        return devicePageBean;
    }

    /**
     * 创建列表查询条件
     *
     * @param deviceBean 查询参数
     * @return
     */
    private static DetachedCriteria createListCriteria(DeviceBean deviceBean) {
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Device.class);

        if (deviceBean != null) {
            if (StringUtils.isNotBlank(deviceBean.getOperatorNumber())) {
                detachedCriteria.add(Restrictions.like("operatorNumber", deviceBean.getOperatorNumber(), MatchMode.ANYWHERE));
            }
            if (StringUtils.isNotBlank(deviceBean.getProjectNumber())) {
                detachedCriteria.add(Restrictions.like("projectNumber", deviceBean.getProjectNumber(), MatchMode.ANYWHERE));
            }
            if (StringUtils.isNotBlank(deviceBean.getGatewayNumber())) {
                detachedCriteria.add(Restrictions.like("gatewayNumber", deviceBean.getGatewayNumber(), MatchMode.ANYWHERE));
            }
            if (StringUtils.isNotBlank(deviceBean.getSn())) {
                detachedCriteria.add(Restrictions.like("sn", deviceBean.getSn(), MatchMode.ANYWHERE));
            }
            if (StringUtils.isNotBlank(deviceBean.getIp())) {
                detachedCriteria.add(Restrictions.like("ip", deviceBean.getIp(), MatchMode.ANYWHERE));
            }
            if (StringUtils.isNotBlank(deviceBean.getName())) {
                detachedCriteria.add(Restrictions.like("name", deviceBean.getName(), MatchMode.ANYWHERE));
            }
            if (StringUtils.isNotBlank(deviceBean.getType())) {
                detachedCriteria.add(Restrictions.like("type", deviceBean.getType(), MatchMode.ANYWHERE));
            }
            if (StringUtils.isNotBlank(deviceBean.getDeviceStatus())) {
                detachedCriteria.add(Restrictions.eq("deviceStatus", deviceBean.getDeviceStatus()));
            }
            if (StringUtils.isNotBlank(deviceBean.getGatewayCode())) {
                detachedCriteria.add(Restrictions.eq("gatewayCode", deviceBean.getGatewayCode()));
            }

        }

        detachedCriteria.add(Restrictions.eq("valid", VALID));
        return detachedCriteria;
    }


    @Override
    public void batchDelete(List<DeviceBean> deviceBean) {
        if (deviceBean.isEmpty()) {
            return;
        }
        List<String> codes = new ArrayList<>();
        deviceBean.forEach((e) -> {
            codes.add(e.getCode());
        });
        batchDeleteByCodes(codes);

    }


    @Override
    public void batchDeleteByCodes(List<String> codes) {

        if (codes.isEmpty()) {
            return;
        }

        for (String code : codes) {
            Assert.notNull(this.delete(DeviceBean.builder().code(code).build()), "batch delete by codes error! ");
        }

    }


}
