package constants

// The consultation and settlement vocabulary, shared by all three stacks: the
// user side writes these values when a session is billed, the admin side moves
// rows between the settlement statuses, and the astrologer side reads them.
// They are string columns in MySQL, so a typo is a silent no-match rather than
// an error — always use these constants.

//------------------------------------------------
// Media
//------------------------------------------------

const (
	MediumChat  = "CHAT"
	MediumAudio = "AUDIO"
	MediumVideo = "VIDEO"
)

//------------------------------------------------
// Session status
//------------------------------------------------

const (
	ConsultationStatusRequested = "REQUESTED"
	ConsultationStatusAccepted  = "ACCEPTED"
	ConsultationStatusOngoing   = "ONGOING"
	ConsultationStatusCompleted = "COMPLETED"
	ConsultationStatusRejected  = "REJECTED"
	ConsultationStatusCancelled = "CANCELLED"
	ConsultationStatusMissed    = "MISSED"
)

//------------------------------------------------
// Why the session stopped
//------------------------------------------------

const (
	EndReasonUserEnded = "USER_ENDED"

	EndReasonAstrologerEnded = "ASTROLOGER_ENDED"

	// The balance-check tick ran the wallet down to the point where the next
	// minute could not be paid for, so the session was cut.
	EndReasonInsufficientBalance = "INSUFFICIENT_BALANCE"

	// Nobody ended it: the ticks stopped arriving (app killed, network gone)
	// and the stale-session sweeper closed and billed it.
	EndReasonAbandoned = "ABANDONED"

	EndReasonRejected  = "REJECTED"
	EndReasonCancelled = "CANCELLED"

	// The request rang until the ring timeout without the astrologer
	// answering. Nothing is billed and the free-chat entitlement survives.
	EndReasonNoAnswer = "NO_ANSWER"

	// The astrologer accepted but the customer never tapped Start chat, so
	// the session never opened. Nothing is billed, the astrologer is released
	// and the free-chat entitlement survives.
	EndReasonNotJoined = "NOT_JOINED"

	// A free chat reached the end of its funded minutes.
	EndReasonFreeMinutesOver = "FREE_MINUTES_OVER"

	// Support closed the session from the admin panel. Server-written only —
	// deliberately absent from the end reasons a client may send.
	EndReasonAdminEnded = "ADMIN_ENDED"
)

//------------------------------------------------
// Settlement status
//------------------------------------------------
//
// The order a billed consultation travels through:
//
//	PENDING -> TO_BE_SETTLED -> SETTLED
//
// with ON_HOLD and REJECTED as the admin's two ways out. NA is for sessions
// that were never billed, so there is nothing to settle.

const (
	SettlementStatusNA          = "NA"
	SettlementStatusPending     = "PENDING"
	SettlementStatusToBeSettled = "TO_BE_SETTLED"
	SettlementStatusSettled     = "SETTLED"
	SettlementStatusOnHold      = "ON_HOLD"
	SettlementStatusRejected    = "REJECTED"
)

//------------------------------------------------
// wallet_settlements.settlement_type
//------------------------------------------------
//
// One table, two opposite money movements. A batch credits the astrologer
// wallet from settled consultations; a payout debits it for a withdrawal.

const (
	SettlementTypeConsultationBatch = "CONSULTATION_BATCH"
	SettlementTypeWithdrawPayout    = "WITHDRAW_PAYOUT"
)

// wallet_settlements.settlement_status for a batch. "Completed" (not
// "SETTLED") because that is the string the existing withdraw flow and
// GetPendingEarnings already agree on for a finished settlement row.
const (
	BatchStatusCompleted = "Completed"
	BatchStatusFailed    = "Failed"
)

//------------------------------------------------
// wallettransaction.transactionType / wallet_ledger.transaction_type
//------------------------------------------------

const (
	TxnTypeChatConsultation  = "CHAT_CONSULTATION"
	TxnTypeAudioConsultation = "AUDIO_CONSULTATION"
	TxnTypeVideoConsultation = "VIDEO_CONSULTATION"

	// The credit the settlement job writes into the astrologer wallet.
	TxnTypeSettlement = "SETTLEMENT"
)

//------------------------------------------------
// Admin review trail
//------------------------------------------------

const (
	ActionSourceAdmin  = "ADMIN"
	ActionSourceSystem = "SYSTEM"
)

//------------------------------------------------
// Settlement schedule
//------------------------------------------------

const (
	SettlementFrequencyWeekly  = "WEEKLY"
	SettlementFrequencyMonthly = "MONTHLY"
	SettlementFrequencyCustom  = "CUSTOM"
)

//------------------------------------------------
// systemflag names
//------------------------------------------------
//
// Every price and rule in this layer is server-side. Nothing here may be
// taken from a request body.

