package space.nstart.pcp.pcp_types_lib.dto.satellite.mission

import com.fasterxml.jackson.annotation.JsonProperty
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.DecimalMin
import space.nstart.pcp.pcp_types_lib.utils.UtcDateTimes
import java.time.LocalDateTime

/**
 * Способ построения временного окна маршрута относительно момента видимости.
 */
enum class SurveyRouteAnchor {
    /** Окно центрируется на моменте видимости: [time - duration/2, time + duration/2]. */
    CENTERED,

    /** Момент видимости — начало съёмки: [time, time + duration]. */
    FORWARD
}

@Schema(description = "Запрос на построение одного маршрута съёмки по параметрам видимости точки")
data class SurveyRouteBuildRequestDTO(
    @field:Schema(description = "Идентификатор КА (тот же, что используется в obj-view/mpl-point — NORAD)")
    val satelliteId: Long = 0,

    @field:Schema(description = "Момент видимости (локальное время без зоны)")
    val time: LocalDateTime = UtcDateTimes.now(),

    @field:DecimalMin(value = "1", message = "Длительность съёмки должна быть не меньше 1 секунды")
    @field:Schema(description = "Длительность съёмки, секунды")
    val durationSeconds: Double = 60.0,

    @field:Schema(description = "Крен (gamma), градусы")
    val roll: Double = 0.0,

    @field:Schema(description = "Угол захвата (полуширина полосы), градусы")
    val captureAngle: Double = 1.5,

    @field:Schema(description = "Номер витка (0 — определить по орбитальным точкам)")
    val revolution: Long = 0,

    @field:Schema(description = "Способ построения окна относительно момента видимости")
    val anchor: SurveyRouteAnchor = SurveyRouteAnchor.CENTERED,

    @field:Schema(
        description = "Начало интервала плана (локальное время без зоны). Используется только при " +
            "сохранении маршрута, если миссии/плана с таким id ещё нет — чтобы создать их с " +
            "корректным окном (для расчёта пересечений и наложений). Игнорируется в /build.",
        nullable = true
    )
    val planStart: LocalDateTime? = null,

    @field:Schema(
        description = "Конец интервала плана (локальное время без зоны). См. planStart.",
        nullable = true
    )
    val planEnd: LocalDateTime? = null
)

@Schema(description = "Построенный маршрут съёмки")
data class SurveyRouteBuildResponseDTO(
    val satelliteId: Long,
    @field:Schema(description = "Начало съёмки (локальное время без зоны)")
    val timeStart: LocalDateTime,
    @field:Schema(description = "Длительность съёмки, секунды")
    val duration: Double,
    val revolution: Long,
    @field:Schema(description = "Крен (gamma), градусы")
    val roll: Double,
    @field:Schema(description = "Угол захвата, градусы")
    val captureAngle: Double,
    @field:Schema(description = "Широта центра контура, градусы")
    val lat: Double,
    @field:Schema(description = "Долгота центра контура, градусы")
    val longitude: Double,
    @field:Schema(description = "Контур полосы съёмки, WKT POLYGON (lon lat, ...)")
    val contourWkt: String,
    @field:Schema(description = "Идентификатор сохранённого режима съёмки в БД (null — маршрут не сохранялся)")
    val surveyModeId: Long? = null
) {
    @get:Schema(description = "Объём маршрута, Мбайт (накопление съёмки 120 Мбайт/с × длительность)")
    @get:JsonProperty(access = JsonProperty.Access.READ_ONLY)
    val volumeMb: Double get() = ModeDataRates.surveyVolumeMb(duration)
}
