package com.zhongshu.card.server.core.service.devices;

import com.beust.jcommander.internal.Lists;
import com.github.microservice.components.data.base.util.PageEntityUtil;
import com.github.microservice.models.device.DeviceInfoSyncParam;
import com.github.microservice.net.ResultContent;
import com.github.microservice.net.ResultMessage;
import com.zhongshu.card.client.model.devices.*;
import com.zhongshu.card.client.model.org.OrganizationMiniModel;
import com.zhongshu.card.client.model.org.OrganizationPayInfoModel;
import com.zhongshu.card.client.model.org.UserJoinBusOrgModel;
import com.zhongshu.card.client.model.school.AreaSimpleModel;
import com.zhongshu.card.client.service.school.DeviceInfoService;
import com.zhongshu.card.client.type.OnLineState;
import com.zhongshu.card.server.core.dao.devices.DeviceInfoDao;
import com.zhongshu.card.server.core.dao.org.OrganizationDao;
import com.zhongshu.card.server.core.dao.school.AreaDao;
import com.zhongshu.card.server.core.dataConfig.DeviceConfig;
import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
import com.zhongshu.card.server.core.domain.devices.DeviceProduct;
import com.zhongshu.card.server.core.domain.devices.DeviceProductBindDevice;
import com.zhongshu.card.server.core.domain.devices.permiss.DevicePermiss;
import com.zhongshu.card.server.core.domain.org.Organization;
import com.zhongshu.card.server.core.domain.school.Area;
import com.zhongshu.card.server.core.service.base.CommonService;
import com.zhongshu.card.server.core.service.base.SuperService;
import com.zhongshu.card.server.core.service.devices.deviceProduct.DeviceProductBindDeviceService;
import com.zhongshu.card.server.core.service.devices.permiss.DevicePermissEventService;
import com.zhongshu.card.server.core.service.permissVerify.DevicePermissVerifyService;
import com.zhongshu.card.server.core.service.org.OrganizationServiceImpl;
import com.zhongshu.card.server.core.service.orgManager.OrganizationManagerServiceImpl;
import com.zhongshu.card.server.core.service.paySetting.OrgPaySettingJudgmentService;
import com.zhongshu.card.server.core.service.school.AreaServiceImpl;
import com.zhongshu.card.server.core.util.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author TRX
 * @date 2024/6/14
 */
@Slf4j
@Service
public class DeviceInfoServiceImpl extends SuperService implements DeviceInfoService {

    @Autowired
    private DeviceInfoDao deviceInfoDao;

    @Autowired
    private AreaServiceImpl areaService;

    @Autowired
    private AreaDao areaDao;

    @Autowired
    private OrganizationServiceImpl organizationServiceImpl;

    @Autowired
    private OrganizationDao organizationDao;

    @Autowired
    private OrganizationManagerServiceImpl organizationManagerService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private OrgPaySettingJudgmentService orgPaySettingJudgmentService;

    @Autowired
    private DevicePermissEventService devicePermissEventService;

    @Autowired
    private DeviceProductBindDeviceService deviceProductBindDeviceService;

    @Autowired
    private DevicePermissVerifyService devicePermissVerifyService;

    /**
     * 同步设备 （设备基础信息） 从物联网来
     *
     * @param param
     * @return
     */
    @Override
    public ResultContent syncDeviceInfo(DeviceInfoSyncParam param) {
        Assert.hasText(param.getDeviceId(), "deviceId不能为空");
        if (StringUtils.isEmpty(param.getProjectInfoCode())) {
            return ResultContent.buildFail("projectInfoCode不能为空");
        }
        Organization projectInfo = null;
        if (StringUtils.isNotEmpty(param.getProjectInfoCode())) {
            projectInfo = organizationDao.findTopByCode(param.getProjectInfoCode());
            if (ObjectUtils.isEmpty(projectInfo)) {
                return ResultContent.buildFail("所属项目未找到，同步失败");
            }
        }

        // 设备号
        String deviceId = param.getDeviceId();
        DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
        if (ObjectUtils.isNotEmpty(deviceInfo)) {
            // 编辑
            BeanUtils.copyProperties(param, deviceInfo, "id");
        } else {
            // 新增
            deviceInfo = new DeviceInfo();
            initEntityNoCheckOid(deviceInfo);
            BeanUtils.copyProperties(param, deviceInfo, "id");
        }
        // 所属项目信息
        if (ObjectUtils.isNotEmpty(projectInfo)) {
            deviceInfo.setProjectOid(projectInfo.getOid());
            deviceInfo.setAboutOid(projectInfo.getOid());
            deviceInfo.setAboutAuthType(projectInfo.getAuthType());
            deviceInfo.setProjectInfoName(projectInfo.getName());
        }

        // 设备的别名
        if (StringUtils.isEmpty(deviceInfo.getNickName())) {
            deviceInfo.setNickName(deviceInfo.getDeviceName());
        }
        deviceInfoDao.save(deviceInfo);

        // 修改其他的关联设备信息
        HashMap<String, Object> where = new HashMap<>();
        where.put("deviceId", param.getDeviceId());

        HashMap<String, Object> bindMap = new HashMap<>();
        bindMap.put("gateWayId", deviceInfo.getGateWayId());
        commonService.updateData(where, bindMap, DevicePermiss.class.getSimpleName());
        return ResultContent.buildSuccess();
    }

