package com.aegis.resource.vehicle.service.impl;

import com.aegis.common.exception.ServiceException;
import com.aegis.common.utils.SecurityUtils;
import com.aegis.common.utils.StringUtils;
import com.aegis.resource.vehicle.domain.Vehicle;
import com.aegis.resource.vehicle.mapper.ResourceVehicleMapper;
import com.aegis.resource.vehicle.service.IResourceVehicleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 车辆Service业务层处理
 * 
 * @author aegis
 */
@Service
public class ResourceVehicleServiceImpl extends ServiceImpl<ResourceVehicleMapper, Vehicle>
    implements IResourceVehicleService {

    private static final String STATUS_AVAILABLE = "available";
    private static final String DEL_FLAG_NORMAL = "0";
    private static final String DEL_FLAG_DELETED = "2";

    @Override
    public List<Vehicle> listByCondition(Vehicle condition) {
        LambdaQueryWrapper<Vehicle> wrapper = buildConditionWrapper(condition);
        wrapper.eq(Vehicle::getDelFlag, DEL_FLAG_NORMAL)
            .orderByDesc(Vehicle::getCreateTime);
        return list(wrapper);
    }

    @Override
    public List<Vehicle> listByTeamId(Long teamId) {
        return list(new LambdaQueryWrapper<Vehicle>()
            .eq(Vehicle::getDelFlag, DEL_FLAG_NORMAL)
            .eq(Vehicle::getTeamId, teamId)
            .orderByDesc(Vehicle::getCreateTime));
    }

    @Override
    public Vehicle getById(Serializable id) {
        Vehicle vehicle = super.getById(id);
        if (vehicle != null && DEL_FLAG_DELETED.equals(vehicle.getDelFlag())) {
            return null;
        }
        return vehicle;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(Vehicle entity) {
        ensureVehicleNoUnique(entity);
        Vehicle deletedVehicle = findDeletedVehicle(entity.getPlateNo());
        if (deletedVehicle != null) {
            entity.setId(deletedVehicle.getId());
            entity.setCreateBy(deletedVehicle.getCreateBy());
            entity.setCreateTime(deletedVehicle.getCreateTime());
            entity.setDelFlag(DEL_FLAG_NORMAL);
            entity.setUpdateBy(SecurityUtils.getUsername());
            entity.setUpdateTime(new Date());
            if (StringUtils.isEmpty(entity.getStatus())) {
                entity.setStatus(STATUS_AVAILABLE);
            }
            return super.updateById(entity);
        }

        String operator = SecurityUtils.getUsername();
        Date now = new Date();
        entity.setCreateBy(operator);
        entity.setCreateTime(now);
        entity.setUpdateBy(operator);
        entity.setUpdateTime(now);
        entity.setDelFlag(DEL_FLAG_NORMAL);
        if (StringUtils.isEmpty(entity.getStatus())) {
            entity.setStatus(STATUS_AVAILABLE);
        }
        return super.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(Vehicle entity) {
        if (entity.getId() == null) {
            throw new ServiceException("车辆ID不能为空");
        }
        Vehicle existing = baseMapper.selectById(entity.getId());
        if (existing == null) {
            throw new ServiceException("车辆不存在");
        }

        if (!StringUtils.equals(existing.getPlateNo(), entity.getPlateNo())) {
            ensureVehicleNoUnique(entity);
            Vehicle deletedConflict = findDeletedVehicle(entity.getPlateNo());
            if (deletedConflict != null) {
                throw new ServiceException("修改车辆'" + entity.getPlateNo() + "'失败，该车牌存在已删除记录，需先恢复");
            }
        }

        entity.setUpdateBy(SecurityUtils.getUsername());
        entity.setUpdateTime(new Date());
        return super.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateVehicleLocation(Long id, BigDecimal gpsLat, BigDecimal gpsLng) {
        Vehicle vehicle = baseMapper.selectById(id);
        if (vehicle == null || DEL_FLAG_DELETED.equals(vehicle.getDelFlag())) {
            throw new ServiceException("车辆不存在");
        }
        return lambdaUpdate()
            .eq(Vehicle::getId, id)
            .set(Vehicle::getGpsLat, gpsLat)
            .set(Vehicle::getGpsLng, gpsLng)
            .set(Vehicle::getLastSeenAt, new Date())
            .set(Vehicle::getUpdateTime, new Date())
            .update();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeById(Serializable id) {
        return softDeleteByIds(Collections.singleton(id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIds(Collection<?> idList) {
        return softDeleteByIds(idList);
    }

    private boolean softDeleteByIds(Collection<?> idList) {
        if (idList == null || idList.isEmpty()) {
            return true;
        }
        return lambdaUpdate()
            .in(Vehicle::getId, idList)
            .set(Vehicle::getDelFlag, DEL_FLAG_DELETED)
            .set(Vehicle::getUpdateBy, SecurityUtils.getUsername())
            .set(Vehicle::getUpdateTime, new Date())
            .update();
    }

    private LambdaQueryWrapper<Vehicle> buildConditionWrapper(Vehicle condition) {
        LambdaQueryWrapper<Vehicle> wrapper = new LambdaQueryWrapper<>();
        if (condition == null) {
            return wrapper;
        }
        wrapper.like(StringUtils.isNotBlank(condition.getVehicleName()), Vehicle::getVehicleName, condition.getVehicleName());
        wrapper.like(StringUtils.isNotBlank(condition.getPlateNo()), Vehicle::getPlateNo, condition.getPlateNo());
        wrapper.eq(StringUtils.isNotBlank(condition.getVehicleType()), Vehicle::getVehicleType, condition.getVehicleType());
        wrapper.eq(condition.getTeamId() != null, Vehicle::getTeamId, condition.getTeamId());
        wrapper.eq(StringUtils.isNotBlank(condition.getStatus()), Vehicle::getStatus, condition.getStatus());
        wrapper.eq(StringUtils.isNotBlank(condition.getDeviceId()), Vehicle::getDeviceId, condition.getDeviceId());
        wrapper.like(StringUtils.isNotBlank(condition.getCapabilities()), Vehicle::getCapabilities, condition.getCapabilities());
        return wrapper;
    }

    private void ensureVehicleNoUnique(Vehicle vehicle) {
        if (!isVehicleNoUnique(vehicle)) {
            throw new ServiceException("车牌号已存在：" + vehicle.getPlateNo());
        }
    }

    private Vehicle findDeletedVehicle(String plateNo) {
        if (StringUtils.isEmpty(plateNo)) {
            return null;
        }
        return lambdaQuery()
            .eq(Vehicle::getPlateNo, plateNo)
            .eq(Vehicle::getDelFlag, DEL_FLAG_DELETED)
            .last("LIMIT 1")
            .one();
    }

    private boolean isVehicleNoUnique(Vehicle vehicle) {
        if (vehicle == null || StringUtils.isEmpty(vehicle.getPlateNo())) {
            return true;
        }
        LambdaQueryWrapper<Vehicle> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Vehicle::getPlateNo, vehicle.getPlateNo())
            .eq(Vehicle::getDelFlag, DEL_FLAG_NORMAL);
        if (vehicle.getId() != null) {
            wrapper.ne(Vehicle::getId, vehicle.getId());
        }
        return count(wrapper) == 0;
    }
}