package bmdb

import (
	"context"
	"fmt"
	"strings"
	"testing"
	"time"

	"github.com/google/uuid"
	"google.golang.org/protobuf/proto"

	apb "source.monogon.dev/cloud/agent/api"
	"source.monogon.dev/cloud/bmaas/bmdb/model"
	"source.monogon.dev/cloud/bmaas/bmdb/reflection"
	"source.monogon.dev/cloud/bmaas/server/api"
)

// TestReflection exercises the BMDB reflection schema reflection and data
// retrieval code. Ideally this code would live in //cloud/bmaas/bmdb/reflection,
// but due to namespacing issues it lives here.
func TestReflection(t *testing.T) {
	b := dut()
	conn, err := b.Open(true)
	if err != nil {
		t.Fatalf("Open failed: %v", err)
	}

	ctx, ctxC := context.WithCancel(context.Background())
	defer ctxC()

	sess, err := conn.StartSession(ctx)
	if err != nil {
		t.Fatalf("StartSession: %v", err)
	}

	// Create 10 test machines.
	var mids []uuid.UUID
	sess.Transact(ctx, func(q *model.Queries) error {
		for i := 0; i < 10; i += 1 {
			mach, err := q.NewMachine(ctx)
			if err != nil {
				return err
			}
			err = q.MachineAddProvided(ctx, model.MachineAddProvidedParams{
				MachineID:  mach.MachineID,
				Provider:   model.ProviderEquinix,
				ProviderID: fmt.Sprintf("test-%d", i),
			})
			if err != nil {
				return err
			}
			mids = append(mids, mach.MachineID)
		}
		return nil
	})
	if err != nil {
		t.Fatal(err)
	}
	// Start and fail work on one of the machines with an hour long backoff.
	w, err := sess.Work(ctx, model.ProcessUnitTest1, func(q *model.Queries) ([]uuid.UUID, error) {
		return mids[0:1], nil
	})
	if err != nil {
		t.Fatal(err)
	}
	to := time.Hour
	w.Fail(ctx, &to, "failure test")

	// On another machine, create a failure with a 1 second backoff.
	w, err = sess.Work(ctx, model.ProcessUnitTest1, func(q *model.Queries) ([]uuid.UUID, error) {
		return mids[1:2], nil
	})
	if err != nil {
		t.Fatal(err)
	}
	to = time.Second
	w.Fail(ctx, &to, "failure test")
	// Later on in the test we must wait for this backoff to actually elapse. Start
	// counting now.
	elapsed := time.NewTicker(to * 1)
	defer elapsed.Stop()

	// On another machine, create work and don't finish it yet.
	_, err = sess.Work(ctx, model.ProcessUnitTest1, func(q *model.Queries) ([]uuid.UUID, error) {
		return mids[2:3], nil
	})
	if err != nil {
		t.Fatal(err)
	}

	schema, err := conn.Reflect(ctx)
	if err != nil {
		t.Fatalf("ReflectTagTypes: %v", err)
	}

	// Dump all in strict mode.
	opts := &reflection.GetMachinesOpts{
		Strict: true,
	}
	res, err := schema.GetMachines(ctx, opts)
	if err != nil {
		t.Fatalf("Dump failed: %v", err)
	}
	if res.Query == "" {
		t.Errorf("Query not set on result")
	}
	machines := res.Data
	if want, got := 10, len(machines); want != got {
		t.Fatalf("Expected %d machines in dump, got %d", want, got)
	}

	// Expect Provided tag on all machines. Do a detailed check on fields, too.
	for _, machine := range machines {
		tag, ok := machine.Tags["Provided"]
		if !ok {
			t.Errorf("No Provided tag on machine.")
			continue
		}
		if want, got := "Provided", tag.Type.Name(); want != got {
			t.Errorf("Provided tag should have type %q, got %q", want, got)
		}
		if provider := tag.Field("provider"); provider != nil {
			if want, got := provider.HumanValue(), "Equinix"; want != got {
				t.Errorf("Wanted Provided.provider value %q, got %q", want, got)
			}
		} else {
			t.Errorf("Provider tag has no provider field")
		}
		if providerId := tag.Field("provider_id"); providerId != nil {
			if !strings.HasPrefix(providerId.HumanValue(), "test-") {
				t.Errorf("Unexpected provider_id value %q", providerId.HumanValue())
			}
		} else {
			t.Errorf("Provider tag has no provider_id field")
		}
	}

	// Now just dump one machine.
	opts.FilterMachine = &mids[0]
	res, err = schema.GetMachines(ctx, opts)
	if err != nil {
		t.Fatalf("Dump failed: %v", err)
	}
	machines = res.Data
	if want, got := 1, len(machines); want != got {
		t.Fatalf("Expected %d machines in dump, got %d", want, got)
	}
	if want, got := mids[0].String(), machines[0].ID.String(); want != got {
		t.Fatalf("Expected machine %s, got %s", want, got)
	}

	// Now dump a machine that doesn't exist. That should just return an empty list.
	fakeMid := uuid.New()
	opts.FilterMachine = &fakeMid
	res, err = schema.GetMachines(ctx, opts)
	if err != nil {
		t.Fatalf("Dump failed: %v", err)
	}
	machines = res.Data
	if want, got := 0, len(machines); want != got {
		t.Fatalf("Expected %d machines in dump, got %d", want, got)
	}

	// Finally, check the special case machines. The first one should have an active
	// backoff.
	opts.FilterMachine = &mids[0]
	res, err = schema.GetMachines(ctx, opts)
	if err != nil {
		t.Errorf("Dump failed: %v", err)
	} else {
		machine := res.Data[0]
		if _, ok := machine.Backoffs["UnitTest1"]; !ok {
			t.Errorf("Expected UnitTest1 backoff on machine")
		}
	}
	// The second one should have an expired backoff that shouldn't be reported in a
	// normal call..
	<-elapsed.C
	opts.FilterMachine = &mids[1]
	res, err = schema.GetMachines(ctx, opts)
	if err != nil {
		t.Errorf("Dump failed: %v", err)
	} else {
		machine := res.Data[0]
		if _, ok := machine.Backoffs["UnitTest1"]; ok {
			t.Errorf("Expected no UnitTest1 backoff on machine")
		}
	}
	// But if we ask for expired backoffs, we should get it.
	opts.ExpiredBackoffs = true
	res, err = schema.GetMachines(ctx, opts)
	if err != nil {
		t.Errorf("Dump failed: %v", err)
	} else {
		machine := res.Data[0]
		if _, ok := machine.Backoffs["UnitTest1"]; !ok {
			t.Errorf("Expected UnitTest1 backoff on machine")
		}
	}
	// Finally, the third machine should have an active Work item.
	opts.FilterMachine = &mids[2]
	res, err = schema.GetMachines(ctx, opts)
	if err != nil {
		t.Errorf("Dump failed: %v", err)
	} else {
		machine := res.Data[0]
		if _, ok := machine.Work["UnitTest1"]; !ok {
			t.Errorf("Expected UnitTest1 work item on machine")
		}
	}
}

