package com.dowstats.service.datamaps

import com.dowstats.Metadata.Requirements
import com.dowstats.data.dto.controllers.building.BuildingFullDto
import com.dowstats.data.dto.controllers.building.RaceBuildings
import com.dowstats.data.entities.building.Building
import com.dowstats.data.repositories.BuildingRepository
import com.dowstats.data.repositories.RaceRepository
import com.dowstats.service.datamaps.CommonMapping.toBuildingShortDto
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service

@Service
class DowBuildingMappingService @Autowired constructor(
    val buildingRepository: BuildingRepository,
    val requirementsMappingComponent: RequirementsMappingComponent,
    val raceRepository: RaceRepository
) {

    fun findBuildingsByMod(modId: Long): List<RaceBuildings> {
        return getAllBuildings(modId).groupBy { it.race }.mapNotNull { raceBuildings ->
            RaceBuildings(raceBuildings.key?.toDto() ?: throw Exception("Race is null"),
                raceBuildings.value.filter { !it.advancedBuildOption }.toBuildingShortDto(withoutUnits = true),
                raceBuildings.value.filter { it.advancedBuildOption }.toBuildingShortDto(withoutUnits = true),)
        }
    }

    fun findBuildingsByModAndRace(modId: Long, race: String): RaceBuildings {
        val buildings = getAllBuildings(modId, race)
        val raceEntity = race.let { raceRepository.findById(race) ?: throw Exception("Race $race not found") }
        return RaceBuildings(raceEntity.toDto(), buildings.filter { !it.advancedBuildOption }.toBuildingShortDto(),
            buildings.filter { it.advancedBuildOption }.toBuildingShortDto())
    }

    fun mapToDto(building: Building): BuildingFullDto {

        val buildingAddons = building.addons?.sortedBy { it.uiIndexHint }?.map { addon ->

            val replaceWhenDone = addon.addonRequirements?.find { it.reference ==Requirements.REFERENCE_REQUIREMENT_ADDON }
                ?.replaceWhenDone ?: false
            val requirement = requirementsMappingComponent
                .getRequirements(addon.addonRequirements?.toList() ?: emptyList(),
                    building.modId!!
                )

            addon.toDto(requirement?.copy(
                replaceWhenDone = replaceWhenDone,
                requirementBuildings = requirement.requirementBuildings.filter { it.id != building.id }.toSet())
            )
        }

        val researches = building.researches?.map {research ->
            research.toResearchShortDto()
        }?.sortedBy { it.uiIndexHint }

        val requirementDto = requirementsMappingComponent
            .getRequirements(building.buildingRequirements.toList(),
                building.modId!!)

        val weapons = building.weapons?.map { buildingWeapon ->
            buildingWeapon.toWeaponSlotDto()
        }?.toSet() ?: emptySet()

        return building.toDto(buildingAddons, researches, weapons, requirementDto)
    }


    private fun getAllBuildings(modId: Long, race: String? = null): List<Building> {
        val raceEntity = race?.let { raceRepository.findById(race) ?: throw Exception("Race $race not found") }
        return buildingRepository.findByModIdAndRace(modId, raceEntity)
    }

}