package kr.or.bok.rtgs.dior

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import kr.or.bok.rtgs.common.ledger.TransferRecord
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Modifying
import org.springframework.data.jpa.repository.Query
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.data.repository.query.Param

@SpringBootApplication
@EntityScan("kr.or.bok.rtgs.common.ledger")
@EnableJpaRepositories(considerNestedRepositories = true)
class DiorApplication {
    @Bean
    fun objectMapper(): ObjectMapper = jacksonObjectMapper()
}

interface TransferRepository : JpaRepository<TransferRecord, String> {
    /**
     * 접수내역을 PDNG로 삽입하되, 이미 존재하면(=Hermes/타 소비자가 먼저 만든 경우) 상태·금액 등은 건드리지 않고
     * 기록시각(pdng_at)만 비어있을 때 채운다(COALESCE). 원자적 upsert라 Dior-Hermes 동시 삽입 경합에서
     * 중복키 예외가 발생하지 않으며, 어느 쪽이 먼저 행을 만들어도 pdng_at은 유실 없이 기록된다.
     */
    @Modifying
    @Query(
        value = """
            INSERT INTO transfer
              (bmi, global_seq, status, sender_code, receiver_code, amount, origin_center, created_at, updated_at, pdng_at)
            VALUES
              (:bmi, :seq, 'PDNG', :sender, :receiver, :amount, :origin, :createdAt, :updatedAt, :pdngAt)
            ON CONFLICT (bmi) DO UPDATE SET
              pdng_at = COALESCE(transfer.pdng_at, EXCLUDED.pdng_at)
        """,
        nativeQuery = true,
    )
    fun insertPdngIfAbsent(
        @Param("bmi") bmi: String,
        @Param("seq") seq: Long,
        @Param("sender") sender: String,
        @Param("receiver") receiver: String,
        @Param("amount") amount: Long,
        @Param("origin") origin: String,
        @Param("createdAt") createdAt: Long,
        @Param("updatedAt") updatedAt: Long,
        @Param("pdngAt") pdngAt: Long,
    ): Int
}

fun main(args: Array<String>) {
    runApplication<DiorApplication>(*args)
}
