package manta

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"path"

	uuid "github.com/hashicorp/go-uuid"
	"github.com/hashicorp/terraform/internal/states/remote"
	"github.com/hashicorp/terraform/internal/states/statemgr"
	tritonErrors "github.com/joyent/triton-go/errors"
	"github.com/joyent/triton-go/storage"
)

const (
	mantaDefaultRootStore = "/stor"
	lockFileName          = "tflock"
)

type RemoteClient struct {
	storageClient *storage.StorageClient
	directoryName string
	keyName       string
	statePath     string
}

func (c *RemoteClient) Get() (*remote.Payload, error) {
	output, err := c.storageClient.Objects().Get(context.Background(), &storage.GetObjectInput{
		ObjectPath: path.Join(mantaDefaultRootStore, c.directoryName, c.keyName),
	})
	if err != nil {
		if tritonErrors.IsResourceNotFound(err) {
			return nil, nil
		}
		return nil, err
	}
	defer output.ObjectReader.Close()

	buf := bytes.NewBuffer(nil)
	if _, err := io.Copy(buf, output.ObjectReader); err != nil {
		return nil, fmt.Errorf("Failed to read remote state: %s", err)
	}

	payload := &remote.Payload{
		Data: buf.Bytes(),
	}

	// If there was no data, then return nil
	if len(payload.Data) == 0 {
		return nil, nil
	}

	return payload, nil

}

func (c *RemoteClient) Put(data []byte) error {
	contentType := "application/json"
	contentLength := int64(len(data))

	params := &storage.PutObjectInput{
		ContentType:   contentType,
		ContentLength: uint64(contentLength),
		ObjectPath:    path.Join(mantaDefaultRootStore, c.directoryName, c.keyName),
		ObjectReader:  bytes.NewReader(data),
	}

	log.Printf("[DEBUG] Uploading remote state to Manta: %#v", params)
	err := c.storageClient.Objects().Put(context.Background(), params)
	if err != nil {
		return err
	}

	return nil
}

func (c *RemoteClient) Delete() error {
	err := c.storageClient.Objects().Delete(context.Background(), &storage.DeleteObjectInput{
		ObjectPath: path.Join(mantaDefaultRootStore, c.directoryName, c.keyName),
	})

	return err
}

func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
	//At Joyent, we want to make sure that the State directory exists before we interact with it
	//We don't expect users to have to create it in advance
	//The order of operations of Backend State as follows:
	// * Get - if this doesn't exist then we continue as though it's new
	// * Lock - we make sure that the state directory exists as it's the entrance to writing to Manta
	// * Put - put the state up there
	// * Unlock - unlock the directory
	//We can always guarantee that the user can put their state in the specified location because of this
	err := c.storageClient.Dir().Put(context.Background(), &storage.PutDirectoryInput{
		DirectoryName: path.Join(mantaDefaultRootStore, c.directoryName),
	})
	if err != nil {
		return "", err
	}

	//firstly we want to check that a lock doesn't already exist
	lockErr := &statemgr.LockError{}
	lockInfo, err := c.getLockInfo()
	if err != nil {
		if !tritonErrors.IsResourceNotFound(err) {
			lockErr.Err = fmt.Errorf("failed to retrieve lock info: %s", err)
			return "", lockErr
		}
	}

	if lockInfo != nil {
		lockErr := &statemgr.LockError{
			Err:  fmt.Errorf("A lock is already acquired"),
			Info: lockInfo,
		}
		return "", lockErr
	}

	info.Path = path.Join(c.directoryName, lockFileName)

	if info.ID == "" {
		lockID, err := uuid.GenerateUUID()
		if err != nil {
			return "", err
		}

		info.ID = lockID
	}

	data := info.Marshal()

	contentType := "application/json"
	contentLength := int64(len(data))

	params := &storage.PutObjectInput{
		ContentType:   contentType,
		ContentLength: uint64(contentLength),
		ObjectPath:    path.Join(mantaDefaultRootStore, c.directoryName, lockFileName),
		ObjectReader:  bytes.NewReader(data),
		ForceInsert:   true,
	}

	log.Printf("[DEBUG] Creating manta state lock: %#v", params)
	err = c.storageClient.Objects().Put(context.Background(), params)
	if err != nil {
		return "", err
	}

	return info.ID, nil
}

func (c *RemoteClient) Unlock(id string) error {
	lockErr := &statemgr.LockError{}

	lockInfo, err := c.getLockInfo()
	if err != nil {
		lockErr.Err = fmt.Errorf("failed to retrieve lock info: %s", err)
		return lockErr
	}
	lockErr.Info = lockInfo

	if lockInfo.ID != id {
		lockErr.Err = fmt.Errorf("lock id %q does not match existing lock", id)
		return lockErr
	}

	err = c.storageClient.Objects().Delete(context.Background(), &storage.DeleteObjectInput{
		ObjectPath: path.Join(mantaDefaultRootStore, c.directoryName, lockFileName),
	})

	return err
}

func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
	output, err := c.storageClient.Objects().Get(context.Background(), &storage.GetObjectInput{
		ObjectPath: path.Join(mantaDefaultRootStore, c.directoryName, lockFileName),
	})
	if err != nil {
		return nil, err
	}

	defer output.ObjectReader.Close()

	buf := bytes.NewBuffer(nil)
	if _, err := io.Copy(buf, output.ObjectReader); err != nil {
		return nil, fmt.Errorf("Failed to read lock info: %s", err)
	}

	lockInfo := &statemgr.LockInfo{}
	err = json.Unmarshal(buf.Bytes(), lockInfo)
	if err != nil {
		return nil, err
	}

	return lockInfo, nil
}