    /**
     * 添加-编辑设备
     *
     * @param param
     * @return
     */
    @Override
    public ResultContent addDeviceInfo(DeviceInfoParam param) {
        initDefaultUserAndOidNoExcept(param);
        Assert.hasText(param.getDeviceId(), "deviceId不能为空");
        String deviceId = param.getDeviceId();
        DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
        if (ObjectUtils.isNotEmpty(deviceInfo)) {
        } else {
            deviceInfo = new DeviceInfo();
        }
        BeanUtils.copyProperties(param, deviceInfo, "id");
        deviceInfo.setProjectInfoName(organizationServiceImpl.getOrgNameByCode(param.getProjectInfoCode()));
        deviceInfoDao.save(deviceInfo);

        devicePermissEventService.sendDeviceChangeEvent(deviceInfo.getDeviceId(), deviceInfo.getProjectOid(), "addDeviceInfo");
        return ResultContent.buildSuccess();
    }

    /**
     * 设备分页列表
     *
     * @param param
     * @param pageable
     * @return
     */
    @Override
    public ResultContent<Page<DeviceInfoModel>> page(DeviceInfoSearch param, Pageable pageable) {
        // 完善所属项目
        String projectOid = param.getProjectOid();
        if (StringUtils.isNotEmpty(projectOid)) {
            Organization organization = organizationDao.findTopByOid(projectOid);
            if (ObjectUtils.isEmpty(organization)) {
                return ResultContent.buildFail("projectOid不存在");
            }
            //TODO 放开查询所有的设备
            param.setProjectInfoCode(organization.getCode());
        }
        Page<DeviceInfo> page = deviceInfoDao.page(pageable, param);
        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toModel));
    }

    /**
     * 产品绑定设备（可见的设备列表）
     *
     * @param param
     * @param pageable
     * @return
     */
    @Override
    public ResultContent<Page<DeviceInfoModel>> pageBindDevices(DeviceInfoSearch param, Pageable pageable) {
        // 去掉已绑定的设备
        param.setNotInDeviceIds(deviceProductBindDeviceService.getAllBindDeviceIds(param.getProjectOid()));
        return page(param, pageable);
    }

    @Override
    public ResultContent<Page<DeviceInfoModel>> busPage(DeviceInfoSearch param, Pageable pageable) {
        // 完善所属项目
        String projectOid = param.getProjectOid();
        if (StringUtils.isEmpty(projectOid)) {
            projectOid = getCurrentProjectOid();
        }
        param.setProjectOid(projectOid);
        if (StringUtils.isEmpty(projectOid)) {
            return ResultContent.buildFail("projectOid不能为空");
        }

        List<String> shopOids = new ArrayList<String>();
        if (param.getIsAllBusinessMain() != null && param.getIsAllBusinessMain()) {
            List<UserJoinBusOrgModel> list = organizationServiceImpl.getUserAboutShopList(getCurrentUserId());
            if (ObjectUtils.isNotEmpty(list)) {
                shopOids = list.stream().map(it -> it.getBusOid()).collect(Collectors.toList());
            }
        } else {
            if (StringUtils.isNotEmpty(param.getShopOid())) {
                shopOids.add(param.getShopOid());
            }
        }
        if (ObjectUtils.isEmpty(shopOids)) {
            return ResultContent.buildFail("关联商户不存在");
        }
        param.setShopOids(shopOids);
        Page<DeviceInfo> page = deviceInfoDao.page(pageable, param);
        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toModel));
    }

    /**
     * 删除设备
     *
     * @param id
     * @return
     */
    @Override
    public ResultContent deleteDeviceInfo(String id) {
        DeviceInfo deviceInfo = deviceInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(deviceInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        deviceInfoDao.delete(deviceInfo);
        return ResultContent.buildSuccess();
    }

    /**
     * 得到设备详情
     *
     * @param id
     * @return
     */
    @Override
    public ResultContent<DeviceInfoMoreModel> getDeviceDetail(String id) {
        DeviceInfo deviceInfo = deviceInfoDao.findTopById(id);
        if (ObjectUtils.isEmpty(deviceInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        DeviceInfoMoreModel model = toMoreModel(deviceInfo);
        return ResultContent.buildSuccess(model);
    }

    @Override
    public ResultContent<DeviceInfoMoreModel> getDeviceDetailByDeviceId(String deviceId) {
        DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
        DeviceInfoMoreModel model = null;
        if (ObjectUtils.isNotEmpty(deviceInfo)) {
            model = toMoreModel(deviceInfo);
        }
        return ResultContent.buildSuccess(model);
    }

    @Override
    public ResultContent<List<DeviceInfoMoreModel>> getDeviceDetailByDeviceIdLike(String deviceId) {
        List<DeviceInfoMoreModel> models = new ArrayList<>();
        if (StringUtils.isNotEmpty(deviceId)) {
            List<DeviceInfo> list = deviceInfoDao.findTop10ByDeviceIdLike(deviceId);
            if (ObjectUtils.isNotEmpty(list)) {
                models = list.stream().map(this::toMoreModel).collect(Collectors.toList());
            }
        }
        return ResultContent.buildSuccess(models);
    }

    /**
     * 判断当前用户关于设备的信息 和 是否有权限
     *
     * @param deviceId
     * @return
     */
    @Override
    public ResultContent<DeviceInfoServeModel> getDeviceDetailAndPer(String deviceId) {
        DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);

        // 判断当前用户是否有设备的权限
        String userId = getCurrentUserId();
        ResultContent content = devicePermissVerifyService.verifyDevice(userId, deviceId, null);
        if (content.isFailed()) {
            return ResultContent.buildFail(content.getMsg());
        }

        DeviceInfoServeModel model = null;
        if (ObjectUtils.isNotEmpty(deviceInfo)) {
            model = toServeModel(deviceInfo);
            model.setPayOrgInfo(getDeviceReceiveOrgInfo(deviceId));
        }
        return ResultContent.buildSuccess(model);
    }

    public DeviceInfoMoreModel toMoreModel(DeviceInfo entity) {
        DeviceInfoMoreModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new DeviceInfoMoreModel();
            DeviceInfoModel deviceInfoModel = toModel(entity);
            BeanUtils.copyProperties(deviceInfoModel, model);
        }
        return model;
    }

    /**
     * 设备包含的 商品、、收款机构等信息 转换
     *
     * @param entity
     * @return
     */
    public DeviceInfoServeModel toServeModel(DeviceInfo entity) {
        DeviceInfoServeModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new DeviceInfoServeModel();
            DeviceInfoModel deviceInfoModel = toModel(entity);
            BeanUtils.copyProperties(deviceInfoModel, model);
        }
        return model;
    }

    /**
     * @param param
     * @return
     */
    public ResultContent updateDevice(DeviceBindAreaParam param) {
        DeviceInfo deviceInfo = deviceInfoDao.findTopById(param.getId());
        if (ObjectUtils.isEmpty(deviceInfo)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
        }

        Area area = null;
        List<String> strings = new ArrayList<>();
        // 修改设备 只能绑定 区域 所属机构等信息
        if (StringUtils.isNotEmpty(param.getAreaId())) {
            area = areaDao.findTopById(param.getAreaId());
            if (ObjectUtils.isEmpty(area)) {
                return ResultContent.buildFail("区域信息不存在");
            }
            strings = areaService.getAllParents(param.getAreaId());
        }
        if (ObjectUtils.isNotEmpty(area)) {
            deviceInfo.setArea(area);
            deviceInfo.setAreaId(area.getId());
        } else {
            deviceInfo.setArea(null);
            deviceInfo.setAreaId(null);
        }
        deviceInfo.setAreaPaths(String.join("/", strings));
        deviceInfo.setDeviceName(param.getDeviceName());

        // 设备收款机构
        Organization organization = null;
        if (StringUtils.isNotEmpty(param.getBeLongOid())) {
            organization = organizationDao.findTopByOid(param.getBeLongOid());
            if (ObjectUtils.isEmpty(organization)) {
                return ResultContent.buildFail("所属机构不存在");
            }
            deviceInfo.setBeLongName(organization.getName());
        }
        deviceInfo.setOrganization(organization);
        deviceInfo.setBeLongOid(param.getBeLongOid());

        // 设备所属机构
        Organization beToOrganization = null;
        if (StringUtils.isNotEmpty(param.getBeToOid())) {
            beToOrganization = organizationDao.findTopByOid(param.getBeToOid());
        }
        if (ObjectUtils.isNotEmpty(beToOrganization)) {
            deviceInfo.setAboutOid(beToOrganization.getOid());
            deviceInfo.setBeToName(beToOrganization.getName());
        } else {
            deviceInfo.setBeToName("");
            deviceInfo.setBeToOid("");
        }

        Organization billOrganization = null;
        if (StringUtils.isNotEmpty(param.getBillOid())) {
            billOrganization = organizationDao.findTopByOid(param.getBillOid());
        }
        if (ObjectUtils.isNotEmpty(billOrganization)) {
            deviceInfo.setBillOid(billOrganization.getOid());
            deviceInfo.setBillName(billOrganization.getName());
        } else {
            deviceInfo.setBillName("");
            deviceInfo.setBillOid("");
        }

        if (StringUtils.isEmpty(deviceInfo.getProjectOid())) {
            Organization project = organizationDao.findTopByCode(deviceInfo.getProjectInfoCode());
            if (ObjectUtils.isNotEmpty(project)) {
                deviceInfo.setProjectOid(project.getOid());
            }
        }

        if (ObjectUtils.isNotEmpty(organization)) {
            // 检查设备关联的机构，是否可以收款
            ResultContent resultContent = orgPaySettingJudgmentService.checkOrgPaySetting(deviceInfo.getProjectOid(), deviceInfo.getBeLongOid());
            if (resultContent.isFailed()) {
                return ResultContent.buildFail(resultContent.getMsg());
            }
        }
        deviceInfo.setAboutInfo(param.getAboutInfo());
        deviceInfo.setNickName(param.getNickName());
        deviceInfoDao.save(deviceInfo);

        devicePermissEventService.sendDeviceChangeEvent(deviceInfo.getDeviceId(), deviceInfo.getProjectOid(), "updateDevice");
        return ResultContent.buildSuccess();
    }

    /**
     * 启动平台时检查设备 （有些设备没有使用了，没有改变在线状态）
     */
    public void initCheckDeviceOnLine() {
        List<DeviceInfo> list = deviceInfoDao.findAll();
        if (ObjectUtils.isNotEmpty(list)) {
            long maxTime = DeviceConfig.maxInitCheckDeviceLineStateTime;
            List<DeviceInfo> deviceInfos = new ArrayList<>();
            for (DeviceInfo deviceInfo : list) {
                if (deviceInfo.getLastOnlineTime() == null || (System.currentTimeMillis() - deviceInfo.getLastOnlineTime()) > maxTime) {
                    deviceInfo.setOnLineState(OnLineState.OffLine);
                    deviceInfos.add(deviceInfo);
                }
            }
            if (ObjectUtils.isNotEmpty(deviceInfos)) {
                deviceInfoDao.saveAll(deviceInfos);
            }
        }
    }

    public List<DeviceInfo> getDevicesByDeviceIds(List<String> deviceIds) {
        if (ObjectUtils.isNotEmpty(deviceIds)) {
            return deviceInfoDao.findByDeviceIdIn(deviceIds);
        }
        return Lists.newArrayList();
    }

    /**
     * 得到 设备的收款机构
     *
     * @param deviceId
     * @return
     */
    public OrganizationPayInfoModel getDeviceReceiveOrgInfo(String deviceId) {
        DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
        if (ObjectUtils.isEmpty(deviceInfo)) {
            return null;
        }
        String beLongOid = deviceInfo.getBeLongOid();
        if (StringUtils.isEmpty(beLongOid)) {
            // 查询设备绑定的产品 关联的 收款机构
            DeviceProduct deviceProduct = deviceProductBindDeviceService.getDeviceBindProductInfo(deviceInfo);
            if (deviceProduct != null) {
                beLongOid = deviceProduct.getBeLongOid();
            }
        }
        if (StringUtils.isNotEmpty(beLongOid)) {
            return organizationManagerService.toPayInfoModel(organizationServiceImpl.getOrgByOid(beLongOid));
        }
        return null;
    }

    public DeviceInfoModel getDeviceInfoModel(String deviceId) {
        if (StringUtils.isEmpty(deviceId)) {
            return null;
        }
        DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
        if (ObjectUtils.isNotEmpty(deviceInfo)) {
            return toModel(deviceInfo);
        }
        return null;
    }

    /**
     * 设备基础信息
     *
     * @param entity
     * @return
     */
    public DeviceInfoModel toModel(DeviceInfo entity) {
        DeviceInfoModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new DeviceInfoModel();
            // 收款机构信息
            OrganizationMiniModel miniModel = organizationManagerService.toMiniModel(entity.getOrganization());
            model.setOrganization(miniModel);

            // 所属机构
            OrganizationMiniModel beToMiniModel = organizationManagerService.toMiniModel(organizationServiceImpl.getOrgByOid(entity.getBeToOid()));
            model.setBeToOrganization(beToMiniModel);

            OrganizationMiniModel billMiniModel = organizationManagerService.toMiniModel(organizationServiceImpl.getOrgByOid(entity.getBillOid()));
            model.setBillOrganization(billMiniModel);


            BeanUtils.copyProperties(entity, model);
            model.setProjectInfoName(organizationServiceImpl.getOrgNameByCode(entity.getProjectInfoCode()));

            // 所属区域信息
            List<AreaSimpleModel> areaModels = areaService.getParents(entity.getArea());
            if (ObjectUtils.isNotEmpty(areaModels)) {
                model.setArea(areaModels.get(0));
                Collections.reverse(areaModels);
                List<String> areaNames = areaModels.stream().map(it -> it.getName()).collect(Collectors.toList());
                model.setAreaAllName(String.join("/", areaNames));
            }
        }
        return model;
    }

    public DeviceInfoStoreModel toStoreModel(DeviceInfo entity) {
        DeviceInfoStoreModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new DeviceInfoStoreModel();
            BeanUtils.copyProperties(entity, model);

            model.setProjectInfoName(organizationServiceImpl.getOrgNameByCode(entity.getProjectInfoCode()));

            // 所属区域信息
            List<AreaSimpleModel> areaModels = areaService.getParents(entity.getArea());
            if (ObjectUtils.isNotEmpty(areaModels)) {
                model.setArea(areaModels.get(0));
                Collections.reverse(areaModels);
                List<String> areaNames = areaModels.stream().map(it -> it.getName()).collect(Collectors.toList());
                model.setAreaAllName(String.join("/", areaNames));
            }
        }
        return model;
    }

    /**
     * 查询设备的 收款 机构
     *
     * @param deviceId
     * @return
     */
    public Organization getDeviceReceiveOrganization(String deviceId) {
        if (StringUtils.isNotEmpty(deviceId)) {
            DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
            return getDeviceReceiveOrganization(deviceInfo);
        }
        return null;
    }

    /**
     * 查询设备的 收款 机构
     *
     * @param deviceInfo
     * @return
     */
    public Organization getDeviceReceiveOrganization(DeviceInfo deviceInfo) {
        Organization organization = null;
        if (ObjectUtils.isNotEmpty(deviceInfo)) {
            String oid = deviceInfo.getBeLongOid();

            if (StringUtils.isEmpty(oid)) {
                // 查找产品绑定的产品
                DeviceProductBindDevice bindInfo = deviceProductBindDeviceService.getDeviceBindInfo(deviceInfo);
                if (ObjectUtils.isNotEmpty(bindInfo) && bindInfo.getDeviceProduct() != null) {
                    oid = bindInfo.getDeviceProduct().getBeLongOid();
                }
            }

            if (StringUtils.isNotEmpty(oid)) {
                organization = organizationDao.findTopByOid(oid);
            }
        }
        return organization;
    }

    /**
     * 得到所属机构 ()
     *
     * @param deviceInfo
     * @return
     */
    public Organization getDeviceBeToOrganization(DeviceInfo deviceInfo) {
        Organization organization = null;
        if (ObjectUtils.isNotEmpty(deviceInfo)) {
            String oid = deviceInfo.getBeToOid();
            if (StringUtils.isNotEmpty(oid)) {
                organization = organizationDao.findTopByOid(oid);
            }
        }
        return organization;
    }

    /**
     * 设备信息  简单模型
     *
     * @param entity
     * @return
     */
    public DeviceInfoSimpleModel toSimpleModel(DeviceInfo entity) {
        DeviceInfoSimpleModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new DeviceInfoSimpleModel();
            BeanUtils.copyProperties(entity, model);
        }
        return model;
    }
}
