package platform

import "testing"

func TestInferLiveBootKind(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name       string
		fsType     string
		source     string
		deviceType string
		transport  string
		want       string
	}{
		{name: "ram tmpfs", fsType: "tmpfs", source: "/dev/shm/bee-live", want: "ram"},
		{name: "usb disk", source: "/dev/sdb1", deviceType: "disk", transport: "usb", want: "usb"},
		{name: "cdrom rom", source: "/dev/sr0", deviceType: "rom", want: "cdrom"},
		{name: "disk sata", source: "/dev/nvme0n1p1", deviceType: "disk", transport: "nvme", want: "disk"},
		{name: "unknown", source: "overlay", want: "unknown"},
	}
	for _, tc := range tests {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			got := inferLiveBootKind(tc.fsType, tc.source, tc.deviceType, tc.transport)
			if got != tc.want {
				t.Fatalf("inferLiveBootKind(%q,%q,%q,%q)=%q want %q", tc.fsType, tc.source, tc.deviceType, tc.transport, got, tc.want)
			}
		})
	}
}

func TestVerifyInstallToRAMStatus(t *testing.T) {
	t.Parallel()

	dstDir := t.TempDir()

	if err := verifyInstallToRAMStatus(LiveBootSource{InRAM: true, Kind: "ram", Source: "tmpfs"}, dstDir, false, nil); err != nil {
		t.Fatalf("expected success for RAM-backed status, got %v", err)
	}

	err := verifyInstallToRAMStatus(LiveBootSource{InRAM: false, Kind: "usb", Device: "/dev/sdb1"}, dstDir, false, nil)
	if err == nil {
		t.Fatal("expected verification failure when media is still on USB")
	}
	if got := err.Error(); got != "install to RAM verification failed: live medium still mounted from USB (/dev/sdb1) and no squashfs found in "+dstDir {
		t.Fatalf("error=%q", got)
	}
}

func TestDescribeLiveBootSource(t *testing.T) {
	t.Parallel()

	if got := describeLiveBootSource(LiveBootSource{InRAM: true, Kind: "ram"}); got != "RAM" {
		t.Fatalf("got %q want RAM", got)
	}
	if got := describeLiveBootSource(LiveBootSource{Kind: "unknown", Source: "/run/live/medium"}); got != "/run/live/medium" {
		t.Fatalf("got %q want /run/live/medium", got)
	}
}

func TestEvaluateLiveMediaRAMState(t *testing.T) {
	t.Parallel()

	t.Run("in_ram", func(t *testing.T) {
		state := evaluateLiveMediaRAMState(
			LiveBootSource{InRAM: true, Kind: "ram", Source: "tmpfs"},
			false,
			nil,
			nil,
		)
		if state.State != "in_ram" || state.Status != "ok" || state.CanStartCopy {
			t.Fatalf("state=%+v", state)
		}
	})

	t.Run("partial_copy_after_cancel", func(t *testing.T) {
		state := evaluateLiveMediaRAMState(
			LiveBootSource{InRAM: false, Kind: "usb", Device: "/dev/sdb1"},
			false,
			[]string{"/run/live/medium/live/filesystem.squashfs", "/run/live/medium/live/firmware.squashfs"},
			[]string{"/dev/shm/bee-live/filesystem.squashfs"},
		)
		if state.State != "partial" || state.Status != "partial" || !state.CanStartCopy {
			t.Fatalf("state=%+v", state)
		}
		if state.CopyComplete {
			t.Fatalf("CopyComplete=%v want false", state.CopyComplete)
		}
	})

	t.Run("toram_failed", func(t *testing.T) {
		state := evaluateLiveMediaRAMState(
			LiveBootSource{InRAM: false, Kind: "usb", Device: "/dev/sdb1"},
			true,
			nil,
			nil,
		)
		if state.State != "toram_failed" || state.Status != "failed" || !state.CanStartCopy {
			t.Fatalf("state=%+v", state)
		}
	})
}
