package com.dji.sample.ai.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dji.sample.ai.dao.IAiInfoMapper;
import com.dji.sample.ai.model.dto.AiInfoDTO;
import com.dji.sample.ai.model.entity.AiInfoEntity;
import com.dji.sample.ai.model.param.AiInfoSearchParam;
import com.dji.sample.ai.service.IAiInfoService;
import com.dji.sample.wayline.model.entity.WaylineJobEntity;
import com.dji.sdk.common.Pagination;
import com.dji.sdk.common.PaginationData;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author guan
 */
@Service
public class AiInfoServiceImpl extends ServiceImpl<IAiInfoMapper, AiInfoEntity> implements IAiInfoService {

    @Override
    public PaginationData<AiInfoDTO> getAiInfoPageByParam(AiInfoSearchParam param, Long page, Long pageSize) {

        LambdaQueryWrapper<AiInfoEntity> wrapper = new LambdaQueryWrapper<>();

        if (StringUtils.hasText(param.getDeviceSn())) {
            wrapper.like(AiInfoEntity::getDeviceSn, param.getDeviceSn());
        }
        if (StringUtils.hasText(param.getWarnEvent())) {
            wrapper.like(AiInfoEntity::getWarnEvent, param.getWarnEvent());
        }
        if (StringUtils.hasText(param.getWarnType())) {
            wrapper.eq(AiInfoEntity::getWarnType, param.getWarnType());
        }
        if (StringUtils.hasText(param.getAlgorithmType())) {
            wrapper.eq(AiInfoEntity::getAlgorithmType, param.getAlgorithmType());
        }
        if (!ObjectUtils.isEmpty(param.getStartWarnTime())) {
            wrapper.ge(AiInfoEntity::getWarnTime, param.getStartWarnTime());
        }
        if (!ObjectUtils.isEmpty(param.getEndWarnTime())) {
            wrapper.le(AiInfoEntity::getWarnTime, param.getEndWarnTime());
        }
        if (StringUtils.hasText(param.getOrderBy())) {

            String[] arr = param.getOrderBy().split(" ");
            String column = arr[0];
            String direction = arr.length > 1 ? arr[1] : "desc";

            // 避免SQL注入，不直接使用SQL语句，所以判断相应的列
            switch (column) {
                case "id":
                    if ("asc".equals(direction)) {
                        wrapper.orderByAsc(AiInfoEntity::getId);
                    } else {
                        wrapper.orderByDesc(AiInfoEntity::getId);
                    }
                    break;
                case "createTime":
                case "create_time":
                    if ("asc".equals(direction)) {
                        wrapper.orderByAsc(AiInfoEntity::getCreateTime);
                    } else {
                        wrapper.orderByDesc(AiInfoEntity::getCreateTime);
                    }
                    break;
                case "warnTime":
                case "warn_time":
                    if ("asc".equals(direction)) {
                        wrapper.orderByAsc(AiInfoEntity::getWarnTime);
                    } else {
                        wrapper.orderByDesc(AiInfoEntity::getWarnTime);
                    }
                    break;
                case "deviceSn":
                case "device_sn":
                    if ("asc".equals(direction)) {
                        wrapper.orderByAsc(AiInfoEntity::getDeviceSn);
                    } else {
                        wrapper.orderByDesc(AiInfoEntity::getDeviceSn);
                    }
                    break;
                case "warnType":
                case "warn_type":
                    if ("asc".equals(direction)) {
                        wrapper.orderByAsc(AiInfoEntity::getWarnType);
                    } else {
                        wrapper.orderByDesc(AiInfoEntity::getWarnType);
                    }
                    break;
                case "warnEvent":
                case "warn_event":
                    if ("asc".equals(direction)) {
                        wrapper.orderByAsc(AiInfoEntity::getWarnEvent);
                    } else {
                        wrapper.orderByDesc(AiInfoEntity::getWarnEvent);
                    }
                    break;
                case "algorithmType":
                case "algorithm_type":
                    if ("asc".equals(direction)) {
                        wrapper.orderByAsc(AiInfoEntity::getAlgorithmType);
                    } else {
                        wrapper.orderByDesc(AiInfoEntity::getAlgorithmType);
                    }
                    break;
                default:
                    wrapper.orderByDesc(AiInfoEntity::getId);
                    break;
            }
        } else {
            wrapper.orderByDesc(AiInfoEntity::getId);
        }

        Page<AiInfoEntity> pagination = this.page(new Page<>(page, pageSize), wrapper);
        List<AiInfoDTO> aiInfoDTOList = pagination.getRecords().stream().map(this::AiInfoEntityToDTO)
                .collect(Collectors.toList());

        return new PaginationData<>(aiInfoDTOList, new Pagination(pagination.getCurrent(), pagination.getSize(), pagination.getTotal()));
    }

