package org.jpos.tcpay.db.entity;

import lombok.Data;
import lombok.experimental.Accessors;

import javax.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;

@Data
@Accessors(chain = true)
@Entity
@Table(name = "pos_temp_transaction", 
       indexes = {
           @Index(name = "idx_temp_transaction_btid_bmid", columnList = "b_tid,b_mid"),
           @Index(name = "idx_temp_transaction_stid", columnList = "s_tid")
       })
public class PosTempTransaction {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "s_tid", length = 8)
    private String sTid;

    @Column(name = "s_mid", length = 15)
    private String sMid;

    @Column(name = "s_tid_stan", length = 6)
    private String sTidStan;

    @Column(name = "s_tid_invoiceno", length = 6)
    private String sTidInvoiceNo;

    @Column(name = "s_tid_batchno", length = 6)
    private String sTidBatchNo;

    @Column(name = "b_tid", length = 8)
    private String bTid;

    @Column(name = "b_mid", length = 15)
    private String bMid;

    @Column(name = "acquirer_id")
    private Long acquirerId;

    @Column(name = "b_tid_stan", length = 6)
    private String bTidStan;

    @Column(name = "b_tid_invoiceno", length = 6)
    private String bTidInvoiceNo;

    @Column(name = "b_tid_batchno", length = 6)
    private String bTidBatchNo;

    @Column(name = "b_tid_date", length = 8)
    private String bTidDate;

    @Column(name = "b_tid_time", length = 6)
    private String bTidTime;

    @Column(name = "entry_mode", length = 3)
    private String entryMode;

    @Column(name = "condition_code", length = 2)
    private String conditionCode;

    @Column(name = "currency_code", length = 3)
    private String currencyCode;

    @Column(name = "mti", length = 4)
    private String mti;

    @Column(name = "proc_code", length = 6)
    private String procCode;

    @Column(name = "total_amount", precision = 12, scale = 2)
    private BigDecimal totalAmount;

    @Column(name = "auth_amount", precision = 12, scale = 2)
    private BigDecimal authAmount;

    @Column(name = "cash_amount", precision = 12, scale = 2)
    private BigDecimal cashAmount;

    @Column(name = "tip_amount", precision = 12, scale = 2)
    private BigDecimal tipAmount;

    @Column(name = "approval_code", length = 6)
    private String approvalCode;

    @Column(name = "reference_no", length = 12)
    private String referenceNo;

    @Column(name = "response_code", length = 2)
    private String responseCode;

    @Column(name = "response_message", length = 100)
    private String responseMessage;

    @Column(name = "mcc_code", length = 4)
    private String mccCode;

    @Column(name = "encrypted_track2", length = 256)
    private String encryptedTrack2;

    @Column(name = "encrypted_expiry", length = 4)
    private String encryptedExpiry;

    @Column(name = "encrypted_pan", length = 256)
    private String encryptedPan;

    @Column(name = "masked_card_no", length = 19)
    private String maskedCardNo;

    @Column(name = "pan_seq", length = 3)
    private String panSeq;

    @Column(name = "emv_data", columnDefinition = "TEXT")
    private String emvData;

    @Column(name = "acquirer_reference_no", length = 23)
    private String acquirerReferenceNo;

    @Column(name = "scheme_reference_no", length = 23)
    private String schemeReferenceNo;

    @Column(name = "created_dateTime")
    private LocalDateTime createdDateTime;

    @Column(name = "updated_dateTime")
    private LocalDateTime updatedDateTime;

    @Column(name = "metadata", columnDefinition = "TEXT")
    private String metadata;

    @Enumerated(EnumType.STRING)
    @Column(name = "status", length = 30, nullable = false)
    private TempTransactionStatus status = TempTransactionStatus.ACTIVE;

    @PrePersist
    protected void onCreate() {
        createdDateTime = LocalDateTime.now();
        updatedDateTime = LocalDateTime.now();
        if (status == null) {
            status = TempTransactionStatus.ACTIVE;
        }
    }

    @PreUpdate
    protected void onUpdate() {
        updatedDateTime = LocalDateTime.now();
    }

    /**
     * Status progression for temp transactions during reversal lifecycle
     */
    public enum TempTransactionStatus {
        ACTIVE,                    // Normal processing
        RESPONSE_TIMEOUT,          // Bank didn't respond in time
        CONNECTION_LOST,           // TCP/IP connection lost
        REVERSAL_PENDING,          // Reversal request sent
        REVERSAL_SENT,            // Reversal confirmed sent
        REVERSAL_COMPLETED,        // Reversal successful
        REVERSAL_FAILED,          // Reversal failed - needs retry
        REVERSAL_ERROR,           // Error in reversal process
        PENDING_MANUAL_REVIEW     // Requires manual intervention
    }
}