package com.nisemoe.nise.search

import org.jooq.Condition
import org.jooq.Field
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter

class PredicateBuilder {

    companion object {

        fun buildBooleanCondition(field: Field<Boolean>, operator: String, value: Boolean): Condition {
            return when (operator) {
                "=" -> field.eq(value)
                "!=" -> field.ne(value)
                else -> throw IllegalArgumentException("Invalid operator")
            }
        }

        fun buildGradeCondition(field: Field<String>, operator: String, value: String): Condition {
            return when (value) {
                "SS", "S", "A", "B", "C", "D" -> {
                    val valuesToMatch = when (value) {
                        "SS" -> listOf("Grade.SS", "Grade.SSH")
                        "S" -> listOf("Grade.S", "Grade.SH")
                        else -> listOf("Grade.$value")
                    }
                    when (operator) {
                        "=" -> field.`in`(valuesToMatch)
                        "!=" -> field.notIn(valuesToMatch)
                        else -> throw IllegalArgumentException("Invalid operator")
                    }
                }
                else -> throw IllegalArgumentException("Invalid grade value")
            }
        }

        fun buildNumberCondition(field: Field<Double>, operator: String, value: Double): Condition {
            return when (operator) {
                "=" -> field.eq(value)
                ">" -> field.gt(value)
                "<" -> field.lt(value)
                ">=" -> field.ge(value)
                "<=" -> field.le(value)
                "!=" -> field.ne(value)
                else -> throw IllegalArgumentException("Invalid operator")
            }
        }

        fun buildStringCondition(field: Field<String>, operator: String, value: String): Condition {
            return when (operator.lowercase()) {
                "=" -> field.eq(value)
                "contains" -> field.containsIgnoreCase(value)
                "like" -> field.likeIgnoreCase(
                    // Escape special characters for LIKE if needed
                    value.replace("%", "\\%").replace("_", "\\_")
                )

                else -> throw IllegalArgumentException("Invalid operator")
            }
        }

        fun buildDatetimeCondition(field: Field<String>, operator: String, value: String): Condition {

            if(field.type == OffsetDateTime::class.java) {
                val fieldOffset = field as Field<OffsetDateTime>
                val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm")
                val parsedDate = OffsetDateTime.parse(value, formatter.withZone(ZoneOffset.UTC))

                return when (operator.lowercase()) {
                    "before" -> fieldOffset.lessThan(parsedDate)
                    "after" -> fieldOffset.greaterThan(parsedDate)
                    else -> throw IllegalArgumentException("Invalid operator")
                }
            }

            return when (operator.lowercase()) {
                "before" -> field.lessThan(value)
                "after" -> field.greaterThan(value)
                else -> throw IllegalArgumentException("Invalid operator")
            }
        }

    }

}