// TestReflectionProtoFields ensures that the basic proto field introspection
// functionality works.
func TestReflectionProtoFields(t *testing.T) {
	s := dut()
	ctx, ctxC := context.WithCancel(context.Background())
	defer ctxC()

	bmdb, err := s.Open(true)
	if err != nil {
		t.Fatalf("Open: %v", err)
	}
	sess, err := bmdb.StartSession(ctx)
	if err != nil {
		t.Fatalf("StartSession: %v", err)
	}
	var machine model.Machine
	err = sess.Transact(ctx, func(q *model.Queries) error {
		machine, err = q.NewMachine(ctx)
		if err != nil {
			return err
		}

		report := &api.AgentHardwareReport{
			Report: &apb.Node{
				Manufacturer:         "Charles Babbage",
				Product:              "Analytical Engine",
				SerialNumber:         "183701",
				MemoryInstalledBytes: 14375,
				MemoryUsableRatio:    1.0,
				Cpu: []*apb.CPU{
					{
						Architecture:    nil,
						HardwareThreads: 1,
						Cores:           1,
					},
				},
			},
			Warning: []string{"something went wrong"},
		}
		b, _ := proto.Marshal(report)
		return q.MachineSetHardwareReport(ctx, model.MachineSetHardwareReportParams{
			MachineID:         machine.MachineID,
			HardwareReportRaw: b,
		})
	})
	if err != nil {
		t.Fatalf("Failed to submit hardware report: %v", err)
	}

	schem, err := bmdb.Reflect(ctx)
	if err != nil {
		t.Fatalf("Failed to reflect on database: %v", err)
	}

	machines, err := schem.GetMachines(ctx, &reflection.GetMachinesOpts{FilterMachine: &machine.MachineID, Strict: true})
	if err != nil {
		t.Fatalf("Failed to get machine: %v", err)
	}
	if len(machines.Data) != 1 {
		t.Errorf("Expected one machine, got %d", len(machines.Data))
	} else {
		machine := machines.Data[0]
		ty := machine.Tags["HardwareReport"].Field("hardware_report_raw").Type.HumanType()
		if want, got := "cloud.bmaas.server.api.AgentHardwareReport", ty; want != got {
			t.Errorf("Mismatch in type: wanted %q, got %q", want, got)
		}
		v := machine.Tags["HardwareReport"].Field("hardware_report_raw").HumanValue()
		if !strings.Contains(v, "manufacturer:") {
			t.Errorf("Invalid serialized prototext: %s", v)
		}
	}
}
