package com.ffii.fpsms.modules.master.service

import com.ffii.core.support.AbstractBaseEntityService
import com.ffii.core.support.JdbcDao
import com.ffii.fpsms.modules.master.entity.Equipment
import com.ffii.fpsms.modules.master.entity.EquipmentRepository
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import com.ffii.fpsms.modules.master.web.models.NewEquipmentRequest

@Service
open class EquipmentService(
    private val jdbcDao: JdbcDao,
    private val equipmentRepository: EquipmentRepository,
) : AbstractBaseEntityService<Equipment, Long, EquipmentRepository>(jdbcDao, equipmentRepository) {

    open fun allEquipments(): List<Equipment> {
        return equipmentRepository.findAll()
    }

    open fun getEquipmentsByPage(args: Map<String, Any>): List<Map<String, Any>> {
        val sql = StringBuilder(
            """
            SELECT 
                e.id AS id, 
                e.code AS code, 
                e.name AS name, 
                e.description AS description, 
                e.equipmentTypeId AS equipmentTypeId,
                ed.repairAndMaintenanceStatus AS repairAndMaintenanceStatus,
                ed.latestRepairAndMaintenanceDate AS latestRepairAndMaintenanceDate,
                ed.lastRepairAndMaintenanceDate AS lastRepairAndMaintenanceDate,
                ed.repairAndMaintenanceRemarks AS repairAndMaintenanceRemarks
            FROM equipment e 
            LEFT JOIN equipment_detail ed ON e.code = ed.equipmentCode
            WHERE e.deleted = FALSE
            """
        )
        if (args.containsKey("code")) {
            sql.append(" AND e.code like :code ")
        }
        if (args.containsKey("id")) {
            sql.append(" AND e.id like :id ")
        }
        if (args.containsKey("name")) {
            sql.append(" AND e.name like :name ")
        }
        if (args.containsKey("description")) {
            sql.append(" AND e.description like :description ")
        }
        if (args.containsKey("equipmentTypeId")) {
            sql.append(" AND e.equipmentTypeId like :equipmentTypeId ")
        }
        return jdbcDao.queryForList(sql.toString(), args)
    }

    open fun findById(id: Long): Equipment? {
        return equipmentRepository.findByIdAndDeletedFalse(id)
    }

    open fun findByCode(code: String): Equipment? {
        return equipmentRepository.findByCodeAndDeletedIsFalse(code)
    }

    open fun findByName(name: String): Equipment? {
        return equipmentRepository.findByNameAndDeletedIsFalse(name)
    }

    open fun findByDescription(description: String): Equipment? {
        return equipmentRepository.findByDescriptionAndDeletedIsFalse(description)
    }

    @Transactional
    open fun saveEquipment(request: NewEquipmentRequest): Equipment {
        if (request.code.isNullOrBlank()) {
            throw IllegalArgumentException("Equipment type code cannot be null or blank")
        }
        val duplicated = equipmentRepository.findByCodeAndDeletedFalse(request.code!!)
        if (duplicated != null && duplicated.id != request.id) {
            throw IllegalArgumentException("Equipment type code already exists")
        }

        val entity = if (request.id != null && request.id > 0) {
            equipmentRepository.findByIdAndDeletedFalse(request.id) ?: Equipment()
        } else {
            Equipment()
        }

        entity.code = request.code
        entity.name = request.name
        entity.description = request.description
        entity.EquipmentDetail = request.equipmentType
        return equipmentRepository.saveAndFlush(entity)
    }

    @Transactional
    open fun deleteEquipment(id: Long) {
        val equipment = equipmentRepository.findByIdAndDeletedFalse(id)
        equipment?.let { et ->
            et.deleted = true
            equipmentRepository.saveAndFlush(et)
        }
    }
}