package main

import (
	"encoding/json"
	"fmt"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
	"os"
)

type Product struct {
	ID          string  `json:"id"`
	Name        string  `json:"name"`
	Description string  `json:"description"`
	Price       float64 `json:"price"`
}

var dynamoDB *dynamodb.DynamoDB

func init() {
	sess := session.Must(session.NewSession(&aws.Config{
		Region: aws.String(os.Getenv("AWS_REGION")),
	}))
	dynamoDB = dynamodb.New(sess)
}

func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	switch request.HTTPMethod {
	case "GET":
		return getProduct(request)
	case "POST":
		return createProduct(request)
	case "PUT":
		return updateProduct(request)
	case "DELETE":
		return deleteProduct(request)
	default:
		return events.APIGatewayProxyResponse{
			StatusCode: 400,
			Body:       "Invalid request method",
		}, nil
	}
}

func main() {
	lambda.Start(handler)
}

func getProduct(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	id := request.QueryStringParameters["id"]

	result, err := dynamoDB.GetItem(&dynamodb.GetItemInput{
		TableName: aws.String(os.Getenv("PRODUCTS_TABLE")),
		Key: map[string]*dynamodb.AttributeValue{
			"id": {
				S: aws.String(id),
			},
		},
	})

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to get product with ID %s", id),
		}, err
	}

	product := Product{}
	err = dynamodbattribute.UnmarshalMap(result.Item, &product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to unmarshal product with ID %s", id),
		}, err
	}

	response, err := json.Marshal(product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to marshal product with ID %s", id),
		}, err
	}

	return events.APIGatewayProxyResponse{
		StatusCode: 200,
		Body:       string(response),
	}, nil
}

func createProduct(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	var product Product

	err := json.Unmarshal([]byte(request.Body), &product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 400,
			Body:       "Invalid request body",
		}, err
	}

	item, err := dynamodbattribute.MarshalMap(product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to marshal product with ID %s", product.ID),
		}, err
	}

	_, err = dynamoDB.PutItem(&dynamodb.PutItemInput{
		TableName: aws.String(os.Getenv("PRODUCTS_TABLE")),
		Item:      item,
	})

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to create product with ID %s", product.ID),
		}, err
	}

	return events.APIGatewayProxyResponse{
		StatusCode: 201,
		Body:       fmt.Sprintf("Created product with ID %s", product.ID),
	}, nil
}

func updateProduct(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	var product Product

	err := json.Unmarshal([]byte(request.Body), &product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 400,
			Body:       "Invalid request body",
		}, err
	}

	expression := "SET name = :name, description = :description, price = :price"
	values := map[string]*dynamodb.AttributeValue{
		":name":        {S: aws.String(product.Name)},
		":description": {S: aws.String(product.Description)},
		":price":       {N: aws.String(fmt.Sprintf("%f", product.Price))},
	}

	_, err = dynamoDB.UpdateItem(&dynamodb.UpdateItemInput{
		TableName:                 aws.String(os.Getenv("PRODUCTS_TABLE")),
		Key:                       map[string]*dynamodb.AttributeValue{"id": {S: aws.String(product.ID)}},
		UpdateExpression:          aws.String(expression),
		ExpressionAttributeValues: values,
	})

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to update product with ID %s", product.ID),
		}, err
	}

	return events.APIGatewayProxyResponse{
		StatusCode: 200,
		Body:       fmt.Sprintf("Updated product with ID %s", product.ID),
	}, nil
}

func deleteProduct(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	id := request.QueryStringParameters["id"]

	_, err := dynamoDB.DeleteItem(&dynamodb.DeleteItemInput{
		TableName: aws.String(os.Getenv("PRODUCTS_TABLE")),
		Key: map[string]*dynamodb.AttributeValue{
			"id": {
				S: aws.String(id),
			},
		},
	})

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to delete product with ID %s", id),
		}, err
	}

	return events.APIGatewayProxyResponse{
		StatusCode: 200,
		Body:       fmt.Sprintf("Deleted product with ID %s", id),
	}, nil
}
package main

import (
	"encoding/json"
	"fmt"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
	"os"
)

