package main

import (
	"context"
	"log"

	"code.justin.tv/beefcake/server/internal/config"
	"code.justin.tv/beefcake/server/internal/legacyperm/legacypermiface"
	"code.justin.tv/beefcake/server/internal/role"
	"code.justin.tv/beefcake/server/internal/stringutil"
	"github.com/aws/aws-lambda-go/events"
)

type handler struct {
	Config            *config.Config
	LegacyPermissions legacypermiface.LegacyPermissionsAPI
}

func (h *handler) Handle(ctx context.Context, event events.DynamoDBEvent) error {
	for _, record := range event.Records {
		if err := h.handleRecord(ctx, record); err != nil {
			return err
		}
	}
	return nil
}

func (h *handler) handleRecord(ctx context.Context, record events.DynamoDBEventRecord) error {
	permsRemoved := h.perms(record.Change.OldImage)
	newPerms := h.perms(record.Change.NewImage)
	for perm := range newPerms {
		permsRemoved.Remove(perm)
	}

	if len(permsRemoved) > 0 {
		roleID := h.roleID(record.Change.OldImage)
		log.Printf("Removing role<%v> from permissions<%v>", roleID, permsRemoved)
		for perm := range permsRemoved {
			if err := h.LegacyPermissions.RemoveRole(ctx, perm, roleID); err != nil {
				return err
			}
		}
	}

	if len(newPerms) > 0 {
		roleID := h.roleID(record.Change.NewImage)
		log.Printf("Adding role<%v> to permissions<%v>", roleID, newPerms)
		for perm := range newPerms {
			roleName := h.roleName(record.Change.NewImage)
			if err := h.LegacyPermissions.AddRole(ctx, perm, roleID, roleName); err != nil {
				return err
			}
		}
	}

	return nil
}

func (h *handler) perms(av map[string]events.DynamoDBAttributeValue) stringutil.Set {
	raw, ok := av[role.LegacyPermissionsAttribute]
	if !ok {
		return stringutil.NewSet()
	}
	return stringutil.NewSet(raw.StringSet()...)
}

func (h *handler) roleID(av map[string]events.DynamoDBAttributeValue) string {
	return av[h.Config.RolesHashKey.Get()].String()
}

func (h *handler) roleName(av map[string]events.DynamoDBAttributeValue) string {
	return av[role.NameAttribute].String()
}
