package qrbill

import (
	"crypto/rand"
	"fmt"
	"time"
)

func generateReference() string {
	// 1) Build the 26-digit payload from time + random suffix
	now := time.Now().UTC()
	ts := now.Format("20060102150405") // YYYYMMDDHHMMSS -> 14 chars
	ns := now.Nanosecond()             // 0..999999999
	// format nanoseconds as 9 digits, zero padded
	nsStr := fmt.Sprintf("%09d", ns)

	// 3-digit random suffix (000..999) to reach 26 digits
	randBytes := make([]byte, 2) // we'll read 2 bytes and map to 0..999
	rand.Read(randBytes)

	// convert to number 0..65535 then mod 1000
	rnum := int(randBytes[0])<<8 | int(randBytes[1])
	rnum = rnum % 1000
	randStr := fmt.Sprintf("%03d", rnum)

	// compose 26-digit payload: 14 + 9 + 3 = 26
	payload := ts + nsStr + randStr

	// Safety: ensure payload is 26 digits (should always be true)
	if len(payload) != 26 {
		panic(fmt.Errorf("internal error: payload length %d != 26", len(payload)))
	}

	// 2) Compute Modulo-10 recursive check digit
	check := mod10RecursiveChecksum(payload)

	// 3) Build full 27-digit reference
	full := payload + fmt.Sprintf("%d", check)

	// 4) Format with grouping: 2-5-5-5-5-5
	formatted := fmt.Sprintf("%s %s %s %s %s %s",
		full[0:2],
		full[2:7],
		full[7:12],
		full[12:17],
		full[17:22],
		full[22:27],
	)
	return formatted
}

// mod10RecursiveChecksum computes the Mod10 recursive check digit for a numeric string.
// Implements the table-based recursive mod10 described in Swiss Annex B / ISR implementations.
func mod10RecursiveChecksum(digits string) int {
	// table as used in ISR/QR implementations
	arrTable := [10]int{0, 9, 4, 6, 8, 2, 7, 1, 3, 5}
	carry := 0
	for i := 0; i < len(digits); i++ {
		ch := digits[i]
		// assume digits are ASCII '0'..'9'
		n := int(ch - '0')
		// update carry
		idx := (carry + n) % 10
		carry = arrTable[idx]
	}
	// final check digit
	return (10 - carry) % 10
}
