package dto

//------------------------------------------------
// Start
//------------------------------------------------

type StartConsultationRequest struct {
	AstrologerID uint `json:"astrologer_id" binding:"required"`

	// CHAT, AUDIO or VIDEO.
	Medium      string `json:"medium" binding:"required"`
	ChannelName string `json:"channel_name"`

	Name       string `json:"name"`
	BirthDate  string `json:"birth_date"`
	BirthTime  string `json:"birth_time"`
	BirthPlace string `json:"birth_place"`
	Gender     string `json:"gender"`
}

type StartConsultationResponse struct {
	ConsultationID uint    `json:"consultation_id"`
	ConsultationNo string  `json:"consultation_no"`
	AstrologerID   uint    `json:"astrologer_id"`
	AstrologerName string  `json:"astrologer_name"`
	Medium         string  `json:"medium"`
	Status         string  `json:"status"`
	RatePerMinute  float64 `json:"rate_per_minute"`
	WalletBalance  float64 `json:"wallet_balance"`
	// How long the customer's balance can pay for. The app must disconnect at
	// this point; billing will not go past it either way.
	MaxBillableSeconds int `json:"max_billable_seconds"`
	MaxBillableMinutes int `json:"max_billable_minutes"`

	ChannelName string `json:"channel_name"`

	StartedAt string `json:"started_at"`

	// Seconds after which a session with no tick is treated as abandoned.
	// The app should tick more often than this.
	TickIntervalSeconds int `json:"tick_interval_seconds"`
}

//------------------------------------------------
// Tick
//------------------------------------------------

// TickRequest is the periodic balance check while a session runs. It is what
// keeps a wallet from going negative: the app calls it on a timer and hangs up
// when ShouldDisconnect comes back true.
type TickRequest struct {
	ConsultationID uint `json:"consultation_id" binding:"required"`
}

type TickResponse struct {
	ConsultationID uint   `json:"consultation_id"`
	Status         string `json:"status"`

	ElapsedSeconds int `json:"elapsed_seconds"`

	// Seconds left before the balance runs out. 0 with ShouldDisconnect true
	// means hang up now.
	RemainingSeconds int `json:"remaining_seconds"`

	// What the session has run up so far, if it ended this second.
	CurrentCharge float64 `json:"current_charge"`

	WalletBalance float64 `json:"wallet_balance"`

	ShouldDisconnect bool   `json:"should_disconnect"`
	DisconnectReason string `json:"disconnect_reason,omitempty"`

	IsFreeChat bool `json:"is_free_chat"`

	// True on the single tick that crosses the warning threshold, not on
	// every tick below it. Latch it client-side.
	Warning bool `json:"warning"`

	// LOW_BALANCE, FREE_CHAT_ENDING or MAX_DURATION. Only meaningful when
	// Warning is true.
	//
	// FREE_CHAT_ENDING is the one with a decision attached: the customer can
	// call /consultation/continue-paid to carry on at the astrologer's rate,
	// and silence ends the session.
	WarningType string `json:"warning_type,omitempty"`

	WarningSeconds int `json:"warning_seconds,omitempty"`

	// How often to call this, and how long a silence has to last before the
	// session is closed as abandoned. These are different numbers with a 4x
	// ratio — poll at the interval, never at the timeout.
	TickIntervalSeconds int `json:"tick_interval_seconds,omitempty"`
	TickTimeoutSeconds  int `json:"tick_timeout_seconds,omitempty"`

	ServerTime string `json:"server_time,omitempty"`
}

//------------------------------------------------
// End
//------------------------------------------------

type EndConsultationRequest struct {
	ConsultationID uint `json:"consultation_id" binding:"required"`

	// USER_ENDED (default), ASTROLOGER_ENDED or INSUFFICIENT_BALANCE. Any
	// other value is rejected — the remaining reasons are written by the
	// server, not claimed by a client.
	EndReason string `json:"end_reason"`

	// Optional duration the client observed, seconds. Used only when it is
	// *shorter* than what the server measured, so a client can shorten its
	// own bill but never lengthen it.
	ClientDurationSeconds int `json:"client_duration_seconds"`
}

