package org.dromara.member.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.member.domain.AppDevice;
import org.dromara.member.domain.bo.AppDeviceBo;
import org.dromara.member.domain.vo.AppDeviceVo;
import org.dromara.member.exception.DeviceException;
import org.dromara.member.mapper.AppDeviceMapper;
import org.dromara.member.service.AppDeviceService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;

/**
 * App端设备信息Service业务层处理
 *
 * @author pengles
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class AppDeviceServiceImpl extends ServiceImpl<AppDeviceMapper, AppDevice> implements AppDeviceService {

    private final AppDeviceMapper baseMapper;

    /**
     * 查询App端设备信息
     */
    @Override
    public AppDeviceVo queryById(Long deviceId) {
        return baseMapper.selectVoById(deviceId);
    }

    /**
     * 查询App端设备信息列表
     */
    @Override
    public TableDataInfo<AppDeviceVo> queryPageList(AppDeviceBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AppDevice> lqw = buildQueryWrapper(bo);
        Page<AppDeviceVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询App端设备信息列表
     */
    @Override
    public List<AppDeviceVo> queryList(AppDeviceBo bo) {
        LambdaQueryWrapper<AppDevice> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<AppDevice> buildQueryWrapper(AppDeviceBo bo) {
        LambdaQueryWrapper<AppDevice> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, AppDevice::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceType()), AppDevice::getDeviceType, bo.getDeviceType());
        lqw.like(StringUtils.isNotBlank(bo.getDeviceName()), AppDevice::getDeviceName, bo.getDeviceName());
        lqw.like(StringUtils.isNotBlank(bo.getDeviceModel()), AppDevice::getDeviceModel, bo.getDeviceModel());
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceBrand()), AppDevice::getDeviceBrand, bo.getDeviceBrand());
        lqw.eq(StringUtils.isNotBlank(bo.getOsVersion()), AppDevice::getOsVersion, bo.getOsVersion());
        lqw.eq(StringUtils.isNotBlank(bo.getAppVersion()), AppDevice::getAppVersion, bo.getAppVersion());
        lqw.eq(StringUtils.isNotBlank(bo.getIsActive()), AppDevice::getIsActive, bo.getIsActive());
        lqw.orderByDesc(AppDevice::getLastActiveTime);
        return lqw;
    }

    /**
     * 新增App端设备信息
     */
    @Override
    public Boolean insertByBo(AppDeviceBo bo) {
        AppDevice add = BeanUtil.toBean(bo, AppDevice.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setDeviceId(add.getDeviceId());
        }
        return flag;
    }

    /**
     * 修改App端设备信息
     */
    @Override
    public Boolean updateByBo(AppDeviceBo bo) {
        AppDevice update = BeanUtil.toBean(bo, AppDevice.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(AppDevice entity) {
        // TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除App端设备信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 根据用户ID查询设备列表
     */
    @Override
    public List<AppDeviceVo> queryByUserId(Long userId) {
        LambdaQueryWrapper<AppDevice> lqw = Wrappers.lambdaQuery();
        lqw.eq(AppDevice::getUserId, userId);
        lqw.orderByDesc(AppDevice::getLastActiveTime);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 绑定设备
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean bindDevice(AppDeviceBo bo) {
        // 检查用户设备数量限制
        LambdaQueryWrapper<AppDevice> countLqw = Wrappers.lambdaQuery();
        countLqw.eq(AppDevice::getUserId, bo.getUserId());
        countLqw.eq(AppDevice::getIsActive, "1");
        long deviceCount = baseMapper.selectCount(countLqw);
        if (deviceCount >= 10) { // 限制每个用户最多绑定10台设备
            throw DeviceException.deviceLimitExceeded(10);
        }

        // 检查是否已存在相同设备
        LambdaQueryWrapper<AppDevice> lqw = Wrappers.lambdaQuery();
        lqw.eq(AppDevice::getUserId, bo.getUserId());
        lqw.eq(AppDevice::getDeviceType, bo.getDeviceType());
        lqw.eq(StringUtils.isNotBlank(bo.getPushToken()), AppDevice::getPushToken, bo.getPushToken());

        AppDevice existDevice = baseMapper.selectOne(lqw);
        if (existDevice != null) {
            // 更新现有设备信息
            existDevice.setDeviceName(bo.getDeviceName());
            existDevice.setDeviceModel(bo.getDeviceModel());
            existDevice.setDeviceBrand(bo.getDeviceBrand());
            existDevice.setOsVersion(bo.getOsVersion());
            existDevice.setAppVersion(bo.getAppVersion());
            existDevice.setIsActive("1");
            existDevice.setLastActiveTime(LocalDateTime.now());
            boolean result = baseMapper.updateById(existDevice) > 0;
            if (!result) {
                throw DeviceException.bindFailed("设备信息更新失败");
            }
            return result;
        } else {
            // 新增设备
            bo.setIsActive("1");
            bo.setLastActiveTime(LocalDateTime.now());
            boolean result = insertByBo(bo);
            if (!result) {
                throw DeviceException.bindFailed("设备信息保存失败");
            }
            return result;
        }
    }

    /**
     * 解绑设备
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unbindDevice(Long deviceId, Long userId) {
        LambdaQueryWrapper<AppDevice> lqw = Wrappers.lambdaQuery();
        lqw.eq(AppDevice::getDeviceId, deviceId);
        lqw.eq(AppDevice::getUserId, userId);

        AppDevice device = baseMapper.selectOne(lqw);
        if (device == null) {
            throw DeviceException.deviceNotFound(deviceId);
        }

        boolean result = baseMapper.deleteById(deviceId) > 0;
        if (!result) {
            throw DeviceException.unbindFailed("设备删除失败");
        }
        return result;
    }

    /**
     * 更新设备活跃状态
     */
    @Override
    public Boolean updateActiveStatus(Long deviceId, String isActive) {
        if (!"0".equals(isActive) && !"1".equals(isActive)) {
            throw DeviceException.invalidStatus(isActive);
        }

        AppDevice existDevice = baseMapper.selectById(deviceId);
        if (existDevice == null) {
            throw DeviceException.deviceNotFound(deviceId);
        }

        AppDevice device = new AppDevice();
        device.setDeviceId(deviceId);
        device.setIsActive(isActive);
        if ("1".equals(isActive)) {
            device.setLastActiveTime(LocalDateTime.now());
        }
        return baseMapper.updateById(device) > 0;
    }

    /**
     * 更新推送令牌
     */
    @Override
    public Boolean updatePushToken(Long deviceId, String pushToken) {
        if (StringUtils.isBlank(pushToken)) {
            throw DeviceException.invalidPushToken(pushToken);
        }

        AppDevice existDevice = baseMapper.selectById(deviceId);
        if (existDevice == null) {
            throw DeviceException.deviceNotFound(deviceId);
        }

        AppDevice device = new AppDevice();
        device.setDeviceId(deviceId);
        device.setPushToken(pushToken);
        device.setLastActiveTime(LocalDateTime.now());
        return baseMapper.updateById(device) > 0;
    }

    /**
     * 获取用户活跃设备
     */
    @Override
    public List<AppDeviceVo> getActiveDevices(Long userId) {
        LambdaQueryWrapper<AppDevice> lqw = Wrappers.lambdaQuery();
        lqw.eq(AppDevice::getUserId, userId);
        lqw.eq(AppDevice::getIsActive, "1");
        lqw.orderByDesc(AppDevice::getLastActiveTime);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 清理非活跃设备
     */
    @Override
    public Integer cleanInactiveDevices(Integer days) {
        if (days == null || days <= 0) {
            days = 30; // 默认30天
        }

        LambdaQueryWrapper<AppDevice> lqw = Wrappers.lambdaQuery();
        lqw.lt(AppDevice::getLastActiveTime, LocalDateTime.now().minusDays(days));
        lqw.or();
        lqw.eq(AppDevice::getIsActive, "0");

        List<AppDevice> inactiveDevices = baseMapper.selectList(lqw);
        if (!inactiveDevices.isEmpty()) {
            List<Long> ids = inactiveDevices.stream().map(AppDevice::getDeviceId).toList();
            baseMapper.deleteBatchIds(ids);
            log.info("清理非活跃设备 {} 个", ids.size());
            return ids.size();
        }

        return 0;
    }

    /**
     * 根据推送令牌查询设备
     */
    @Override
    public AppDeviceVo queryByPushToken(String pushToken) {
        if (StringUtils.isBlank(pushToken)) {
            return null;
        }

        LambdaQueryWrapper<AppDevice> lqw = Wrappers.lambdaQuery();
        lqw.eq(AppDevice::getPushToken, pushToken);
        lqw.eq(AppDevice::getIsActive, "1");
        return baseMapper.selectVoOne(lqw);
    }

    /**
     * 设备心跳更新
     */
    @Override
    public Boolean heartbeat(Long deviceId) {
        AppDevice device = new AppDevice();
        device.setDeviceId(deviceId);
        device.setIsActive("1");
        device.setLastActiveTime(LocalDateTime.now());
        return baseMapper.updateById(device) > 0;
    }

    /**
     * 批量更新设备状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchUpdateStatus(List<Long> deviceIds, String isActive) {
        if (ObjectUtil.isEmpty(deviceIds)) {
            return false;
        }

        AppDevice device = new AppDevice();
        device.setIsActive(isActive);
        if ("1".equals(isActive)) {
            device.setLastActiveTime(LocalDateTime.now());
        }

        LambdaQueryWrapper<AppDevice> lqw = Wrappers.lambdaQuery();
        lqw.in(AppDevice::getDeviceId, deviceIds);

        return baseMapper.update(device, lqw) > 0;
    }

}