    public AiInfoDTO AiInfoEntityToDTO(AiInfoEntity aiInfoEntity) {

        AiInfoDTO aiInfoDTO = new AiInfoDTO();

        aiInfoDTO.setId(aiInfoEntity.getId());
        aiInfoDTO.setCreateTime(Objects.nonNull(aiInfoEntity.getCreateTime()) ?
                LocalDateTime.ofInstant(Instant.ofEpochMilli(aiInfoEntity.getCreateTime()), ZoneId.systemDefault()) : null);
        aiInfoDTO.setDeviceSn(aiInfoEntity.getDeviceSn());
        aiInfoDTO.setPayloadSn(aiInfoEntity.getPayloadSn());
        aiInfoDTO.setImageUrl(aiInfoEntity.getImageUrl());
        aiInfoDTO.setWarnType(aiInfoEntity.getWarnType());
        aiInfoDTO.setWarnEvent(aiInfoEntity.getWarnEvent());
        aiInfoDTO.setWarnLocation(aiInfoEntity.getWarnLocation());
        aiInfoDTO.setWarnTime(Objects.nonNull(aiInfoEntity.getWarnTime()) ?
                LocalDateTime.ofInstant(Instant.ofEpochMilli(aiInfoEntity.getWarnTime()), ZoneId.systemDefault()) : null);
        aiInfoDTO.setJson(aiInfoEntity.getJson());
        aiInfoDTO.setAlgorithmType(aiInfoEntity.getAlgorithmType());


        return aiInfoDTO;
    }

    public AiInfoEntity AiInfoDTOToEntity(AiInfoDTO aiInfoDTO) {

        AiInfoEntity aiInfoEntity = new AiInfoEntity();

        aiInfoEntity.setId(aiInfoDTO.getId());
        if (Objects.nonNull(aiInfoDTO.getCreateTime())) {
            aiInfoEntity.setCreateTime(aiInfoDTO.getCreateTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
        }
        aiInfoEntity.setDeviceSn(aiInfoDTO.getDeviceSn());
        aiInfoEntity.setPayloadSn(aiInfoDTO.getPayloadSn());
        aiInfoEntity.setImageUrl(aiInfoDTO.getImageUrl());
        aiInfoEntity.setWarnType(aiInfoDTO.getWarnType());
        aiInfoEntity.setWarnEvent(aiInfoDTO.getWarnEvent());
        aiInfoEntity.setWarnLocation(aiInfoDTO.getWarnLocation());
        if (Objects.nonNull(aiInfoDTO.getWarnTime())) {
            aiInfoEntity.setWarnTime(aiInfoDTO.getWarnTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
        }
        aiInfoEntity.setJson(aiInfoDTO.getJson());
        aiInfoEntity.setAlgorithmType(aiInfoDTO.getAlgorithmType());

        return aiInfoEntity;
    }

    @Override
    public AiInfoDTO createAiInfo(AiInfoDTO dto) {
        AiInfoEntity entity = AiInfoDTOToEntity(dto);
        this.save(entity);
        return AiInfoEntityToDTO(entity);
    }

    @Override
    public AiInfoDTO getAiInfoById(Long id) {
        AiInfoEntity entity = this.getById(id);
        return Objects.nonNull(entity) ? AiInfoEntityToDTO(entity) : null;
    }

    @Override
    public boolean updateAiInfo(AiInfoDTO dto) {
        AiInfoEntity entity = AiInfoDTOToEntity(dto);
        return this.updateById(entity);
    }

    @Override
    public boolean deleteAiInfoById(Long id) {
        return this.removeById(id);
    }
}
