package cn.hanghui.outapi.platform.tenant.service.impl;

import cn.hanghui.outapi.platform.common.entity.rest.RestResult;
import cn.hanghui.outapi.platform.tenant.entity.dto.AppApkDeviceTaskDto;
import cn.hanghui.outapi.platform.tenant.entity.dto.AppApkDeviceTaskErrorVo;
import cn.hanghui.outapi.platform.tenant.entity.dto.AppApkDeviceTaskPageDto;
import cn.hanghui.outapi.platform.tenant.entity.dto.AppApkDeviceTaskReq;
import cn.hanghui.outapi.platform.tenant.entity.dto.AppApkDeviceTaskVo;
import cn.hanghui.outapi.platform.tenant.entity.dto.AppApkDto;
import cn.hanghui.outapi.platform.tenant.entity.dto.AppApkPageDto;
import cn.hanghui.outapi.platform.tenant.entity.dto.AppApkVo;
import cn.hanghui.outapi.platform.tenant.entity.po.AppApk;
import cn.hanghui.outapi.platform.tenant.entity.po.AppApkDeviceTask;
import cn.hanghui.outapi.platform.tenant.entity.po.Device;
import cn.hanghui.outapi.platform.tenant.mapper.AppApkDeviceTaskMapper;
import cn.hanghui.outapi.platform.tenant.mapper.AppApkMapper;
import cn.hanghui.outapi.platform.tenant.mapper.DeviceMapper;
import cn.hanghui.outapi.platform.tenant.service.AppApkService;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author shisl
 * @package cn.hanghui.outapi.platform.tenant.service.impl
 * @class AppApkServiceImpl
 * @date 2023/10/8 下午4:20
 * @description
 */
@Slf4j
@Service
public class AppApkServiceImpl implements AppApkService {

    @Resource
    private AppApkMapper appApkMapper;

    @Resource
    private AppApkDeviceTaskMapper appApkDeviceTaskMapper;

    @Resource
    private DeviceMapper deviceMapper;

    @Override
    public RestResult add(AppApkDto dto) {
        if (dto.getId() != null) {
            return updateApk(dto);
        } else {
            return addApk(dto);
        }
    }

    private RestResult addApk(AppApkDto dto) {
        AppApk apk = BeanUtil.copyProperties(dto, AppApk.class);
        apk.setApkStatus(1);
        apk.setIsDeleted(Boolean.FALSE);
        apk.setVersion(1);
        apk.setCreateTime(new Date());
        apk.setUpdateTime(new Date());
        appApkMapper.insert(apk);
        return RestResult.ok();
    }

    private RestResult updateApk(AppApkDto dto) {
        AppApk apk = appApkMapper.selectById(dto.getId());
        if (apk == null) {
            return RestResult.error("数据不存在或已删除");
        }
        apk.setUpdateTime(new Date());
        apk.setApkPath(dto.getApkPath());
        apk.setApkTitle(dto.getApkTitle());
        apk.setApkVersion(dto.getApkVersion());
        appApkMapper.updateById(apk);
        return RestResult.ok();
    }

    @Override
    public RestResult del(Long id) {
        AppApk apk = appApkMapper.selectById(id);
        if (apk == null) {
            return RestResult.error("数据不存在或已删除");
        }
        appApkMapper.deleteById(apk);
        return RestResult.ok();
    }

