package auditlog

import (
	"context"
	"fmt"
	"github.com/pingcap/tep/db/entity"
	"github.com/pingcap/tep/pkg/apis/apiserver"
	store "github.com/pingcap/tep/pkg/registry/apiserver"
	"github.com/pingcap/tep/pkg/utils"
	metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apiserver/pkg/endpoints/request"
)

type TiDBAuditLogStorage struct {
	store *store.Store
}

func NewStorage(store *store.Store) *TiDBAuditLogStorage {
	return &TiDBAuditLogStorage{
		store: store,
	}
}

func (s *TiDBAuditLogStorage) Kind() string {
	return "TiDBAuditLog"
}

func (s *TiDBAuditLogStorage) New() runtime.Object {
	return &apiserver.TiDBAuditLog{}
}

func (s *TiDBAuditLogStorage) NewList() runtime.Object {
	return &apiserver.TiDBAuditLogList{}
}

func (s *TiDBAuditLogStorage) NamespaceScoped() bool {
	return true
}

func (s *TiDBAuditLogStorage) NewExtraListOptions() runtime.Object {
	return &apiserver.TiDBAuditLogListOptions{}
}

func (s *TiDBAuditLogStorage) List(ctx context.Context, options *metainternalversion.ListOptions, extraOptions runtime.Object) (runtime.Object, error) {
	listOptions := extraOptions.(*apiserver.TiDBAuditLogListOptions)
	tidbClusterID := request.NamespaceValue(ctx)
	if listOptions.Format != "csv" {
		return s.ListAuditLog(TiDBAuditLogCxt{
			EventClass:     listOptions.EventClass,
			From:           utils.GetStartIndex(listOptions.Page, listOptions.ItemsPerPage),
			Size:           utils.GetSize(listOptions.ItemsPerPage),
			StartTimeInSec: listOptions.StartTimeInSec,
			EndTimeInSec:   listOptions.EndTimeInSec,
			TiDBClusterID:  tidbClusterID,
			Database:       listOptions.Database,
			Table:          listOptions.Table,
			User:           listOptions.User,
			OrderBy:        utils.GetSingleOrderByFieldName(listOptions.SortBy),
			Desc:           utils.GetSingleOrderByDirection(listOptions.SortBy),
		})
	}
	userID := ""
	if user, found := request.UserFrom(ctx); found {
		userID = user.GetUID()
	}
	utils.AddEventAndLogError(s.store.DB, &utils.Event{
		UserID:         userID,
		Payload:        fmt.Sprintf("download audit log of %s", tidbClusterID),
		ManagementType: entity.InstanceManagement,
		OperationType:  entity.OperateOperation,
	})
	return s.DownloadAuditLog(TiDBAuditLogCxt{
		EventClass:     listOptions.EventClass,
		From:           utils.GetStartIndex(listOptions.Page, listOptions.ItemsPerPage),
		Size:           utils.GetSize(listOptions.ItemsPerPage),
		StartTimeInSec: listOptions.StartTimeInSec,
		EndTimeInSec:   listOptions.EndTimeInSec,
		TiDBClusterID:  tidbClusterID,
		Database:       listOptions.Database,
		Table:          listOptions.Table,
		User:           listOptions.User,
		OrderBy:        utils.GetSingleOrderByFieldName(listOptions.SortBy),
		Desc:           utils.GetSingleOrderByDirection(listOptions.SortBy),
	})
}
