package models

import "time"

// One message from a chat consultation.
//
// Agora RTM persists nothing, so the conversation exists only on the two
// devices until one of them uploads it. This table is written by that upload,
// never by the realtime path — the API never sees a message as it is sent.
//
// Both parties upload the same conversation, including the messages they
// received. That redundancy is the point: only one device may survive a kill,
// and the unique key on (consultationId, clientMessageId) makes the second
// copy a no-op rather than a duplicate.
//
// The contract that makes that work lives in the apps: ClientMessageID is
// generated once by the SENDING device, travels inside the RTM payload, is
// stored verbatim by the receiving device, and is echoed back by both on
// upload. If the receiver invents its own id instead, every message is stored
// twice and nothing on this side can tell.
//
// Hangs off consultations.id rather than the user_chat_histories mirror: that
// mirror is written only inside bill(), and not at all on the grace
// short-circuit, so a very short chat would have no parent row to attach to.
type ChatMessage struct {
	ID uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`

	ConsultationID uint `gorm:"column:consultationId" json:"consultationId"`

	// Denormalised off the consultation so support can filter without a join.
	UserID       uint `gorm:"column:userId" json:"userId"`
	AstrologerID uint `gorm:"column:astrologerId" json:"astrologerId"`

	// USER, ASTROLOGER or SYSTEM. Taken from the message, not from whoever
	// uploaded it. SenderID is resolved server-side from the consultation's
	// two parties and never read off the request body, or either side could
	// forge messages attributed to the other in a record the admin panel uses
	// to settle disputes.
	SenderType string `gorm:"column:senderType" json:"senderType"`
	SenderID   uint   `gorm:"column:senderId" json:"senderId"`

	ClientMessageID string `gorm:"column:clientMessageId" json:"clientMessageId"`

	// TEXT only in v1. The column and AttachmentURL exist now so that adding
	// media later is a code change rather than DDL on a live table.
	MessageType   string `gorm:"column:messageType" json:"messageType"`
	Body          string `gorm:"column:body" json:"body"`
	AttachmentURL string `gorm:"column:attachmentUrl" json:"attachmentUrl,omitempty"`

	// The sending device's clock, and its own counter within the session.
	// Ordering is (SentAt, Sequence, ID): two devices' clocks disagree, so a
	// tie has to break deterministically somehow.
	SentAt   *time.Time `gorm:"column:sentAt" json:"sentAt,omitempty"`
	Sequence int        `gorm:"column:sequence" json:"sequence"`

	// Which party's upload won the insert. Forensics only — it says nothing
	// about who wrote the message.
	UploadedBy string `gorm:"column:uploadedBy" json:"uploadedBy"`

	IsDelete  bool       `gorm:"column:isDelete" json:"-"`
	CreatedAt *time.Time `gorm:"column:created_at" json:"createdAt,omitempty"`
	UpdatedAt *time.Time `gorm:"column:updated_at" json:"-"`
}

func (ChatMessage) TableName() string {
	return "chat_messages"
}
