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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dji.sample.map.model.param.MediaDirQueryParam;
import com.dji.sample.media.dao.IMediaDirMapper;
import com.dji.sample.media.model.MediaDirDTO;
import com.dji.sample.media.model.MediaDirEntity;
import com.dji.sample.media.model.MediaFileDTO;
import com.dji.sample.media.model.MediaFileEntity;
import com.dji.sample.media.service.IFileService;
import com.dji.sample.media.service.IMediaDirService;
import com.dji.sample.wayline.model.enums.WaylineTemplateTypeEnum;
import com.dji.sdk.common.Pagination;
import com.dji.sdk.common.PaginationData;
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.stream.Collectors;

/**
 * @author hqjiang
 * @version 1.0
 * @date 2024/7/2
 */
@Service
@Transactional
public class MediaDirServiceImpl implements IMediaDirService {

    @Autowired
    private IMediaDirMapper mapper;

    @Override
    public PaginationData<MediaDirDTO> getMediaDirsPaginationByWorkspaceId(String workspaceId, MediaDirQueryParam param, long page, long pageSize) {
        Page<MediaDirEntity> pageData = mapper.selectPage(
                new Page<MediaDirEntity>(page, pageSize),
                new LambdaQueryWrapper<MediaDirEntity>()
                        .eq(MediaDirEntity::getWorkspaceId, workspaceId)
                        .ge(param != null && param.getBeginTime() != null, MediaDirEntity::getCreateTime,param.getBeginTime())
                        .le(param != null && param.getEndTime() != null, MediaDirEntity::getCreateTime,param.getEndTime())
                        .eq(param != null && StringUtils.hasText(param.getTemplateType()), MediaDirEntity::getTemplateType,param.getTemplateType())
                        .eq(param != null && StringUtils.hasText(param.getPayload()), MediaDirEntity::getPayload,param.getPayload())
                        .and(StringUtils.hasText(param.getSearchInfo()),
                                wrapper -> wrapper .like( MediaDirEntity::getDirName, param.getSearchInfo())
                                        .or().like( MediaDirEntity::getPayload, param.getSearchInfo())
                                        .or().like( MediaDirEntity::getDeviceName, param.getSearchInfo())
                        )
                        .orderByDesc(MediaDirEntity::getCreateTime));
        List<MediaDirDTO> records = pageData.getRecords()
                .stream()
                .map(this::entityToDto)
                .collect(Collectors.toList());

        return new PaginationData<MediaDirDTO>(records, new Pagination(pageData.getCurrent(), pageData.getSize(), pageData.getTotal()));
    }

    @Override
    public MediaDirDTO getMediaDirByName(String workspaceId, String dirName, Integer parentId) {
        MediaDirEntity mediaDirEntity = mapper.selectOne(new LambdaQueryWrapper<MediaDirEntity>()
                .eq(MediaDirEntity::getWorkspaceId, workspaceId)
                .eq(MediaDirEntity::getDirName, dirName)
                .eq(MediaDirEntity::getParentId, parentId == null? 0 : parentId));
        if(mediaDirEntity == null) {
            return null;
        }
       return entityToDto(mediaDirEntity);
    }

    @Override
    public MediaDirDTO getMediaDirById(String workspaceId, String dirId) {
        MediaDirEntity mediaDirEntity = mapper.selectOne(new LambdaQueryWrapper<MediaDirEntity>()
                .eq(StringUtils.hasText(workspaceId), MediaDirEntity::getWorkspaceId, workspaceId)
                .eq(MediaDirEntity::getId, dirId));
        return entityToDto(mediaDirEntity);
    }

    @Override
    public Integer createDir(MediaDirDTO mediaDirDTO) {
        MediaDirEntity dirEntity = this.dtoToEntity(mediaDirDTO);
        return mapper.insert(dirEntity);
    }

    @Override
    public MediaDirDTO createDir(MediaDirEntity dirEntity) {
        int result = mapper.insert(dirEntity);
        if(result > 0) {
            return entityToDto(dirEntity);
        }
        return null;
    }

    @Override
    public void deleteDir(String dirId) {
        mapper.deleteById(dirId);
    }



    private MediaDirEntity dtoToEntity(MediaDirDTO mediaDir) {
        MediaDirEntity.MediaDirEntityBuilder builder = MediaDirEntity.builder();

        if (mediaDir != null) {
            builder.workspaceId(mediaDir.getWorkspaceId())
                    .dirName(mediaDir.getDirName())
                    .parentId(mediaDir.getParentId())
                    .deviceName(mediaDir.getDeviceName())
                    .payload(mediaDir.getPayload())
                    .waylineName(mediaDir.getWaylineName())
                    .templateType(mediaDir.getTemplateType())
                    .createTime(mediaDir.getCreateTime() != null ?
                            mediaDir.getCreateTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
                    .username(mediaDir.getUsername());
        }
        return builder.build();
    }

    private MediaDirDTO entityToDto(MediaDirEntity mediaDirEntity) {
        MediaDirDTO.MediaDirDTOBuilder builder = MediaDirDTO.builder();
        if (mediaDirEntity != null) {
            builder.id(mediaDirEntity.getId())
                    .workspaceId(mediaDirEntity.getWorkspaceId())
                    .dirName(mediaDirEntity.getDirName())
                    .parentId(mediaDirEntity.getParentId())
                    .deviceName(mediaDirEntity.getDeviceName())
                    .payload(mediaDirEntity.getPayload())
                    .waylineName(mediaDirEntity.getWaylineName())
                    .templateType( StringUtils.hasText(mediaDirEntity.getTemplateType()) ? WaylineTemplateTypeEnum.find(mediaDirEntity.getTemplateType()).get().getType() : "")
                    .createTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(mediaDirEntity.getCreateTime()), ZoneId.systemDefault()))
                    .username(mediaDirEntity.getUsername());
        }
        return builder.build();
    }

}