type Product struct {
	ID          string  `json:"id"`
	Name        string  `json:"name"`
	Description string  `json:"description"`
	Price       float64 `json:"price"`
}

var dynamoDB *dynamodb.DynamoDB

func init() {
	sess := session.Must(session.NewSession(&aws.Config{
		Region: aws.String(os.Getenv("AWS_REGION")),
	}))
	dynamoDB = dynamodb.New(sess)
}

func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	switch request.HTTPMethod {
	case "GET":
		return getProduct(request)
	case "POST":
		return createProduct(request)
	case "PUT":
		return updateProduct(request)
	case "DELETE":
		return deleteProduct(request)
	default:
		return events.APIGatewayProxyResponse{
			StatusCode: 400,
			Body:       "Invalid request method",
		}, nil
	}
}

func main() {
	lambda.Start(handler)
}

func getProduct(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	id := request.QueryStringParameters["id"]

	result, err := dynamoDB.GetItem(&dynamodb.GetItemInput{
		TableName: aws.String(os.Getenv("PRODUCTS_TABLE")),
		Key: map[string]*dynamodb.AttributeValue{
			"id": {
				S: aws.String(id),
			},
		},
	})

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to get product with ID %s", id),
		}, err
	}

	product := Product{}
	err = dynamodbattribute.UnmarshalMap(result.Item, &product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to unmarshal product with ID %s", id),
		}, err
	}

	response, err := json.Marshal(product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to marshal product with ID %s", id),
		}, err
	}

	return events.APIGatewayProxyResponse{
		StatusCode: 200,
		Body:       string(response),
	}, nil
}

func createProduct(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	var product Product

	err := json.Unmarshal([]byte(request.Body), &product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 400,
			Body:       "Invalid request body",
		}, err
	}

	item, err := dynamodbattribute.MarshalMap(product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to marshal product with ID %s", product.ID),
		}, err
	}

	_, err = dynamoDB.PutItem(&dynamodb.PutItemInput{
		TableName: aws.String(os.Getenv("PRODUCTS_TABLE")),
		Item:      item,
	})

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to create product with ID %s", product.ID),
		}, err
	}

	return events.APIGatewayProxyResponse{
		StatusCode: 201,
		Body:       fmt.Sprintf("Created product with ID %s", product.ID),
	}, nil
}

func updateProduct(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	var product Product

	err := json.Unmarshal([]byte(request.Body), &product)

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 400,
			Body:       "Invalid request body",
		}, err
	}

	expression := "SET name = :name, description = :description, price = :price"
	values := map[string]*dynamodb.AttributeValue{
		":name":        {S: aws.String(product.Name)},
		":description": {S: aws.String(product.Description)},
		":price":       {N: aws.String(fmt.Sprintf("%f", product.Price))},
	}

	_, err = dynamoDB.UpdateItem(&dynamodb.UpdateItemInput{
		TableName:                 aws.String(os.Getenv("PRODUCTS_TABLE")),
		Key:                       map[string]*dynamodb.AttributeValue{"id": {S: aws.String(product.ID)}},
		UpdateExpression:          aws.String(expression),
		ExpressionAttributeValues: values,
	})

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to update product with ID %s", product.ID),
		}, err
	}

	return events.APIGatewayProxyResponse{
		StatusCode: 200,
		Body:       fmt.Sprintf("Updated product with ID %s", product.ID),
	}, nil
}

func deleteProduct(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	id := request.QueryStringParameters["id"]

	_, err := dynamoDB.DeleteItem(&dynamodb.DeleteItemInput{
		TableName: aws.String(os.Getenv("PRODUCTS_TABLE")),
		Key: map[string]*dynamodb.AttributeValue{
			"id": {
				S: aws.String(id),
			},
		},
	})

	if err != nil {
		return events.APIGatewayProxyResponse{
			StatusCode: 500,
			Body:       fmt.Sprintf("Failed to delete product with ID %s", id),
		}, err
	}

	return events.APIGatewayProxyResponse{
		StatusCode: 200,
		Body:       fmt.Sprintf("Deleted product with ID %s", id),
	}, nil
}