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

import com.ffii.core.exception.NotFoundException
import com.ffii.fpsms.modules.master.entity.QcCategoryRepository
import com.ffii.fpsms.modules.master.entity.QcItem
import com.ffii.fpsms.modules.master.entity.QcItemCategoryRepository
import com.ffii.fpsms.modules.master.entity.QcItemRepository
import com.ffii.fpsms.modules.master.web.models.SaveQcItemRequest
import com.ffii.fpsms.modules.master.web.models.SaveQcItemResponse
import com.ffii.fpsms.modules.qc.entity.projection.QcCategoryInfo
import com.ffii.fpsms.modules.qc.entity.projection.QcItemInfo
import jakarta.validation.Valid
import org.springframework.stereotype.Service
import org.springframework.web.bind.annotation.RequestBody

@Service
open class QcItemService(
    private val qcItemRepository: QcItemRepository,
    private val qcCategoryRepository: QcCategoryRepository,
    private val qcItemCategoryRepository: QcItemCategoryRepository,
) {
    open fun allQcItems(): List<QcItem> {
        return qcItemRepository.findAllByDeletedIsFalse()
    }

    open fun findQcItemByCode(code: String): QcItem? {
        return qcItemRepository.findByCodeAndDeletedIsFalse(code)
    }

    open fun findQcItemById(id: Long): QcItem? {
        return qcItemRepository.findByIdAndDeletedIsFalse(id)
    }

    open fun findQcItemsByTemplate(itemId: Long, type: String): List<QcItemInfo>? {
        val qcCategoryInfo = qcCategoryRepository.findQcCategoryInfoByItemIdAndType(itemId, type) ?: throw NotFoundException()
        return qcItemCategoryRepository.findAllByQcCategoryId(qcCategoryInfo.id)
    }

    open fun markDeleted(id: Long): List<QcItem> {
        val qcItem = qcItemRepository.findById(id).orElseThrow().apply {
            deleted = true
        }

        qcItemRepository.save(qcItem)

        return allQcItems()
    }

    open fun saveQcItem(@Valid @RequestBody request: SaveQcItemRequest): SaveQcItemResponse {

//        val qcItemProperties = QcItem::class.members.filterIsInstance<KProperty<QcItem>>()
        val errors = mutableMapOf<String, String>()
        val id = request.id
        val qcItem = if (id != null) qcItemRepository.findById(id).orElseThrow() else QcItem()

        // check duplicated code
//        val duplicateQcItem = findQcItemByCode(request.code)
//        if (duplicateQcItem != null && duplicateQcItem.id != qcItem.id) {
//            errors["code"] = "Code is duplicated"
//        }

        if (errors.isNotEmpty()) {
            request.let {
                SaveQcItemResponse(
                    id = it.id,
                    code = it.code,
                    name = it.name,
                    description = it.description,
                    errors = errors
                )
            }
        }

        // Save Qc Item
        qcItem.apply {
            code = request.code
            name = request.name
            description = request.description
        }

        val savedQcItem = qcItemRepository.save(qcItem)

        return savedQcItem.let {
            SaveQcItemResponse(
                id = it.id,
                code = it.code,
                name = it.name,
                description = it.description,
                errors = null
            )
        }
    }
}