package com.grigowashere.aismap.data.mapper;

import com.grigowashere.aismap.data.entity.AISVesselEntity;
import com.grigowashere.aismap.models.AISVessel;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

/**
 * Маппер для конвертации между AISVessel (модель) и AISVesselEntity (БД)
 * Решает проблему потери данных при сохранении/восстановлении AIS судов
 */
public class AISVesselMapper {
    
    /**
     * Конвертирует AISVessel модель в AISVesselEntity для сохранения в БД
     */
    public static AISVesselEntity toEntity(AISVessel vessel) {
        if (vessel == null) {
            return null;
        }
        
        AISVesselEntity entity = new AISVesselEntity(vessel.getMmsi());
        
        // Основная информация о судне
        entity.vesselName = vessel.getVesselName();
        entity.callSign = vessel.getCallSign();
        entity.imo = vessel.getImo();
        entity.vesselType = vessel.getVesselType();
        
        // Позиция и движение
        entity.latitude = vessel.getLatitude();
        entity.longitude = vessel.getLongitude();
        entity.course = vessel.getCourse();
        entity.speed = vessel.getSpeed();
        entity.heading = vessel.getHeading();
        
        // Размеры судна
        entity.length = vessel.getLength();
        entity.width = vessel.getWidth();
        entity.draft = vessel.getDraft();
        
        // Навигационная информация
        entity.destination = vessel.getDestination();
        entity.etaEpochMs = convertLocalDateTimeToEpochMs(vessel.getEta());
        entity.navigationalStatus = vessel.getNavigationalStatus();
        entity.positionAccuracy = vessel.isPositionAccuracy();
        
        // Техническая информация
        entity.signalStrength = vessel.getSignalStrength();
        entity.vesselClass = vessel.getVesselClass();
        entity.vendorId = vessel.getVendorId();
        entity.lastSafetyMessage = vessel.getLastSafetyMessage();
        
        // Состояние и время
        entity.lastUpdateEpochMs = convertLocalDateTimeToEpochMs(vessel.getLastUpdate());
        entity.isActive = vessel.isActive();
        entity.selected = vessel.isSelected();
        
        return entity;
    }
    
    /**
     * Конвертирует AISVesselEntity из БД в AISVessel модель
     */
    public static AISVessel toModel(AISVesselEntity entity) {
        if (entity == null) {
            return null;
        }
        
        AISVessel vessel = new AISVessel(entity.mmsi);
        
        // Основная информация о судне
        vessel.setVesselName(entity.vesselName);
        vessel.setCallSign(entity.callSign);
        vessel.setImo(entity.imo);
        vessel.setVesselType(entity.vesselType);
        
        // Позиция и движение
        vessel.setLatitude(entity.latitude);
        vessel.setLongitude(entity.longitude);
        vessel.setCourse(entity.course);
        vessel.setSpeed(entity.speed);
        vessel.setHeading(entity.heading);
        
        // Размеры судна
        vessel.setLength(entity.length);
        vessel.setWidth(entity.width);
        vessel.setDraft(entity.draft);
        
        // Навигационная информация
        vessel.setDestination(entity.destination);
        vessel.setEta(convertEpochMsToLocalDateTime(entity.etaEpochMs));
        vessel.setNavigationalStatus(entity.navigationalStatus);
        vessel.setPositionAccuracy(entity.positionAccuracy);
        
        // Техническая информация
        vessel.setSignalStrength(entity.signalStrength);
        vessel.setVesselClass(entity.vesselClass);
        vessel.setVendorId(entity.vendorId);
        vessel.setLastSafetyMessage(entity.lastSafetyMessage);
        
        // Состояние и время
        vessel.setLastUpdate(convertEpochMsToLocalDateTime(entity.lastUpdateEpochMs));
        vessel.setActive(entity.isActive);
        vessel.setSelected(entity.selected);
        
        return vessel;
    }
    
    /**
     * Конвертирует LocalDateTime в epoch milliseconds
     */
    private static long convertLocalDateTimeToEpochMs(LocalDateTime dateTime) {
        if (dateTime == null) {
            return 0;
        }
        return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }
    
    /**
     * Конвертирует epoch milliseconds в LocalDateTime
     */
    private static LocalDateTime convertEpochMsToLocalDateTime(long epochMs) {
        if (epochMs <= 0) {
            return LocalDateTime.now();
        }
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMs), ZoneId.systemDefault());
    }
}
