package cn.reghao.tnb.content.app.geo.service;

import cn.reghao.file.api.iface.OssService;
import cn.reghao.jutil.jdk.converter.DateTimeConverter;
import cn.reghao.tnb.common.auth.UserContext;
import cn.reghao.tnb.common.db.SelectOption;
import cn.reghao.tnb.content.api.dto.geo.MallReplyDto;
import cn.reghao.tnb.content.app.geo.db.mapper.CameraPhotoMapper;
import cn.reghao.tnb.content.app.geo.db.mapper.GeoPointMapper;
import cn.reghao.tnb.content.app.geo.db.mapper.MallReplyMapper;
import cn.reghao.tnb.content.app.geo.db.repository.MallReplyRepository;
import cn.reghao.tnb.content.app.geo.model.constant.GeoItem;
import cn.reghao.tnb.content.app.geo.model.po.CameraPhoto;
import cn.reghao.tnb.content.app.geo.model.po.GeoPoint;
import cn.reghao.tnb.content.app.geo.model.po.MallReply;
import cn.reghao.tnb.content.app.geo.model.vo.MapMarker;
import cn.reghao.tnb.content.app.geo.model.vo.MapPoint;
import cn.reghao.tnb.content.app.geo.model.vo.MarkerInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2023-08-31 17:49:48
 */
@Slf4j
@Service
public class PhotoMapService {
    @DubboReference(check = false, retries = 0)
    private OssService ossService;

    private final MallReplyMapper mallReplyMapper;
    private final CameraPhotoMapper cameraPhotoMapper;
    private final MallReplyRepository mallReplyRepository;
    private final GeoPointMapper geoPointMapper;

    public PhotoMapService(MallReplyMapper mallReplyMapper, CameraPhotoMapper cameraPhotoMapper,
                           MallReplyRepository mallReplyRepository, GeoPointMapper geoPointMapper) {
        this.mallReplyMapper = mallReplyMapper;
        this.cameraPhotoMapper = cameraPhotoMapper;
        this.mallReplyRepository = mallReplyRepository;
        this.geoPointMapper = geoPointMapper;
    }

    public synchronized void addTmallReply(MallReplyDto mallReplyDto) {
        long replyId = mallReplyDto.getReplyId();
        MallReply mallReply = mallReplyMapper.findByReplyId(replyId);
        if (mallReply != null) {
            log.info("{} 已存在", replyId);
            return;
        }

        mallReply = new MallReply(replyId, mallReplyDto);
        List<CameraPhoto> list = mallReplyDto.getCamPhotoList().stream()
                .map(camPhoto -> {
                    CameraPhoto cameraPhoto = new CameraPhoto(replyId, camPhoto);
                    try {
                        String shotAtStr = camPhoto.getShotAt();
                        if (shotAtStr != null) {
                            LocalDateTime shotAt = DateTimeConverter.localDateTime2(camPhoto.getShotAt());
                            cameraPhoto.setShotAt(shotAt);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    return cameraPhoto;
                })
                .collect(Collectors.toList());

        if (!list.isEmpty()) {
            mallReplyRepository.saveTmallReply(mallReply, list);
        }
    }

    @Cacheable(cacheNames = "tnb:geo:mark", key = "#itemType", unless = "#result == null")
    public List<MapMarker> getPhotoMarks(int itemType) {
        int pageSize = 100;
        List<MapMarker> list = mallReplyRepository.findMapMarkers(itemType, pageSize);
        return list;
    }

    public List<MapMarker> getPhotoMarksArea(int areaCode) {
        List<MapMarker> list = mallReplyRepository.findMapMarkers(areaCode);
        return list;
    }

    public List<MapMarker> getMapDistance(int distance) {
        long loginUser = UserContext.getUserId();
        List<GeoPoint> geoPointList = geoPointMapper.findByPositionType(loginUser, 1);
        if (geoPointList.isEmpty()) {
            return Collections.emptyList();
        }

        GeoPoint geoPoint = geoPointList.get(0);
        double lng = geoPoint.getLongitude().doubleValue();
        double lat = geoPoint.getLatitude().doubleValue();
        MapPoint mapPoint = new MapPoint(lng, lat);
        List<MapMarker> list = mallReplyRepository.findMapMarkers(mapPoint, distance);
        MapMarker mapMarker = new MapMarker("0", "MyPosition", mapPoint);
        list.add(mapMarker);
        return list;
    }

    public MarkerInfo getMarkerInfo(int id) {
        CameraPhoto cameraPhoto = cameraPhotoMapper.findById(id);
        if (cameraPhoto == null) {
            return null;
        }
        
        String albumType = cameraPhoto.getAlbumType();
        MarkerInfo markerInfo;
        if (albumType.equals("ImagePost")) {
            markerInfo = cameraPhotoMapper.findImagePostInfo(id);
            markerInfo.setType(GeoItem.ImagePost.getValue());
        } else if (albumType.equals("MallReply")) {
            markerInfo = cameraPhotoMapper.findMallReplyInfo(id);
            markerInfo.setType(GeoItem.MallReply.getValue());
        } else {
            markerInfo = cameraPhotoMapper.findMarkerInfo(id);
            markerInfo.setType(0);
        }

        int channelCode = markerInfo.getChannelCode();
        if (channelCode != 0) {
            String uploadId = markerInfo.getUploadId();
            try {
                String signedUrl = ossService.getSignedUrl(uploadId, null);
                if (signedUrl != null) {
                    markerInfo.setPhotoUrl(signedUrl);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return markerInfo;
    }

    public List<SelectOption> getGeoItems() {
        return Arrays.stream(GeoItem.values()).map(geoItem -> {
            int id = geoItem.getValue();
            String name = geoItem.getName();
            return new SelectOption(name, id+"");
        }).collect(Collectors.toList());
    }
}
