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

import com.ffii.core.support.AbstractBaseEntityService
import com.ffii.fpsms.modules.master.entity.QcCategory
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.projections.QcCategoryCombo
import com.ffii.fpsms.modules.master.web.models.SaveQcCategoryRequest
import com.ffii.fpsms.modules.master.web.models.SaveQcCategoryResponse
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 QcCategoryService(
    private val qcCategoryRepository: QcCategoryRepository,
    private val qcItemCategoryRepository: QcItemCategoryRepository,
    private val itemsService: ItemsService
) {
    open fun allQcCategories(): List<QcCategory> {
        return qcCategoryRepository.findAllByDeletedIsFalse()
    }

    open fun findQcCategoryById(id: Long): QcCategory? {
        return qcCategoryRepository.findByIdAndDeletedIsFalse(id)
    }

    open fun getQcCategoryCombo(): List<QcCategoryCombo> {
        return qcCategoryRepository.findQcCategoryComboByDeletedIsFalse();
    }

    open fun getQcItemsByCategoryId(categoryId: Long): List<QcItemInfo> {
        return qcItemCategoryRepository.findAllByQcCategoryId(categoryId)
    }

    open fun getQcCategoryInfoByMapping(itemId : Long, type: String): QcCategoryInfo? {
        var result = qcCategoryRepository.findQcCategoryInfoByItemIdAndType(itemId, type)
        if (result == null) {   // Temporarily fix for missing QC template (Auto find template from similar items)
            val args = mapOf(
                "itemId" to itemId,
                "qcType" to type
            )
            val similarItemIds = itemsService.getItemsIdWithSameCategoryForQc(args);

            // Comment the lines below to disable auto matching QC from similar items
            result = if (similarItemIds.isNotEmpty())
                qcCategoryRepository.findQcCategoryInfoByItemIdAndType(similarItemIds[0].toLong(), type)
            else null
            //
            if (result == null) {   // Use Default Template
                val defaultTemplates = qcCategoryRepository.findQcCategoryInfoByIsDefault(true)
                result = defaultTemplates.firstOrNull()
            }
        }
        return result;
    }

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

        qcCategoryRepository.save(qcItem)

        return allQcCategories()
    }

    open fun saveQcCategory(@Valid @RequestBody request: SaveQcCategoryRequest): SaveQcCategoryResponse {
        val errors = mutableMapOf<String, String>()
        val id = request.id
        val qcCategory = if (id != null) qcCategoryRepository.findById(id).orElseThrow() else QcCategory()

        // check duplicated code
//        val duplicateQcCategory = findQcCategoryByCode(request.code)
//        if (duplicateQcCategory != null && duplicateQcCategory.id != qcCategory.id) {
//            errors["code"] = "Code is duplicated"
//        }

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

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

        val savedQcCategory = qcCategoryRepository.save(qcCategory)

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