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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.util.UserRequest;
import com.dji.sample.manage.dao.IDeviceOprLogsMapper;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.dto.DeviceOprLogsDTO;
import com.dji.sample.manage.model.dto.WorkspaceDTO;
import com.dji.sample.manage.model.entity.DeviceOprLogsEntity;
import com.dji.sample.manage.model.enums.LogOprTypeEnum;
import com.dji.sample.manage.model.param.DeviceOprLogsQueryParam;
import com.dji.sample.manage.service.IDeviceOprLogsService;
import com.dji.sample.manage.service.IWorkspaceService;
import com.dji.sdk.common.Pagination;
import com.dji.sdk.common.PaginationData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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 hqjiang
 * @version 1.0
 * @date 2024/6/25
 */
@Service
@Transactional
@Slf4j
public class DeviceOprLogsServiceImpl implements IDeviceOprLogsService {

    @Autowired
    private IDeviceOprLogsMapper mapper;

    @Autowired
    private IWorkspaceService workspaceService;

    @Override
    public Long insertDeviceOprLogs(DeviceOprLogsDTO logsDTO) {
        DeviceOprLogsEntity entity = dto2Entity(logsDTO);
        return mapper.insert(entity) > 0 ? entity.getId() : -1;
    }

    @Override
    public PaginationData<DeviceOprLogsDTO> getDeviceOprLogs(String workspaceId, DeviceOprLogsQueryParam param) {
        LambdaQueryWrapper<DeviceOprLogsEntity> queryWrapper = new LambdaQueryWrapper<DeviceOprLogsEntity>()
                .eq(DeviceOprLogsEntity::getWorkspaceId, workspaceId)
                .between(Objects.nonNull(param.getBeginTime()) && Objects.nonNull(param.getEndTime()),
                        DeviceOprLogsEntity::getCreateTime, param.getBeginTime(), param.getEndTime())
                .eq(param!=null && StringUtils.hasText(param.getDeviceName()),DeviceOprLogsEntity::getDeviceName,param.getDeviceName())
                .and(StringUtils.hasText(param.getSearchInfo()),
                        wrapper -> wrapper .like( DeviceOprLogsEntity::getLogInfo, param.getSearchInfo())
                                .or().like( DeviceOprLogsEntity::getDeviceSn, param.getSearchInfo())
                                .or().like(DeviceOprLogsEntity::getWorkspaceName, param.getSearchInfo())
                )
                .orderByDesc(DeviceOprLogsEntity::getCreateTime);

        Page<DeviceOprLogsEntity> pagination = mapper.selectPage(new Page<>(param.getPage(), param.getPageSize()), queryWrapper);

        List<DeviceOprLogsDTO> deviceOprLogsList = pagination.getRecords().stream().map(this::entity2Dto).collect(Collectors.toList());

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


    @Override
    public void addDeviceOprLogsDTO(DeviceDTO redisDevice, LogOprTypeEnum oprTypeEnum) {
        CustomClaim customClaim = UserRequest.getCurrentUser();
        addDeviceOprLog(redisDevice,oprTypeEnum,customClaim);
    }

    @Override
    public void addDeviceOprLogsDTO(DeviceDTO redisDevice, LogOprTypeEnum oprTypeEnum, CustomClaim customClaim) {
        if(customClaim == null) {
            customClaim = UserRequest.getCurrentUser();
        }
        addDeviceOprLog(redisDevice,oprTypeEnum,customClaim);
    }

    private void addDeviceOprLog(DeviceDTO redisDevice, LogOprTypeEnum oprTypeEnum,CustomClaim customClaim) {
        String userName = "System";
        if(customClaim != null) {
            userName = customClaim.getUsername();
        }
        WorkspaceDTO workspaceDTO = workspaceService.getWorkspaceByWorkspaceId(redisDevice.getWorkspaceId()).get();
        DeviceOprLogsDTO deviceOprLogsDTO =
                DeviceOprLogsDTO.builder().username(userName)
                        .deviceSn(redisDevice.getDeviceSn())
                        .deviceName(redisDevice.getDeviceName())
                        .nickName(redisDevice.getNickname())
                        .logInfo(oprTypeEnum.getDesc() + "成功")
                        .workspaceId(redisDevice.getWorkspaceId())
                        .workspaceName(workspaceDTO.getWorkspaceName())
                        .type(oprTypeEnum.getVal())
                        .bindCode(workspaceDTO.getBindCode())
                        .createTime(LocalDateTime.now())
                        .build();
        insertDeviceOprLogs(deviceOprLogsDTO);
    }

    private DeviceOprLogsDTO entity2Dto(DeviceOprLogsEntity entity) {
        if (Objects.isNull(entity)) {
            return null;
        }
        return DeviceOprLogsDTO.builder()
                .username(entity.getUsername())
                .deviceSn(entity.getDeviceSn())
                .deviceName(entity.getDeviceName())
                .nickName(entity.getNickname())
                .logInfo(entity.getLogInfo())
                .workspaceId(entity.getWorkspaceId())
                .workspaceName(entity.getWorkspaceName())
                .type(entity.getType())
                .typeName(LogOprTypeEnum.find(entity.getType()).getDesc())
                .bindCode(entity.getBindCode())
                .createTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()))
                .build();
    }


    private DeviceOprLogsEntity dto2Entity(DeviceOprLogsDTO dto) {
        if (dto == null) {
            return DeviceOprLogsEntity.builder().build();
        }

        return DeviceOprLogsEntity.builder()
                .username(dto.getUsername())
                .deviceName(dto.getDeviceName())
                .deviceSn(dto.getDeviceSn())
                .nickname(dto.getNickName())
                .logInfo(dto.getLogInfo())
                .workspaceId(dto.getWorkspaceId())
                .workspaceName(dto.getWorkspaceName())
                .type(dto.getType())
                .bindCode(dto.getBindCode())
                .createTime(dto.getCreateTime() != null ? dto.getCreateTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
                .build();
    }
}
