package kr.or.bok.rtgs.common.ledger

import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import kr.or.bok.rtgs.common.TxSts

/**
 * 권위 원장(PostgreSQL, 강한 일관성) 엔티티 — 3개 원장 서비스(Dior/Hermes/Prada)가 공유.
 * 개인(P2P) 잔액이 아니라 참가기관 당좌계좌 잔액을 기록한다(복원력방안 1.4).
 */

@Entity
@Table(name = "account")
class Account(
    @Id
    @Column(name = "code", length = 4)
    var code: String = "",

    @Column(name = "name")
    var name: String = "",

    /** 당좌계좌 잔액(원). 이체 시 강한 일관성으로 증감. */
    @Column(name = "balance", nullable = false)
    var balance: Long = 0,
)

@Entity
@Table(name = "transfer")
class TransferRecord(
    @Id
    @Column(name = "bmi", length = 22)
    var bmi: String = "",

    @Column(name = "global_seq")
    var globalSeq: Long? = null,

    @Column(name = "status", length = 8, nullable = false)
    @jakarta.persistence.Enumerated(jakarta.persistence.EnumType.STRING)
    var status: TxSts = TxSts.PDNG,

    @Column(name = "sender_code", length = 4) var senderCode: String = "",
    @Column(name = "receiver_code", length = 4) var receiverCode: String = "",
    @Column(name = "amount", nullable = false) var amount: Long = 0,
    @Column(name = "origin_center", length = 8) var originCenter: String = "",
    @Column(name = "created_at") var createdAt: Long = 0,
    @Column(name = "updated_at") var updatedAt: Long = 0,
    @Column(name = "reason") var reason: String? = null,
    /** 단계별 처리시각(서비스 타임라인): 기록(Dior)·정산(Hermes). 접수=raw_message, 순번=created_at, 완결=updated_at. */
    @Column(name = "pdng_at") var pdngAt: Long? = null,
    @Column(name = "acsp_at") var acspAt: Long? = null,
)

/**
 * 선(先)저널(write-ahead) 로그 — Hermes가 인메모리 잔액 연산 *전에* 순번을 여기에 확정한다.
 * 노드사 시 살아있는/재기동 센터가 이 로그로 재생해 무손실 승계(복원력방안 부록A S2).
 */
@Entity
@Table(name = "journal_log")
class JournalLog(
    @Id
    @Column(name = "global_seq")
    var globalSeq: Long = 0,

    @Column(name = "bmi", length = 22) var bmi: String = "",
    @Column(name = "seq_epoch_millis") var seqEpochMillis: Long = 0,
    @Column(name = "applied", nullable = false) var applied: Boolean = false,
)

/**
 * 원전문 저장(로컬은 PostgreSQL text 컬럼; 클라우드/BMT는 문서형 DB(MongoDB)).
 * 참가기관 pacs.008 원본 XML을 보관 — 센터 간엔 경량명령문만 복제.
 */
@Entity
@Table(name = "raw_message")
class RawMessageEntity(
    @Id @Column(name = "bmi", length = 22) var bmi: String = "",
    @Column(name = "msg_type", length = 32) var msgType: String = "",
    @Column(name = "raw_xml", columnDefinition = "text") var rawXml: String = "",
    @Column(name = "orig_hash", length = 64) var origHash: String = "",
    @Column(name = "received_at") var receivedAt: Long = 0,
    @Column(name = "origin_center", length = 8) var originCenter: String = "",
)

/**
 * 결과통보 아웃박스 — 접수센터(Chanel)가 신청/수취기관 앞 송부한 결과 전문(pacs.002) 기록.
 * id = bmi:수신기관 (기관별 1건, 재송부 시 멱등 upsert). 로컬은 실제 외부 송신 대신 기록+로그로
 * 송부를 모사한다(실외부 전송/콜백은 향후 Gucci 관문 담당).
 */
@Entity
@Table(name = "notification")
class NotificationEntity(
    @Id @Column(name = "id", length = 32) var id: String = "",
    @Column(name = "bmi", length = 22) var bmi: String = "",
    @Column(name = "to_org", length = 4) var toOrg: String = "",          // 수신 대상 기관
    @Column(name = "role", length = 12) var role: String = "",            // APPLICANT(신청기관) / BENEFICIARY(수취기관)
    @Column(name = "final_status", length = 8) var finalStatus: String = "",
    @Column(name = "pacs002_xml", columnDefinition = "text") var pacs002Xml: String = "",
    @Column(name = "origin_center", length = 8) var originCenter: String = "",
    @Column(name = "reason") var reason: String? = null,
    @Column(name = "delivered", nullable = false) var delivered: Boolean = false,
    @Column(name = "attempts", nullable = false) var attempts: Int = 0,   // 송부 시도 횟수(재시도)
    @Column(name = "created_at") var createdAt: Long = 0,
    @Column(name = "delivered_at") var deliveredAt: Long? = null,
)

/**
 * 조회 전용 사본(로컬은 PostgreSQL; 클라우드/BMT는 문서형 DB). 결과동기화(Prada)가 최종 확정 기록.
 */
@Entity
@Table(name = "settlement_view")
class SettlementViewEntity(
    @Id @Column(name = "bmi", length = 22) var bmi: String = "",
    @Column(name = "global_seq") var globalSeq: Long? = null,
    @Column(name = "final_status", length = 8) var finalStatus: String = "",
    @Column(name = "sender_code", length = 4) var senderCode: String = "",
    @Column(name = "receiver_code", length = 4) var receiverCode: String = "",
    @Column(name = "amount") var amount: Long = 0,
    @Column(name = "origin_center", length = 8) var originCenter: String = "",
    @Column(name = "processed_center", length = 8) var processedCenter: String = "",
    @Column(name = "debtor_balance_after") var debtorBalanceAfter: Long? = null,
    @Column(name = "creditor_balance_after") var creditorBalanceAfter: Long? = null,
    @Column(name = "finalized_at") var finalizedAt: Long = 0,
)
