package space.nstart.pcp.pcp_satellites_service.entity

import jakarta.persistence.CascadeType
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.EnumType
import jakarta.persistence.Enumerated
import jakarta.persistence.FetchType
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.OneToMany
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import jakarta.persistence.PrePersist
import jakarta.persistence.PreUpdate
import jakarta.persistence.Table
import jakarta.persistence.Index
import space.nstart.pcp.pcp_types_lib.dto.satellite.mission.ModeDataRates
import space.nstart.pcp.pcp_types_lib.utils.UtcDateTimes
import java.time.LocalDateTime

@Entity
@Table(
    name = "satellite_modes",
    indexes = [
        Index(name = "idx_satellite_modes_satellite_id", columnList = "satellite_id"),
        Index(name = "idx_satellite_modes_start_time", columnList = "start_time"),
        Index(name = "idx_satellite_modes_end_time", columnList = "end_time"),
        Index(name = "idx_satellite_modes_source", columnList = "source")
    ]
)
class SatelliteModeEntity(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long? = null,

    @Column(name = "satellite_id", nullable = false)
    var satelliteId: Long = 0,

    @Enumerated(EnumType.STRING)
    @Column(name = "source", nullable = false, length = 20)
    var source: SatelliteModeSource = SatelliteModeSource.COMPLAN,

    @Enumerated(EnumType.STRING)
    @Column(name = "type", nullable = false, length = 20)
    var type: SatelliteModeType = SatelliteModeType.SURVEY,

    @Column(name = "start_time", nullable = false)
    var startTime: LocalDateTime = UtcDateTimes.now(),

    @Column(name = "end_time", nullable = false)
    var endTime: LocalDateTime = UtcDateTimes.now(),

    @Column(name = "revolution", nullable = false)
    var revolution: Long = 0,

    @Column(name = "lat", nullable = false)
    var lat: Double = 0.0,

    @Column(name = "longitude", nullable = false)
    var longitude: Double = 0.0,

    @Column(name = "duration", nullable = false)
    var duration: Double = 0.0,

    @Column(name = "contour_wkt", columnDefinition = "TEXT")
    var contourWkt: String? = null,

    @Column(name = "roll", nullable = false)
    var roll: Double = 0.0,

    @Column(name = "cell_num", nullable = false)
    var cellNum: Long = -1,

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "snapshot_id", nullable = false)
    var snapshot: SatelliteModeSnapshotEntity? = null,

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "complex_plan_run_id")
    var complexPlanRun: ComplexPlanRunEntity? = null,

    @OneToMany(
        mappedBy = "mode",
        cascade = [CascadeType.ALL],
        orphanRemoval = true,
        fetch = FetchType.LAZY
    )
    var bookedSlots: MutableList<SatelliteModeBookedSlotEntity> = mutableListOf(),

    @OneToMany(
        mappedBy = "mode",
        cascade = [CascadeType.ALL],
        orphanRemoval = true,
        fetch = FetchType.LAZY
    )
    var cells: MutableList<SatelliteModeCellEntity> = mutableListOf()
) {
    /** Объём маршрута, Мбайт. Денормализация: считается из duration при построении (satellite_modes — только SURVEY). */
    @Column(name = "volume_mb", nullable = false)
    var volumeMb: Double = ModeDataRates.surveyVolumeMb(duration)

    @PrePersist
    @PreUpdate
    fun computeVolumeMb() {
        volumeMb = ModeDataRates.surveyVolumeMb(duration)
    }
}
