package org.github.tess1o.geopulse.sharing.mapper;

import jakarta.enterprise.context.ApplicationScoped;
import org.github.tess1o.geopulse.gps.model.GpsPointEntity;
import org.github.tess1o.geopulse.shared.map.MapRenderMode;
import org.github.tess1o.geopulse.sharing.model.*;
import org.github.tess1o.geopulse.user.model.UserEntity;

import java.util.List;
import java.util.stream.Collectors;

@ApplicationScoped
public class SharedLinkMapper {

    public SharedLinkEntity toEntity(CreateShareLinkRequest createShareLinkRequest, UserEntity user) {
        SharedLinkEntity sharedLinkEntity = new SharedLinkEntity();
        sharedLinkEntity.setName(createShareLinkRequest.getName());
        sharedLinkEntity.setExpiresAt(createShareLinkRequest.getExpiresAt());
        sharedLinkEntity.setPassword(createShareLinkRequest.getPassword());
        sharedLinkEntity.setShowHistory(createShareLinkRequest.isShowHistory());
        sharedLinkEntity.setHistoryHours(createShareLinkRequest.getHistoryHours());
        sharedLinkEntity.setUser(user);

        // Set share type and timeline-specific fields
        if (createShareLinkRequest.getShareType() != null) {
            sharedLinkEntity.setShareType(ShareType.valueOf(createShareLinkRequest.getShareType()));
        } else {
            sharedLinkEntity.setShareType(ShareType.LIVE_LOCATION);
        }
        sharedLinkEntity.setStartDate(createShareLinkRequest.getStartDate());
        sharedLinkEntity.setEndDate(createShareLinkRequest.getEndDate());
        sharedLinkEntity.setShowCurrentLocation(createShareLinkRequest.getShowCurrentLocation() != null ?
                createShareLinkRequest.getShowCurrentLocation() : true);
        sharedLinkEntity.setShowPhotos(createShareLinkRequest.getShowPhotos() != null ?
                createShareLinkRequest.getShowPhotos() : false);
        sharedLinkEntity.setShowNotes(createShareLinkRequest.getShowNotes() != null ?
                createShareLinkRequest.getShowNotes() : false);
        sharedLinkEntity.setCustomMapTileUrl(createShareLinkRequest.getCustomMapTileUrl());
        sharedLinkEntity.setCustomMapStyleUrl(createShareLinkRequest.getCustomMapStyleUrl());
        sharedLinkEntity.setMapRenderMode(createShareLinkRequest.getMapRenderMode() != null ?
                createShareLinkRequest.getMapRenderMode() : MapRenderMode.RASTER);

        return sharedLinkEntity;
    }

    public CreateShareLinkResponse toResponse(SharedLinkEntity sharedLinkEntity) {
        CreateShareLinkResponse response = new CreateShareLinkResponse();
        response.setId(sharedLinkEntity.getId());
        response.setName(sharedLinkEntity.getName());
        response.setExpiresAt(sharedLinkEntity.getExpiresAt());
        response.setHasPassword(sharedLinkEntity.getPassword() != null);
        response.setShowHistory(sharedLinkEntity.isShowHistory());
        response.setHistoryHours(sharedLinkEntity.getHistoryHours());
        response.setCreatedAt(sharedLinkEntity.getCreatedAt());
        return response;
    }

    public SharedLinkDto toDto(SharedLinkEntity entity) {
        return SharedLinkDto.builder()
                .id(entity.getId().toString())
                .name(entity.getName())
                .expiresAt(entity.getExpiresAt())
                .hasPassword(entity.getPassword() != null)
                .showHistory(entity.isShowHistory())
                .historyHours(entity.getHistoryHours())
                .isActive(entity.isActive())
                .createdAt(entity.getCreatedAt())
                .viewCount(entity.getViewCount())
                .shareType(entity.getShareType().name())
                .startDate(entity.getStartDate())
                .endDate(entity.getEndDate())
                .showCurrentLocation(entity.getShowCurrentLocation())
                .showPhotos(entity.getShowPhotos())
                .showNotes(entity.getShowNotes())
                .timelineStatus(entity.getTimelineStatus())
                .customMapTileUrl(entity.getCustomMapTileUrl())
                .customMapStyleUrl(entity.getCustomMapStyleUrl())
                .mapRenderMode(entity.getMapRenderMode() != null ? entity.getMapRenderMode() : MapRenderMode.RASTER)
                .build();
    }

