type Challenge struct {
	Nonce      string
	Difficulty int
	ExpiresAt  time.Time
	Used       bool
}

func GenerateNonce(size int) (string, error) {
	b := make([]byte, size)

	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}

	return base64.RawURLEncoding.EncodeToString(b), nil
}

func leadingZeroBits(b []byte) int {
	count := 0

	for _, by := range b {
		if by == 0 {
			count += 8
			continue
		}

		// count leading zeros in this byte
		for i := 7; i >= 0; i-- {
			if (by>>i)&1 == 0 {
				count++
			} else {
				return count
			}
		}
	}

	return count
}

func issuePOW(c fiber.Ctx) error {
	nonce, err := GenerateNonce(32)
	if err != nil {
		// handle error
	}
	return c.JSON(fiber.Map{
		"nonce":      nonce,
		"difficulty": 20, // bits
	})
}

// verify solution
func verifyPOW(nonce, solution string, difficulty int) bool {
	h := sha256.Sum256([]byte(nonce + solution))
	return leadingZeroBits(h[:]) >= difficulty
}

func pow404() {

}