// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package repo

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

	tuf_data "github.com/theupdateframework/go-tuf/data"

	repo_structs "go.fuchsia.dev/fuchsia/src/sys/pkg/lib/repo"
)

func TestConfigV2(t *testing.T) {
	repoDir := t.TempDir()

	repository, err := New(repoDir, t.TempDir())
	if err != nil {
		t.Fatal(err)
	}

	if err := repository.Init(); err != nil {
		t.Fatal(err)
	}

	if err := repository.AddTargets([]string{}, json.RawMessage{}); err != nil {
		t.Fatal(err)
	}

	if err := repository.CommitUpdates(false); err != nil {
		t.Fatal(err)
	}

	rootBytes, err := os.ReadFile(filepath.Join(repoDir, "repository", "root.json"))
	if err != nil {
		t.Fatal(err)
	}

	t.Run("parse config", func(t *testing.T) {
		var signed tuf_data.Signed
		var root tuf_data.Root
		if err := json.Unmarshal(rootBytes, &signed); err != nil {
			t.Fatal(err)
		}
		if err := json.Unmarshal(signed.Signed, &root); err != nil {
			t.Fatal(err)
		}

		server := NewConfigServer(func() []byte { return rootBytes }, false)
		config, err := server.parseConfig("http://localhost")
		if err != nil {
			t.Fatal(err)
		}

		if root.Version != int(config.RootVersion) {
			t.Fatalf("expected root version to be %v, not %v", root.Version, config.RootVersion)
		}

		rootRole, ok := root.Roles["root"]
		if !ok {
			t.Fatalf("root does not have root role")
		}

		if rootRole.Threshold != int(config.RootThreshold) {
			t.Fatalf("expected root version to be %v, not %v", root.Version, config.RootThreshold)
		}
	})

	t.Run("parse config with persistency flag set", func(t *testing.T) {
		var signed tuf_data.Signed
		var root tuf_data.Root
		if err := json.Unmarshal(rootBytes, &signed); err != nil {
			t.Fatal(err)
		}
		if err := json.Unmarshal(signed.Signed, &root); err != nil {
			t.Fatal(err)
		}

		server := NewConfigServer(func() []byte { return rootBytes }, true)
		config, err := server.parseConfig("http://localhost")
		if err != nil {
			t.Fatal(err)
		}

		if root.Version != int(config.RootVersion) {
			t.Fatalf("expected root version to be %v, not %v", root.Version, config.RootVersion)
		}

		rootRole, ok := root.Roles["root"]
		if !ok {
			t.Fatalf("root does not have root role")
		}

		if rootRole.Threshold != int(config.RootThreshold) {
			t.Fatalf("expected root version to be %v, not %v", root.Version, config.RootThreshold)
		}

		if config.StorageType != repo_structs.Persistent {
			t.Fatalf("expected storage type to be %v, not %v", repo_structs.Persistent, config.StorageType)
		}
	})

	t.Run("parse config errs with underflow root version", func(t *testing.T) {
		var signed tuf_data.Signed
		var root tuf_data.Root
		if err := json.Unmarshal(rootBytes, &signed); err != nil {
			t.Fatal(err)
		}
		if err := json.Unmarshal(signed.Signed, &root); err != nil {
			t.Fatal(err)
		}

		root.Version = -1
		signed.Signed, err = json.Marshal(root)
		if err != nil {
			t.Fatal(err)
		}
		badRootBytes, err := json.Marshal(signed)
		if err != nil {
			t.Fatal(err)
		}

		server := NewConfigServer(func() []byte { return badRootBytes }, false)
		if _, err := server.parseConfig("http://localhost"); !errors.Is(err, OutOfRangeError) {
			t.Fatalf("expected error to be out of range, not %v", err)
		}
	})

	t.Run("parse config errs with overflow root version", func(t *testing.T) {
		var signed tuf_data.Signed
		var root tuf_data.Root
		if err := json.Unmarshal(rootBytes, &signed); err != nil {
			t.Fatal(err)
		}
		if err := json.Unmarshal(signed.Signed, &root); err != nil {
			t.Fatal(err)
		}

		root.Version = math.MaxUint32 + 1
		signed.Signed, err = json.Marshal(root)
		if err != nil {
			t.Fatal(err)
		}
		badRootBytes, err := json.Marshal(signed)
		if err != nil {
			t.Fatal(err)
		}

		server := NewConfigServer(func() []byte { return badRootBytes }, false)
		if _, err := server.parseConfig("http://localhost"); !errors.Is(err, OutOfRangeError) {
			t.Fatalf("expected error to be out of range, not %v", err)
		}
	})

	t.Run("parse config errs with underflow root threshold", func(t *testing.T) {
		var signed tuf_data.Signed
		var root tuf_data.Root
		if err := json.Unmarshal(rootBytes, &signed); err != nil {
			t.Fatal(err)
		}
		if err := json.Unmarshal(signed.Signed, &root); err != nil {
			t.Fatal(err)
		}

		root.Roles["root"].Threshold = -1
		signed.Signed, err = json.Marshal(root)
		if err != nil {
			t.Fatal(err)
		}
		badRootBytes, err := json.Marshal(signed)
		if err != nil {
			t.Fatal(err)
		}

		server := NewConfigServer(func() []byte { return badRootBytes }, false)
		if _, err := server.parseConfig("http://localhost"); !errors.Is(err, OutOfRangeError) {
			t.Fatalf("expected error to be out of range, not %v", err)
		}
	})

	t.Run("parse config errs with overrflow root threshold", func(t *testing.T) {
		var signed tuf_data.Signed
		var root tuf_data.Root
		if err := json.Unmarshal(rootBytes, &signed); err != nil {
			t.Fatal(err)
		}
		if err := json.Unmarshal(signed.Signed, &root); err != nil {
			t.Fatal(err)
		}

		root.Roles["root"].Threshold = math.MaxUint32 + 1
		signed.Signed, err = json.Marshal(root)
		if err != nil {
			t.Fatal(err)
		}
		badRootBytes, err := json.Marshal(signed)
		if err != nil {
			t.Fatal(err)
		}

		server := NewConfigServer(func() []byte { return badRootBytes }, false)
		if _, err := server.parseConfig("http://localhost"); !errors.Is(err, OutOfRangeError) {
			t.Fatalf("expected error to be out of range, not %v", err)
		}
	})
}

func TestBuildRepoUrl(t *testing.T) {
	testCases := []struct {
		url  string
		want string
	}{
		{
			url:  "fuchsia-pkg://devhost",
			want: "fuchsia-pkg://devhost",
		},
		{
			url:  "fuchsia-pkg://DEVHOST",
			want: "fuchsia-pkg://devhost",
		},
		{
			url:  "http://fuchsia.com",
			want: "fuchsia-pkg://fuchsia.com",
		},
		{
			url:  "https://fuchsia.com/packages",
			want: "fuchsia-pkg://fuchsia.com-packages",
		},
	}

	for _, tc := range testCases {
		got := buildRepoUrl(tc.url)
		if got != tc.want {
			t.Errorf("buildRepoUrl(%v) returned %v, wanted %v", tc.url, got, tc.want)
		}
	}
}
