package main

import (
	"fmt"
	"path"

	"code.justin.tv/eventbus/schema/cmd/internal/recon"
	"code.justin.tv/eventbus/schema/cmd/internal/util"
	"github.com/pkg/errors"

	"github.com/golang/protobuf/protoc-gen-go/descriptor"
)

var (
	whitelistedActions = map[string]bool{
		"Create":   true,
		"Delete":   true,
		"Destroy":  true,
		"Undelete": true,
		"Update":   true,
	}

	ignoredFilenames = map[string]bool{
		"google/protobuf/timestamp.proto":  true,
		"google/protobuf/descriptor.proto": true,
	}
)

func lintSchemaName(file *descriptor.FileDescriptorProto) error {
	filename := file.GetName()
	options := file.GetOptions()
	expectedName, expectedAction, err := util.ExpectedMessageName(filename)
	if err != nil {
		return errors.Wrapf(err, "invalid filename %q", filename)
	}

	expectedPkg := path.Base(path.Dir(filename))
	if protoPkg := file.GetPackage(); protoPkg != expectedPkg {
		return errors.Errorf("file %q's protobuf `package` statement should be %v, got %v", filename, expectedPkg, protoPkg)
	}

	if goPkg := options.GetGoPackage(); goPkg != expectedPkg {
		return errors.Errorf("file %q's `go_package` option should be %v, got %v", filename, expectedPkg, goPkg)
	}

	if ignoredFilenames[filename] {
		return nil
	}

	if !whitelistedActions[expectedAction] {
		return errors.Errorf("file %q's action must be one of 'Create, Delete, Destroy, Undelete, Update' but was %q", filename, expectedAction)
	}

	var found bool
	for _, message := range file.GetMessageType() {
		if message.GetName() == expectedName {
			found = true
			ldapGroup, err := recon.GetOwnerLDAPGroup(message)
			if err != nil {
				return errors.Wrapf(err, "could not determine LDAP group ownership for '%s'", message.GetName())
			} else if ldapGroup == "" {
				return fmt.Errorf("No LDAP group specified for event '%s'", message.GetName())
			}

			break
		}
	}

	if !found {
		return errors.Errorf("expected message %q not found in file %q", expectedName, filename)
	}

	return nil
}
