package utils

import (
	"fmt"
	"log"
	"math/big"
	"strconv"
	"strings"

	"github.com/shopspring/decimal"
)

var NumberNames = map[int]string{
	1:  "тыс.",
	2:  "млн.",
	3:  "млрд.",
	4:  "трлн.",
	5:  "квадрлн.",
	6:  "квинтлн.",
	7:  "секстлн.",
	8:  "септлн.",
	9:  "октлн.",
	10: "нонилн.",
	11: "децилн.",
	12: "ундецилн.",
	13: "дуодецилн.",
}

func Short(n string) string {
	d, err := decimal.NewFromString(n)
	if err != nil {
		log.Fatalln(err)
	}
	comma := DecimalComma(&d)
	sp := strings.Split(comma, "'")
	if len(sp) == 0 {
		return ""
	}
	return fmt.Sprintf("(%s %s)", sp[0], NumberNames[len(sp)-1])
}

// order of magnitude (to a max order)
func oomm(n, b *big.Int, maxmag int) (float64, int) {
	mag := 0
	m := &big.Int{}
	for n.Cmp(b) >= 0 {
		n.DivMod(n, b, m)
		mag++
		if mag == maxmag && maxmag >= 0 {
			break
		}
	}
	return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
}

// total order of magnitude
// (same as above, but with no upper limit)
func oom(n, b *big.Int) (float64, int) {
	mag := 0
	m := &big.Int{}
	for n.Cmp(b) >= 0 {
		n.DivMod(n, b, m)
		mag++
	}
	return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
}

func BigComma(b *big.Int) string {
	sign := ""
	if b.Sign() < 0 {
		sign = "-"
		b.Abs(b)
	}

	athousand := big.NewInt(1000)
	c := (&big.Int{}).Set(b)
	_, m := oom(c, athousand)
	parts := make([]string, m+1)
	j := len(parts) - 1

	mod := &big.Int{}
	for b.Cmp(athousand) >= 0 {
		b.DivMod(b, athousand, mod)
		parts[j] = strconv.FormatInt(mod.Int64(), 10)
		switch len(parts[j]) {
		case 2:
			parts[j] = "0" + parts[j]
		case 1:
			parts[j] = "00" + parts[j]
		}
		j--
	}
	parts[j] = strconv.Itoa(int(b.Int64()))
	return sign + strings.Join(parts[j:], "'")
}

func DecimalComma(d *decimal.Decimal) string {
	if d.IsInteger() {
		return BigComma(d.BigInt())
	}
	fmt.Println(d.String())
	exp := strings.Split(d.String(), ".")[1]
	return BigComma(d.BigInt()) + "." + exp
}