// EndConsultationResponse is the customer's receipt. The astrologer's share is
// reported as owed, not paid: it is credited only after admin review and the
// settlement run.
type EndConsultationResponse struct {
	ConsultationID uint   `json:"consultation_id"`
	ConsultationNo string `json:"consultation_no"`

	Medium string `json:"medium"`
	Status string `json:"status"`

	EndReason string `json:"end_reason"`

	DurationSeconds int    `json:"duration_seconds"`
	Duration        string `json:"duration"`

	BilledMinutes int     `json:"billed_minutes"`
	RatePerMinute float64 `json:"rate_per_minute"`

	// What was taken from the customer's wallet.
	DeductedAmount float64 `json:"deducted_amount"`

	WalletBalance float64 `json:"wallet_balance"`

	// The split behind the deduction. Shown to the customer as a breakdown;
	// the astrologer's own app reads it from its own endpoints.
	PlatformFee       float64 `json:"platform_fee"`
	AstrologerEarning float64 `json:"astrologer_earning"`

	SettlementStatus string `json:"settlement_status"`

	EndedAt string `json:"ended_at"`
}

//------------------------------------------------
// Active session
//------------------------------------------------

// ActiveConsultationResponse lets an app that was killed mid-session rejoin
// instead of starting a second one.
type ActiveConsultationResponse struct {
	HasActive bool `json:"has_active"`

	ConsultationID uint   `json:"consultation_id,omitempty"`
	ConsultationNo string `json:"consultation_no,omitempty"`

	AstrologerID   uint   `json:"astrologer_id,omitempty"`
	AstrologerName string `json:"astrologer_name,omitempty"`

	Medium string `json:"medium,omitempty"`
	Status string `json:"status,omitempty"`

	ChannelName string `json:"channel_name,omitempty"`

	RatePerMinute float64 `json:"rate_per_minute,omitempty"`

	ElapsedSeconds   int `json:"elapsed_seconds,omitempty"`
	RemainingSeconds int `json:"remaining_seconds,omitempty"`

	CurrentCharge float64 `json:"current_charge,omitempty"`
	WalletBalance float64 `json:"wallet_balance,omitempty"`

	StartedAt string `json:"started_at,omitempty"`

	IsFreeChat  bool `json:"is_free_chat"`
	FreeMinutes int  `json:"free_minutes,omitempty"`

	MaxBillableSeconds int `json:"max_billable_seconds,omitempty"`

	// Poll the tick at the interval, never at the timeout. They are different
	// numbers with a 4x ratio between them.
	TickIntervalSeconds int `json:"tick_interval_seconds,omitempty"`
	TickTimeoutSeconds  int `json:"tick_timeout_seconds,omitempty"`
	WarningSeconds      int `json:"warning_seconds,omitempty"`

	// Set when the recovered session is still ringing, or was accepted and is
	// waiting for the customer to open it. The app resumes the matching
	// countdown rather than starting a new request.
	RingExpiresAt    string `json:"ring_expires_at,omitempty"`
	SecondsToExpiry  int    `json:"seconds_to_expiry,omitempty"`
	JoinExpiresAt    string `json:"join_expires_at,omitempty"`
	SecondsToJoinEnd int    `json:"seconds_to_join_end,omitempty"`

	// Anchor the countdown to this rather than the device clock: the server
	// bills from started_at, and a device running fast would otherwise show a
	// number the customer will dispute.
	ServerTime string `json:"server_time,omitempty"`

	// Freshly minted on every call. Always renew with what this returns after
	// a resume; never reuse a cached token.
	Agora *AgoraCredentials `json:"agora,omitempty"`
}

//------------------------------------------------
// History
//------------------------------------------------

type ConsultationHistoryItem struct {
	ConsultationID uint   `json:"consultation_id"`
	ConsultationNo string `json:"consultation_no"`

	AstrologerID    uint   `json:"astrologer_id"`
	AstrologerName  string `json:"astrologer_name"`
	AstrologerImage string `json:"astrologer_image"`

	Medium string `json:"medium"`
	Status string `json:"status"`

	Duration      string  `json:"duration"`
	BilledMinutes int     `json:"billed_minutes"`
	RatePerMinute float64 `json:"rate_per_minute"`

	DeductedAmount float64 `json:"deducted_amount"`

	ConsulteeName string `json:"consultee_name"`

	Date string `json:"date"`
}

type ConsultationHistoryResponse struct {
	Items []ConsultationHistoryItem `json:"items"`

	Page       int   `json:"page"`
	Limit      int   `json:"limit"`
	Total      int64 `json:"total"`
	TotalPages int   `json:"total_pages"`
}