    public SharedLocationInfo toLocationInfo(SharedLinkEntity entity) {
        return SharedLocationInfo.builder()
                .id(entity.getId())
                .name(entity.getName())
                .expiresAt(entity.getExpiresAt())
                .hasPassword(entity.getPassword() != null)
                .showHistory(entity.isShowHistory())
                .historyHours(entity.getHistoryHours())
                .isActive(entity.isActive())
                .createdAt(entity.getCreatedAt())
                .viewCount(entity.getViewCount())
                .sharedBy(entity.getUser().getFullName() != null ?
                        entity.getUser().getFullName() : entity.getUser().getEmail())
                .shareType(entity.getShareType().name())
                .startDate(entity.getStartDate())
                .endDate(entity.getEndDate())
                .showCurrentLocation(entity.getShowCurrentLocation())
                .showPhotos(entity.getShowPhotos())
                .showNotes(entity.getShowNotes())
                .timelineStatus(entity.getTimelineStatus())
                .customMapTileUrl(entity.getCustomMapTileUrl())
                .customMapStyleUrl(entity.getCustomMapStyleUrl())
                .mapRenderMode(entity.getMapRenderMode() != null ? entity.getMapRenderMode() : MapRenderMode.RASTER)
                .build();
    }

    public LocationHistoryResponse.CurrentLocationData toCurrentLocationData(GpsPointEntity location) {
        return new LocationHistoryResponse.CurrentLocationData(
                location.getCoordinates().getY(), // latitude
                location.getCoordinates().getX(), // longitude
                location.getTimestamp(),
                location.getAccuracy()
        );
    }

    public LocationHistoryResponse.HistoricalLocationData toHistoricalLocationData(GpsPointEntity location) {
        return new LocationHistoryResponse.HistoricalLocationData(
                location.getCoordinates().getY(), // latitude
                location.getCoordinates().getX(), // longitude
                location.getTimestamp()
        );
    }

    public LocationHistoryResponse toLocationHistoryResponse(GpsPointEntity currentLocation, List<GpsPointEntity> history) {
        LocationHistoryResponse.CurrentLocationData current = currentLocation != null ?
                toCurrentLocationData(currentLocation) : null;

        List<LocationHistoryResponse.HistoricalLocationData> historicalData =
                history.stream()
                        .map(this::toHistoricalLocationData)
                        .collect(Collectors.toList());

        return new LocationHistoryResponse(current, historicalData);
    }

    public ShareLinkResponse toShareLinkResponse(GpsPointEntity location) {
        return new ShareLinkResponse(
                location.getCoordinates().getY(), // latitude
                location.getCoordinates().getX(), // longitude
                location.getTimestamp(),
                location.getAccuracy() != null ? location.getAccuracy() : 0.0
        );
    }

    public void updateEntityFromDto(SharedLinkEntity entity, UpdateShareLinkDto dto) {
        if (dto.getName() != null) {
            entity.setName(dto.getName());
        }
        if (dto.getExpiresAt() != null) {
            entity.setExpiresAt(dto.getExpiresAt());
        }
        if (dto.getPassword() != null) {
            entity.setPassword(dto.getPassword());
        } else if (dto.isPasswordRemoval()) {
            entity.setPassword(null);
        }
        entity.setShowHistory(dto.isShowHistory());
        entity.setHistoryHours(dto.getHistoryHours());

        // Update timeline-specific fields if provided
        if (dto.getShareType() != null) {
            entity.setShareType(ShareType.valueOf(dto.getShareType()));
        }
        if (dto.getStartDate() != null) {
            entity.setStartDate(dto.getStartDate());
        }
        if (dto.getEndDate() != null) {
            entity.setEndDate(dto.getEndDate());
        }
        if (dto.getShowCurrentLocation() != null) {
            entity.setShowCurrentLocation(dto.getShowCurrentLocation());
        }
        if (dto.getShowPhotos() != null) {
            entity.setShowPhotos(dto.getShowPhotos());
        }
        if (dto.getShowNotes() != null) {
            entity.setShowNotes(dto.getShowNotes());
        }
        // Always set custom map tile URL (null is valid - means disabled)
        entity.setCustomMapTileUrl(dto.getCustomMapTileUrl());
        // Always set custom map style URL (null is valid - means disabled)
        entity.setCustomMapStyleUrl(dto.getCustomMapStyleUrl());
        if (dto.getMapRenderMode() != null) {
            entity.setMapRenderMode(dto.getMapRenderMode());
        }
    }
}
