package yookassa

// Fiscal receipt support for «Чеки от ЮKassa» (54-ФЗ). YooKassa registers a receipt itself — no cash
// register to rent, no OFD contract — but only if the payment and refund requests carry a receipt
// object.
//
// It is DORMANT: the merchant runs on НПД, which is outside 54-ФЗ, so no receipt is sent and the
// merchant reports each operation to «Мой налог» instead. The code stays because the switch back is
// foreseeable — НПД has an annual income ceiling, and losing the regime puts 54-ФЗ back in force —
// and turning it on is then setting one deploy variable rather than writing this again. Everything
// here is inert while BACKEND_YOOKASSA_VAT_CODE is unset (see ReceiptEnabled). Reference:
// https://yookassa.ru/developers/payment-acceptance/receipts/54fz/yoomoney/parameters-values
const (
	// PaymentSubjectService is the settlement subject (54-ФЗ tag 1212) — what the money is taken
	// for. Chips are sold as a service ("Услуга").
	PaymentSubjectService = "service"
	// PaymentModeFullPayment is the settlement method (54-ФЗ tag 1214) — the payer pays and receives
	// the goods at once ("Полный расчет"). «Чеки от ЮKassa» accept only this and full_prepayment;
	// partial prepayment, advance and credit are not supported.
	PaymentModeFullPayment = "full_payment"

	// VatCodeNone is the VAT rate code (54-ФЗ tag 1199) for «Без НДС» — the rate a sole proprietor on
	// УСН or ПСН charges. The deployed value is configurable because the rate is the one receipt
	// attribute that genuinely changes (Russia raised the main rate on 1 Jan 2026, adding codes 11
	// and 12).
	VatCodeNone = 1
	// VatCodeOff is the configured value that means "send no receipt at all" — the state a merchant
	// outside 54-ФЗ runs in. It is the default, so receipts stay off until a rate is deliberately set.
	VatCodeOff = 0
	// VatCodeMax is the highest VAT rate code the API accepts; codes run 1..12.
	VatCodeMax = 12
)

// Customer is the payer's contact data for delivering the receipt. «Чеки от ЮKassa» deliver only by
// email (no SMS), so Email is required — the direct rail's confirmed email anchor supplies it.
type Customer struct {
	Email string `json:"email,omitempty"`
}

// ReceiptItem is one line of a fiscal receipt: what was sold, how much of it, for how much, and the
// three fiscal attributes that classify it.
type ReceiptItem struct {
	Description    string  `json:"description"`
	Quantity       float64 `json:"quantity"`
	Amount         Amount  `json:"amount"`
	VatCode        int     `json:"vat_code"`
	PaymentSubject string  `json:"payment_subject"`
	PaymentMode    string  `json:"payment_mode"`
}

// Receipt is the fiscal receipt data sent alongside a payment or a refund. tax_system_code is
// deliberately absent: YooKassa ignores it for «Чеки от ЮKassa».
type Receipt struct {
	Customer Customer      `json:"customer"`
	Items    []ReceiptItem `json:"items"`
}

// maxDescriptionRunes is the API's limit for both a payment description and a receipt line
// description (54-ФЗ tag 1030). A longer title is truncated rather than rejected, so an over-long
// product name cannot block a purchase.
const maxDescriptionRunes = 128

// SingleItemReceipt builds a one-line receipt for selling title at amount to email. Chip packs are
// always a single line bought once, so quantity is 1 and the line amount is the whole payment.
func SingleItemReceipt(email, title string, amount Amount, vatCode int) *Receipt {
	return &Receipt{
		Customer: Customer{Email: email},
		Items: []ReceiptItem{{
			Description:    TruncateDescription(title),
			Quantity:       1,
			Amount:         amount,
			VatCode:        vatCode,
			PaymentSubject: PaymentSubjectService,
			PaymentMode:    PaymentModeFullPayment,
		}},
	}
}

// TruncateDescription shortens s to the API's description limit, counting runes rather than bytes so
// a Cyrillic title is not cut mid-character.
func TruncateDescription(s string) string {
	r := []rune(s)
	if len(r) <= maxDescriptionRunes {
		return s
	}
	return string(r[:maxDescriptionRunes])
}

// ValidVatCode reports whether code is a rate the API accepts (1..12) or VatCodeOff, which disables
// receipts altogether.
func ValidVatCode(code int) bool { return code == VatCodeOff || (code >= 1 && code <= VatCodeMax) }

// ReceiptEnabled reports whether a configured VAT rate code asks for fiscal receipts. A merchant
// outside 54-ФЗ leaves the code unset and no receipt is built or sent.
func ReceiptEnabled(vatCode int) bool { return vatCode != VatCodeOff }