    @Override
    public RestResult<IPage<AppApkVo>> pageApk(AppApkPageDto dto) {
        Page<AppApk> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        LambdaQueryWrapper<AppApk> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppApk::getIsDeleted, Boolean.FALSE);
        if (dto.getApkVersion() != null && !"".equals(dto.getApkVersion().trim())) {
            wrapper.eq(AppApk::getApkVersion, dto.getApkVersion());
        }
        if (dto.getApkTitle() != null && !"".equals(dto.getApkTitle().trim())) {
            wrapper.like(AppApk::getApkTitle, dto.getApkTitle());
        }
        if (dto.getStartTime() != null) {
            wrapper.ge(AppApk::getCreateTime, dto.getStartTime());
        }
        if (dto.getEndTime() != null) {
            wrapper.le(AppApk::getCreateTime, dto.getEndTime());
        }
        wrapper.orderByDesc(AppApk::getId);
        IPage<AppApk> iPage = appApkMapper.selectPage(page, wrapper);
        IPage<AppApkVo> convert = iPage.convert(t -> {
            AppApkVo item = BeanUtil.copyProperties(t, AppApkVo.class);
            return item;
        });
        return RestResult.ok(convert);
    }

    @Override
    public RestResult addTask(AppApkDeviceTaskDto dto) {

        if (dto.getAppApkId() == null || dto.getSns() == null || dto.getSns().size() == 0) {
            return RestResult.error("参数有误，请检查参数后重试");
        }

        //校验设备是否存在
        List<Device> devices = deviceMapper.selectList(Wrappers.lambdaQuery(Device.class).in(Device::getSn, dto.getSns()).eq(Device::getIsDeleted, Boolean.FALSE));
        if (devices == null || devices.isEmpty()) {
            return RestResult.error("设备数据不存在或已删除");
        }
        List<AppApkDeviceTaskErrorVo> errors = new ArrayList<>();
        List<String> dbSns = devices.stream().map(Device::getSn).collect(Collectors.toList());
        dto.getSns().stream().forEach(item -> {
            AppApkDeviceTaskErrorVo error = null;
            if (!dbSns.contains(item)) {
                error = new AppApkDeviceTaskErrorVo();
                error.setSn(item);
                error.setErrorMsg("设备数据不存在或已删除");
                errors.add(error);
            }
        });

        //查询设备是否有等待中、下载中的任务存在
        List<AppApkDeviceTask> tasks = appApkDeviceTaskMapper.selectList(Wrappers.lambdaQuery(AppApkDeviceTask.class).in(AppApkDeviceTask::getSn, dbSns).in(AppApkDeviceTask::getStatus, Arrays.asList(0, 1)).eq(AppApkDeviceTask::getIsDeleted, Boolean.FALSE));
        List<String> dbTaskSns = tasks.stream().map(AppApkDeviceTask::getSn).collect(Collectors.toList());
        if (dbTaskSns != null && !dbTaskSns.isEmpty()) {
            dbSns.stream().forEach(item -> {
                AppApkDeviceTaskErrorVo error = null;
                if (dbTaskSns.contains(item)) {
                    error = new AppApkDeviceTaskErrorVo();
                    error.setSn(item);
                    error.setErrorMsg("存在等待中/下载中的任务");
                    errors.add(error);
                }
            });
        }
        //获取过滤后的设备编号
        List<String> filterSns = dbSns.stream().filter(item -> dbTaskSns == null || dbTaskSns.isEmpty() || !dbTaskSns.contains(item)).collect(Collectors.toList());
        log.info("--->过滤后的设备编号:{}", filterSns);
        AppApk apk = appApkMapper.selectById(dto.getAppApkId());
        filterSns.stream().forEach(item -> {
            try {
                AppApkDeviceTask task = new AppApkDeviceTask();
                task.setApkPath(apk.getApkPath());
                task.setApkTitle(apk.getApkTitle());
                task.setApkVersion(apk.getApkVersion());
                task.setAppApkId(apk.getId());
                task.setSn(item);
                task.setStatus(0);
                task.setCreateTime(new Date());
                task.setIsDeleted(Boolean.FALSE);
                task.setUpdateTime(new Date());
                task.setVersion(1);
                appApkDeviceTaskMapper.insert(task);
            } catch (Exception e) {
                AppApkDeviceTaskErrorVo error = new AppApkDeviceTaskErrorVo();
                error.setSn(item);
                error.setErrorMsg("服务异常，添加失败");
                errors.add(error);
            }
        });
        return RestResult.ok(errors);
    }

    @Override
    public RestResult cancelTask(Long id) {
        AppApkDeviceTask task = appApkDeviceTaskMapper.selectById(id);
        if (task == null || task.getIsDeleted()) {
            return RestResult.error("任务数据不存在或已删除");
        }

        if (task.getStatus() == 2 || task.getStatus() == 3) {
            return RestResult.error("任务已完成或已取消");
        }
        task.setStatus(3);
        appApkDeviceTaskMapper.updateById(task);
        return RestResult.ok();
    }

    @Override
    public RestResult<IPage<AppApkDeviceTaskVo>> pageTask(AppApkDeviceTaskPageDto dto) {

        List<String> filterSns = null;
        if (dto.getCompany() != null && !"".equals(dto.getCompany().trim())) {
            List<Device> devices = deviceMapper.selectList(Wrappers.lambdaQuery(Device.class).like(Device::getCompany, dto.getCompany()).eq(Device::getIsDeleted, Boolean.FALSE));
            if (devices != null || !devices.isEmpty()) {
                filterSns = devices.stream().map(Device::getSn).collect(Collectors.toList());
            }
        }

        Page<AppApkDeviceTask> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        LambdaQueryWrapper<AppApkDeviceTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppApkDeviceTask::getIsDeleted, Boolean.FALSE);
        if (dto.getSn() != null && !"".equals(dto.getSn().trim())) {
            wrapper.eq(AppApkDeviceTask::getSn, dto.getSn().trim());
        }
        if (dto.getCompany() != null && !"".equals(dto.getCompany().trim())) {
            if (filterSns == null || filterSns.isEmpty()) {
                wrapper.eq(AppApkDeviceTask::getSn, "-1");
            } else {
                wrapper.in(AppApkDeviceTask::getSn, filterSns);
            }
        }
        if (dto.getApkTitle() != null && !"".equals(dto.getApkTitle().trim())) {
            wrapper.like(AppApkDeviceTask::getApkTitle, dto.getApkTitle());
        }
        if (dto.getApkVersion() != null && !"".equals(dto.getApkVersion().trim())) {
            wrapper.eq(AppApkDeviceTask::getApkVersion, dto.getApkVersion());
        }

        if (dto.getStatus() != null) {
            wrapper.eq(AppApkDeviceTask::getStatus, dto.getStatus());
        }

        if (dto.getStartTime() != null) {
            wrapper.ge(AppApkDeviceTask::getCreateTime, dto.getStartTime());
        }
        if (dto.getEndTime() != null) {
            wrapper.le(AppApkDeviceTask::getCreateTime, dto.getEndTime());
        }
        wrapper.orderByDesc(AppApkDeviceTask::getId);
        IPage<AppApkDeviceTask> iPage = appApkDeviceTaskMapper.selectPage(page, wrapper);
        IPage<AppApkDeviceTaskVo> convert = iPage.convert(t -> {
            AppApkDeviceTaskVo item = BeanUtil.copyProperties(t, AppApkDeviceTaskVo.class);
            return item;
        });
        complete(convert);
        return RestResult.ok(convert);
    }

    private void complete(IPage<AppApkDeviceTaskVo> convert) {
        List<AppApkDeviceTaskVo> records = convert.getRecords();
        if (records == null || records.isEmpty()) {
            return;
        }
        List<String> sns = records.stream().map(AppApkDeviceTaskVo::getSn).collect(Collectors.toList());
        List<Device> devices = deviceMapper.selectList(Wrappers.lambdaQuery(Device.class).in(Device::getSn, sns).eq(Device::getIsDeleted, Boolean.FALSE));
        if (devices == null || devices.isEmpty()) {
            return;
        }
        Map<String, Device> deviceMap = devices.stream().collect(Collectors.toMap(Device::getSn, a -> a, (k1, k2) -> k1));
        records.stream().forEach(item -> {
            Device device = deviceMap.get(item.getSn());
            if (device != null) {
                item.setCompany(device.getCompany());
            }
        });
        convert.setRecords(records);
    }

    @Override
    public RestResult taskQuery(AppApkDeviceTaskReq req) {
        List<AppApkDeviceTask> tasks = appApkDeviceTaskMapper.selectList(Wrappers.lambdaQuery(AppApkDeviceTask.class).eq(AppApkDeviceTask::getSn, req.getSn()).eq(AppApkDeviceTask::getStatus, 0).eq(AppApkDeviceTask::getIsDeleted, Boolean.FALSE));
        if (tasks == null || tasks.isEmpty()) {
            log.info("--->{}不存在等待中的任务", req.getSn());
            return RestResult.ok();
        }
        AppApkDeviceTaskVo vo = BeanUtil.copyProperties(tasks.get(0), AppApkDeviceTaskVo.class);
        tasks.stream().forEach(item -> {
            item.setStatus(1);
            item.setRequestTime(new Date());
            item.setUpdateTime(new Date());
            appApkDeviceTaskMapper.updateById(item);
        });
        return RestResult.ok(vo);
    }

    @Override
    public RestResult taskTracking(AppApkDeviceTaskReq req, Integer status) {
        List<AppApkDeviceTask> tasks = appApkDeviceTaskMapper.selectList(Wrappers.lambdaQuery(AppApkDeviceTask.class).eq(AppApkDeviceTask::getSn, req.getSn()).eq(AppApkDeviceTask::getStatus, 1).eq(AppApkDeviceTask::getIsDeleted, Boolean.FALSE));
        if (tasks == null || tasks.isEmpty()) {
            log.info("--->{}不存在下载中的任务", req.getSn());
            return RestResult.ok();
        }

        tasks.stream().forEach(item -> {
            item.setStatus(status);
            item.setInstallTime(new Date());
            item.setUpdateTime(new Date());
            appApkDeviceTaskMapper.updateById(item);
        });
        return RestResult.ok();
    }

    @Override
    public RestResult<List<AppApkVo>> apkList() {
        LambdaQueryWrapper<AppApk> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppApk::getIsDeleted, Boolean.FALSE);
        wrapper.orderByDesc(AppApk::getId);
        List<AppApk> appApks = appApkMapper.selectList(wrapper);
        List<AppApkVo> appApkVos = BeanUtil.copyToList(appApks, AppApkVo.class);
        return RestResult.ok(appApkVos == null || appApkVos.isEmpty() ? Collections.emptyList() : appApkVos);
    }


}
