package main

import (
	"context"
	"errors"
	"strings"
	"testing"
)

func TestBootstrapMirageBackendForGUIAlreadyReady(t *testing.T) {
	var waited bool
	err := bootstrapMirageBackendForGUI(context.Background(), guiBackendBootstrapDeps{
		ensureRunning: func() error { return nil },
		waitReady: func(context.Context) error {
			waited = true
			return nil
		},
		elevateInstall:    func() error { t.Fatal("unexpected elevateInstall call"); return nil },
		requiresElevation: func(error) bool { return false },
	})
	if err != nil {
		t.Fatalf("bootstrapMirageBackendForGUI() error = %v", err)
	}
	if !waited {
		t.Fatal("waitReady was not called")
	}
}

func TestBootstrapMirageBackendForGUIElevatesWhenNeeded(t *testing.T) {
	needElevationErr := errors.New("access denied")
	var elevated bool
	var waited bool
	err := bootstrapMirageBackendForGUI(context.Background(), guiBackendBootstrapDeps{
		ensureRunning: func() error { return needElevationErr },
		waitReady: func(context.Context) error {
			waited = true
			return nil
		},
		elevateInstall: func() error {
			elevated = true
			return nil
		},
		requiresElevation: func(err error) bool { return errors.Is(err, needElevationErr) },
	})
	if err != nil {
		t.Fatalf("bootstrapMirageBackendForGUI() error = %v", err)
	}
	if !elevated {
		t.Fatal("elevateInstall was not called")
	}
	if !waited {
		t.Fatal("waitReady was not called")
	}
}

func TestBootstrapMirageBackendForGUINonElevationError(t *testing.T) {
	wantErr := errors.New("backend broken")
	err := bootstrapMirageBackendForGUI(context.Background(), guiBackendBootstrapDeps{
		ensureRunning:     func() error { return wantErr },
		waitReady:         func(context.Context) error { t.Fatal("unexpected waitReady call"); return nil },
		elevateInstall:    func() error { t.Fatal("unexpected elevateInstall call"); return nil },
		requiresElevation: func(error) bool { return false },
	})
	if !errors.Is(err, wantErr) {
		t.Fatalf("bootstrapMirageBackendForGUI() error = %v, want wrapped %v", err, wantErr)
	}
	if !strings.Contains(err.Error(), "ensure mirage service running") {
		t.Fatalf("bootstrapMirageBackendForGUI() error = %q, want ensure wrapper", err)
	}
}

func TestBootstrapMirageBackendForGUIElevationFailure(t *testing.T) {
	needElevationErr := errors.New("access denied")
	wantErr := errors.New("uac canceled")
	err := bootstrapMirageBackendForGUI(context.Background(), guiBackendBootstrapDeps{
		ensureRunning: func() error { return needElevationErr },
		waitReady:     func(context.Context) error { t.Fatal("unexpected waitReady call"); return nil },
		elevateInstall: func() error {
			return wantErr
		},
		requiresElevation: func(err error) bool { return errors.Is(err, needElevationErr) },
	})
	if !errors.Is(err, wantErr) {
		t.Fatalf("bootstrapMirageBackendForGUI() error = %v, want wrapped %v", err, wantErr)
	}
	if !strings.Contains(err.Error(), "elevate mirage install") {
		t.Fatalf("bootstrapMirageBackendForGUI() error = %q, want elevate wrapper", err)
	}
}
