package platform

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

// MintDeviceSession sends the bootstrap token as Bearer + the device descriptor, and maps
// the response into the device-session result the desktop then rides.
func TestMintDeviceSession(t *testing.T) {
	var gotAuth string
	var gotBody map[string]string
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost || r.URL.Path != "/api/auth/device-session" {
			http.NotFound(w, r)
			return
		}
		gotAuth = r.Header.Get("Authorization")
		_ = json.NewDecoder(r.Body).Decode(&gotBody)
		_ = json.NewEncoder(w).Encode(map[string]any{
			"access_token": "acc-x", "refresh_token": "rtk-x", "expires_in": 900,
			"device_id": "dev_abc", "user_id": "sub-1", "name": "Commilitia",
			"avatar": "https://example.net/a.png",
		})
	}))
	defer srv.Close()

	res, err := MintDeviceSession(context.Background(), srv.URL, "boot-token", "dev_abc", "Mac", "macos")
	if err != nil {
		t.Fatalf("MintDeviceSession: %v", err)
	}
	if gotAuth != "Bearer boot-token" {
		t.Errorf("Authorization: got %q, want Bearer boot-token", gotAuth)
	}
	if gotBody["device_id"] != "dev_abc" || gotBody["device_name"] != "Mac" || gotBody["device_type"] != "macos" {
		t.Errorf("request body: %+v", gotBody)
	}
	if res.AccessToken != "acc-x" || res.RefreshToken != "rtk-x" || res.DeviceID != "dev_abc" ||
		res.UserID != "sub-1" || res.Name != "Commilitia" || res.ExpiresIn != 900 ||
		res.Avatar != "https://example.net/a.png" {
		t.Errorf("result: %+v", res)
	}
}

// A non-200 from the endpoint surfaces as an error rather than a half-built session.
func TestMintDeviceSession_ErrorStatus(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusBadGateway)
	}))
	defer srv.Close()
	if _, err := MintDeviceSession(context.Background(), srv.URL, "boot", "dev_abc", "Mac", "macos"); err == nil {
		t.Fatal("expected error on non-200, got nil")
	}
}

// ResolveDeviceID mints a validMeta-safe "dev_"-prefixed id and persists it (stable across
// calls). Uses an isolated config dir so it doesn't touch the real one.
func TestResolveDeviceID(t *testing.T) {
	// os.UserConfigDir honours XDG_CONFIG_HOME on Linux and HOME on macOS.
	dir := t.TempDir()
	t.Setenv("XDG_CONFIG_HOME", dir)
	t.Setenv("HOME", dir)
	id, err := ResolveDeviceID()
	if err != nil {
		t.Fatalf("ResolveDeviceID: %v", err)
	}
	if !strings.HasPrefix(id, "dev_") || len(id) < 8 {
		t.Errorf("device id format: %q", id)
	}
	again, err := ResolveDeviceID()
	if err != nil {
		t.Fatalf("ResolveDeviceID (2): %v", err)
	}
	if again != id {
		t.Errorf("device id not stable: %q != %q", again, id)
	}
}
