package hae_test

import (
	"encoding/json"
	"os"
	"path/filepath"
	"testing"

	"git.vakhrushev.me/av/healthlog/internal/hae"
)

func TestPointValueФормыТочки(t *testing.T) {
	t.Parallel()

	cases := []struct {
		name string
		raw  string
		want float64
		ok   bool
	}{
		{"обычная точка", `{"qty":72.5,"date":"2026-07-31 12:00:00 +0300"}`, 72.5, true},
		{"пульс без qty", `{"Min":60,"Avg":70.25,"Max":80}`, 70.25, true},
		{"qty впереди Avg", `{"qty":1,"Avg":9}`, 1, true},
		{"ноль — значение", `{"qty":0}`, 0, true},
		{"отрицательное значение", `{"qty":-1.5}`, -1.5, true},
		{"нет числовых полей", `{"date":"…","source":"часы"}`, 0, false},
		{"qty равен null", `{"qty":null,"Avg":3}`, 3, true},
		{"qty строкой", `{"qty":"72.5"}`, 0, false},
		{"qty объектом", `{"qty":{"value":1}}`, 0, false},
		{"переполнение float64", `{"qty":1e400}`, 0, false},
		{"точка не объект", `[1,2,3]`, 0, false},
		{"пустой объект", `{}`, 0, false},
	}

	for _, c := range cases {
		t.Run(c.name, func(t *testing.T) {
			t.Parallel()

			got, ok := hae.PointValue(json.RawMessage(c.raw))
			if ok != c.ok {
				t.Fatalf("наличие значения: получили %v, ждали %v", ok, c.ok)
			}
			if ok && got != c.want {
				t.Errorf("значение: получили %v, ждали %v", got, c.want)
			}
		})
	}
}

// Формы точки берутся из реальных пакетов: документация формата тонкая и
// местами расходится с тем, что приложение шлёт (docs/research/apple-health.md).
func TestPointValueНаРеальныхПакетах(t *testing.T) {
	t.Parallel()

	for _, name := range []string{"minute.json", "hour.json", "raw.json"} {
		t.Run(name, func(t *testing.T) {
			t.Parallel()

			body, err := os.ReadFile(filepath.Join("testdata", name))
			if err != nil {
				t.Fatalf("фикстура: %v", err)
			}
			var doc struct {
				Data struct {
					Metrics []struct {
						Name string            `json:"name"`
						Data []json.RawMessage `json:"data"`
					} `json:"metrics"`
				} `json:"data"`
			}
			if err := json.Unmarshal(body, &doc); err != nil {
				t.Fatalf("разбор фикстуры: %v", err)
			}

			total, valued := 0, 0
			for _, m := range doc.Data.Metrics {
				for _, raw := range m.Data {
					total++
					if _, ok := hae.PointValue(raw); ok {
						valued++
					}
				}
			}
			if total == 0 {
				t.Fatal("в фикстуре нет точек — проверять нечего")
			}
			// Утверждается свойство, а не число: корпус фикстур пополняется, и
			// константа протухла бы молча. Значение несёт подавляющее
			// большинство точек — если вдруг перестанет, это видно сразу.
			if valued*2 < total {
				t.Errorf("значение прочиталось лишь у %d точек из %d", valued, total)
			}
			t.Logf("точек %d, со значением %d", total, valued)
		})
	}
}
