// Package handlers add by blacknc <blacknc@163.com> at 2024/05/20 15:56:26
package handlers

import (
	"context"
	"dataservices/commons/logger"
	"dataservices/internal/entity"
	"dataservices/internal/repository_ddb"
	service "dataservices/internal/service/common"
	ddbcacheworker "dataservices/worker/ddbcache"
	"fmt"

	"github.com/aws/aws-sdk-go-v2/feature/dynamodbstreams/attributevalue"
	"go.uber.org/zap"
)

func init() {
	ddbcacheworker.RegisterHandler(repository_ddb.EndpointsTable, DraftEndpointHandler)
	ddbcacheworker.RegisterHandler(repository_ddb.EndpointPublishTable, DeployedEndpointHandler)
}

func DraftEndpointHandler(ctx context.Context, event ddbcacheworker.Event, cacheManager service.CacheManager) error {

	record := event.Data
	var images [2]entity.Endpoint
	if err := attributevalue.UnmarshalMap(record.Dynamodb.OldImage, &images[0]); err != nil {
		return fmt.Errorf("failed to unmarshal draft endpoint event old record:%v", err)
	}
	if err := attributevalue.UnmarshalMap(record.Dynamodb.NewImage, &images[1]); err != nil {
		return fmt.Errorf("failed to unmarshal draft endpoint event new record:%v", err)
	}

	pathChanged := images[0].Method != images[1].Method || images[0].Endpoint != images[1].Endpoint
	for i := range images {
		method, path := images[i].Method, images[i].Endpoint
		dataappID, endpointID := images[i].DataappId, images[i].ID
		if dataappID == 0 || endpointID == 0 {
			continue
		}
		if err := cacheManager.ClearDraftEndpoint(ctx, dataappID, method, path); err != nil {
			logger.Error(ctx, "failed to clear draft endpoint cache",
				zap.Uint64("dataapp_id", dataappID), zap.Uint64("endpoint_id", endpointID),
				zap.String("method", method), zap.String("path", path), zap.Error(err))
		}
		if err := cacheManager.ClearDraftEndpointByID(ctx, dataappID, endpointID); err != nil {
			logger.Error(ctx, "failed to clear draft endpoint cache by id",
				zap.Uint64("dataapp_id", dataappID), zap.Uint64("endpoint_id", endpointID),
				zap.String("method", method), zap.String("path", path), zap.Error(err))
		}
		if pathChanged {
			if err := cacheManager.ClearDataappEndpointRouter(ctx, dataappID, "draft"); err != nil {
				logger.Error(ctx, "failed to clear dataapp draft endpoint router cache",
					zap.Uint64("dataapp_id", dataappID), zap.Uint64("endpoint_id", endpointID),
					zap.String("method", method), zap.String("path", path), zap.Error(err))
			}
		}
	}
	return nil
}

func DeployedEndpointHandler(ctx context.Context, event ddbcacheworker.Event, cacheManager service.CacheManager) error {

	record := event.Data
	var images [2]entity.EndpointPublish
	if err := attributevalue.UnmarshalMap(record.Dynamodb.OldImage, &images[0]); err != nil {
		return fmt.Errorf("failed to unmarshal deployed endpoint event old record:%v", err)
	}
	if err := attributevalue.UnmarshalMap(record.Dynamodb.NewImage, &images[1]); err != nil {
		return fmt.Errorf("failed to unmarshal deployed endpoint event new record:%v", err)
	}

	pathChanged := images[0].Method != images[1].Method || images[0].Endpoint != images[1].Endpoint
	for i := range images {
		method, path := images[i].Method, images[i].Endpoint
		dataappID, endpointID := images[i].DataappId, images[i].EndpointId
		if dataappID == 0 || endpointID == 0 {
			continue
		}
		if err := cacheManager.ClearDeployedEndpoint(ctx, dataappID, method, path); err != nil {
			logger.Error(ctx, "failed to clear deployed endpoint cache",
				zap.Uint64("dataapp_id", dataappID), zap.Uint64("endpoint_id", endpointID),
				zap.String("method", method), zap.String("path", path), zap.Error(err))
		}
		if pathChanged {
			if err := cacheManager.ClearDataappEndpointRouter(ctx, dataappID, "deployed"); err != nil {
				logger.Error(ctx, "failed to clear dataapp deployed endpoint router cache",
					zap.Uint64("dataapp_id", dataappID), zap.Uint64("endpoint_id", endpointID),
					zap.String("method", method), zap.String("path", path), zap.Error(err))
			}
		}
	}
	return nil
}
