package manager

import (
	"strconv"

	"code.justin.tv/common/ddbmetrics"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dynamodb"
)

// Delete deletes a secret
func (m *Manager) Delete(secretName string) error {

	// verify that secret exists, if not throw an error
	queryInput := m.inputForQueryGet(secretName)
	queryOutput, err := m.DynamoDB.Query(queryInput)

	if *queryOutput.Count == 0 {
		return nil
	}
	m.metrics.Report(ddbmetrics.Read, queryOutput.ConsumedCapacity)

	secret, err := unmarshalSecret(queryOutput.Items[0])
	if err != nil {
		return err
	}

	// insert tombstone
	tombstoneInput := m.inputForTombstoneUpdate(secretName, secret.UpdatedAt, true)
	tombstoneOutput, err := m.DynamoDB.UpdateItem(tombstoneInput)
	m.metrics.Report(ddbmetrics.Read, tombstoneOutput.ConsumedCapacity)

	if err != nil {
		return err
	}

	// delete from main table
	deleteInput := m.inputForItemDelete(secretName)
	deleteOutput, err := m.DynamoDB.DeleteItem(deleteInput)
	m.metrics.Report(ddbmetrics.Read, deleteOutput.ConsumedCapacity)

	if err != nil {
		return err
	}
	return nil
}

func (m *Manager) removeTombstone(secretName string, updatedAt int64) error {
	tombstoneInput := m.inputForTombstoneUpdate(secretName, updatedAt, false)
	_, err := m.DynamoDB.UpdateItem(tombstoneInput)
	return err
}

func (m *Manager) inputForItemDelete(name string) *dynamodb.DeleteItemInput {
	return &dynamodb.DeleteItemInput{
		Key: map[string]*dynamodb.AttributeValue{
			"name": {
				S: aws.String(name),
			},
		},
		ReturnConsumedCapacity: aws.String("INDEXES"),
		TableName:              aws.String(m.Config.TableName),
	}
}

func (m *Manager) inputForQueryGet(name string) *dynamodb.QueryInput {
	return &dynamodb.QueryInput{
		ConsistentRead: aws.Bool(true),
		ExpressionAttributeNames: map[string]*string{
			"#N": aws.String("name"),
		},
		ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
			":name": {
				S: aws.String(name),
			},
		},
		KeyConditionExpression: aws.String("#N = :name"),
		ReturnConsumedCapacity: aws.String("INDEXES"),
		TableName:              aws.String(m.TableName()),
	}
}

func (m *Manager) inputForTombstoneUpdate(name string, updatedAt int64, tombstone bool) *dynamodb.UpdateItemInput {
	return &dynamodb.UpdateItemInput{
		Key: map[string]*dynamodb.AttributeValue{
			"name":       &dynamodb.AttributeValue{S: aws.String(name)},
			"updated_at": &dynamodb.AttributeValue{N: aws.String(strconv.FormatInt(updatedAt, 10))},
		},
		ExpressionAttributeNames: map[string]*string{
			"#tombstone": aws.String("tombstone"),
		},
		ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
			":tombstone": &dynamodb.AttributeValue{BOOL: aws.Bool(tombstone)},
		},
		UpdateExpression:       aws.String("SET #tombstone = :tombstone"),
		ReturnConsumedCapacity: aws.String("INDEXES"),
		TableName:              aws.String(m.AuditTableName()),
	}
}
