package com.dowstats.data.entities.research

import com.dowstats.data.dto.controllers.AffectedDataDto
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.dto.controllers.ModifierDto
import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.research.ResearchDto
import com.dowstats.data.dto.controllers.research.ResearchShortDto
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.weapon.Weapon
import jakarta.persistence.*


@Entity
@Table(name = "researches")
class Research {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long? = null

    var name: String? = null
    var description: String? = null
    var filename: String? = null
    var costRequisition: Double? = null
    var costPower: Double? = null
    var costFaith: Double? = null
    var costSouls: Double? = null
    var costTime: Double? = null
    var uiIndexHint: Int = 0
    var uiHotkeyName: String? = null
    var icon: String? = null
    var modId: Long? = null

    @OneToMany(mappedBy = "research", cascade = [CascadeType.ALL])
    var researchModifiers: MutableSet<ResearchModifiers> = mutableSetOf()

    @OneToMany(mappedBy = "research", cascade = [CascadeType.ALL])
    var researchRequirements: MutableSet<ResearchRequirements> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "researches_affected_units",
        joinColumns = [JoinColumn(name = "research_id")],
        inverseJoinColumns = [JoinColumn(name = "unit_id")])
    var affectedUnits: MutableSet<DowUnit> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "researches_affected_sergeants",
        joinColumns = [JoinColumn(name = "research_id")],
        inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
    var affectedSergeants: MutableSet<Sergeant> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "researches_affected_buildings",
        joinColumns = [JoinColumn(name = "research_id")],
        inverseJoinColumns = [JoinColumn(name = "building_id")])
    var affectedBuildings: MutableSet<Building> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "researches_affected_weapons",
        joinColumns = [JoinColumn(name = "research_id")],
        inverseJoinColumns = [JoinColumn(name = "weapon_id")])
    var affectedWeapons: MutableSet<Weapon> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "buildings_researches",
        joinColumns = [JoinColumn(name = "research_id")],
        inverseJoinColumns = [JoinColumn(name = "building_id")])
    var buildings: MutableSet<Building>? = null

    fun toResearchShortDto(): ResearchShortDto = ResearchShortDto(
        id = id!!,
        name = name,
        icon = icon,
        uiIndexHint = uiIndexHint,
        buildings?.firstOrNull()?.id
    )

    fun toResearchDto(requirements: RequirementDto?): ResearchDto = ResearchDto(
        id = id!!,
        name = name,
        icon = icon,
        uiIndexHint = uiIndexHint,
        filename = filename,
        description = description,
        costRequisition = costRequisition,
        costPower = costPower,
        costFaith = costFaith,
        costSouls = costSouls,
        costTime = costTime,
        modifiers = researchModifiers.map { it.toDto() }.sortedBy { it.target },
        requirements = requirements,
        affectedData = AffectedDataDto(
            affectedUnits.map { it.compressDto() }.toSet(),
            affectedSergeants.toShortDtoSet(),
            affectedBuildings.map { it.compressDto() }.toSet(),
            affectedWeapons.toShortDtoSet(),
        ),
        modId = modId,
        hotkey = uiHotkeyName
    )
}
