package cn.skcks.matrix.v2.services.location.record;

import cn.hutool.core.util.IdUtil;
import cn.skcks.matrix.v2.model.jwt.dto.Claims;
import cn.skcks.matrix.v2.model.location.record.convert.LocationRecordConvertor;
import cn.skcks.matrix.v2.model.location.record.dto.LocationRecordDto;
import cn.skcks.matrix.v2.model.location.record.dto.LocationRecordParams;
import cn.skcks.matrix.v2.model.location.record.dto.PageLocationRecordParams;
import cn.skcks.matrix.v2.model.location.record.vo.LocationRecordVo;
import cn.skcks.matrix.v2.model.services.ServiceResult;
import cn.skcks.matrix.v2.orm.mybatis.dynamic.mapper.LocationRecordDynamicSqlSupport;
import cn.skcks.matrix.v2.orm.mybatis.dynamic.mapper.LocationRecordMapper;
import cn.skcks.matrix.v2.orm.mybatis.dynamic.mapper.RoleDynamicSqlSupport;
import cn.skcks.matrix.v2.orm.mybatis.dynamic.model.LocationRecord;
import cn.skcks.matrix.v2.utils.page.PageWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.Collection;
import java.util.List;

@Service
@RequiredArgsConstructor
public class LocationRecordServiceImpl implements LocationRecordService{
    private final LocationRecordMapper locationRecordMapper;

    private RuntimeException checkClaims(Claims claims){
        if(claims == null){
            return new RuntimeException("无效的身份令牌");
        }

        String userId = claims.getUserId();
        if (StringUtils.isEmpty(userId)) {
            return new RuntimeException("无效的用户Id");
        }

        return null;
    }

    @Override
    public ServiceResult<Collection<LocationRecord>> getLocationRecord(LocationRecordParams params, Claims claims) {
        ServiceResult.ServiceResultBuilder<Collection<LocationRecord>> result = ServiceResult.builder();
        Exception exception = checkClaims(claims);
        if (exception != null){
            return result.exception(exception.getMessage()).build();
        }

        String userId = claims.getUserId();

        List<LocationRecord> recordList = locationRecordMapper.select((s)-> s.applyWhere(dsl -> {
            if (params.getStartTime() != null) {
                dsl.and(LocationRecordDynamicSqlSupport.locationTime, SqlBuilder.isGreaterThanOrEqualTo(params.getStartTime()));
            }

            if (params.getEndTime() != null) {
                dsl.and(LocationRecordDynamicSqlSupport.locationTime,SqlBuilder.isLessThanOrEqualTo(params.getEndTime()));
            }

            dsl.and(LocationRecordDynamicSqlSupport.userId, SqlBuilder.isEqualTo(Long.valueOf(userId)));
            dsl.and(LocationRecordDynamicSqlSupport.id, SqlBuilder.isNotNull());
        }).orderBy(LocationRecordDynamicSqlSupport.locationTime, LocationRecordDynamicSqlSupport.id));

        return result.result(recordList).build();
    }

    @Override
    public ServiceResult<PageInfo<LocationRecord>> getPageLocationRecord(PageLocationRecordParams params, Claims claims) {
        PageInfo<LocationRecord> pageInfo;
        try(Page<LocationRecord> page = PageHelper.startPage(params.getPage(),params.getSize())){
            pageInfo = page.doSelectPageInfo(()->{
                getLocationRecord(params, claims);
            });
        }

        return ServiceResult.<PageInfo<LocationRecord>>builder()
                .result(pageInfo)
                .build();
    }

    @Override
    public ServiceResult<Void> postLocationRecord(LocationRecordDto locationRecordDto, Claims claims) throws Exception {
        Exception exception = checkClaims(claims);
        if(exception != null){
            throw exception;
        }

        LocationRecord dao = LocationRecordConvertor.INSTANCE.dtoToDao(locationRecordDto);
        dao.setId(IdUtil.getSnowflakeNextIdStr());
        dao.setUserId(Long.valueOf(claims.getUserId()));

        locationRecordMapper.insert(dao);
        return ServiceResult.<Void>builder().build();
    }
}