const (
	FlagPlatformCommissionPercent   = "PlatformCommissionPercent"
	FlagMinConsultationMinutes      = "MinConsultationMinutes"
	FlagConsultationGraceSeconds    = "ConsultationGraceSeconds"
	FlagConsultationTickTimeoutSecs = "ConsultationTickTimeoutSecs"

	FlagSettlementCronExpression = "SettlementCronExpression"
	FlagSettlementFrequency      = "SettlementFrequency"
	FlagSettlementDayOfWeek      = "SettlementDayOfWeek"
	FlagSettlementDayOfMonth     = "SettlementDayOfMonth"
	FlagSettlementRunTime        = "SettlementRunTime"
	FlagSettlementAutoApprove    = "SettlementAutoApprove"
	FlagSettlementMinPayout      = "SettlementMinPayout"

	//------------------------------------------------
	// The request -> accept -> start handshake
	//------------------------------------------------

	// How long a REQUESTED session rings before it is marked MISSED.
	FlagConsultationRingTimeoutSecs = "ConsultationRingTimeoutSecs"

	// How long an ACCEPTED session waits for the customer to tap Start chat
	// before it is released. Without this an astrologer is held busy by a
	// customer who walked away.
	FlagConsultationJoinTimeoutSecs = "ConsultationJoinTimeoutSecs"

	// Talk time remaining when both parties are warned the session is ending.
	FlagConsultationWarningSeconds = "ConsultationWarningSeconds"

	// Hard ceiling on one session whatever the wallet allows. 0 disables it.
	FlagConsultationMaxMinutes = "ConsultationMaxMinutes"

	// 1 means an astrologer with no astrologer_status row cannot be
	// requested. Ships at 0 because that table is empty on this database.
	FlagConsultationAvailabilityStrict = "ConsultationAvailabilityStrict"

	// Chat sessions get their own, longer tick timeout: backgrounding an app
	// mid-chat is normal, mid-call it is not. 0 falls back to
	// ConsultationTickTimeoutSecs.
	FlagChatTickTimeoutSecs = "ChatTickTimeoutSecs"

	//------------------------------------------------
	// Free chat
	//------------------------------------------------

	FlagChatConsultationEnabled = "ChatConsultationEnabled"
	FlagFreeChatEnabled         = "FreeChatEnabled"
	FlagFreeChatMinutes         = "FreeChatMinutes"

	// Below this a free session pays nobody and does not use up the
	// customer's one lifetime free chat, so a network drop in the first
	// seconds is not charged to their entitlement.
	FlagFreeChatMinConnectedSeconds = "FreeChatMinConnectedSeconds"

	//------------------------------------------------
	// Transcripts
	//------------------------------------------------

	FlagChatTranscriptWindowHours = "ChatTranscriptWindowHours"
	FlagChatTranscriptMaxMessages = "ChatTranscriptMaxMessages"
)

//------------------------------------------------
// Chat transcript vocabulary
//------------------------------------------------
//
// Who wrote a message. Taken from the message itself, never from whoever
// uploaded it: each app posts both sides of the conversation.

const (
	SenderTypeUser       = "USER"
	SenderTypeAstrologer = "ASTROLOGER"
	SenderTypeSystem     = "SYSTEM"
)

const (
	MessageTypeText   = "TEXT"
	MessageTypeSystem = "SYSTEM"
)

//------------------------------------------------
// Status predicates
//------------------------------------------------
//
// So the astrologer and admin stacks can ask about a session's state without
// each re-spelling the status strings.

// IsLiveStatus reports whether a session is accepted or running. These are the
// two statuses bill() will close.
func IsLiveStatus(status string) bool {
	return status == ConsultationStatusAccepted || status == ConsultationStatusOngoing
}

// IsPendingStatus reports whether a session is still ringing.
func IsPendingStatus(status string) bool {
	return status == ConsultationStatusRequested
}

// IsOpenStatus covers everything that occupies a customer or an astrologer:
// ringing, accepted, or running. A second request is refused while one of
// these exists.
func IsOpenStatus(status string) bool {
	return IsPendingStatus(status) || IsLiveStatus(status)
}

// MediumTransactionType maps a medium to the transactionType stored on the
// customer's wallet row, so the wallet history can be filtered by medium.
func MediumTransactionType(medium string) string {

	switch medium {

	case MediumAudio:
		return TxnTypeAudioConsultation

	case MediumVideo:
		return TxnTypeVideoConsultation

	default:
		return TxnTypeChatConsultation
	}
}

// IsValidMedium guards the medium coming off a request body.
func IsValidMedium(medium string) bool {

	switch medium {

	case MediumChat, MediumAudio, MediumVideo:
		return true

	default:
		return false
	}
}
