// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package cos

import (
	"bytes"
	"context"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	multierror "github.com/hashicorp/go-multierror"
	"github.com/hashicorp/terraform/internal/states/remote"
	"github.com/hashicorp/terraform/internal/states/statemgr"
	tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813"
	"github.com/tencentyun/cos-go-sdk-v5"
)

const (
	lockTagKey = "tencentcloud-terraform-lock"
)

// RemoteClient implements the client of remote state
type remoteClient struct {
	cosContext context.Context
	cosClient  *cos.Client
	tagClient  *tag.Client

	bucket    string
	stateFile string
	lockFile  string
	encrypt   bool
	acl       string
}

// Get returns remote state file
func (c *remoteClient) Get() (*remote.Payload, error) {
	log.Printf("[DEBUG] get remote state file %s", c.stateFile)

	exists, data, checksum, err := c.getObject(c.stateFile)
	if err != nil {
		return nil, err
	}

	if !exists {
		return nil, nil
	}

	payload := &remote.Payload{
		Data: data,
		MD5:  []byte(checksum),
	}

	return payload, nil
}

// Put put state file to remote
func (c *remoteClient) Put(data []byte) error {
	log.Printf("[DEBUG] put remote state file %s", c.stateFile)

	return c.putObject(c.stateFile, data)
}

// Delete delete remote state file
func (c *remoteClient) Delete() error {
	log.Printf("[DEBUG] delete remote state file %s", c.stateFile)

	return c.deleteObject(c.stateFile)
}

// Lock lock remote state file for writing
func (c *remoteClient) Lock(info *statemgr.LockInfo) (string, error) {
	log.Printf("[DEBUG] lock remote state file %s", c.lockFile)

	err := c.cosLock(c.bucket, c.lockFile)
	if err != nil {
		return "", c.lockError(err)
	}
	defer c.cosUnlock(c.bucket, c.lockFile)

	exists, _, _, err := c.getObject(c.lockFile)
	if err != nil {
		return "", c.lockError(err)
	}

	if exists {
		return "", c.lockError(fmt.Errorf("lock file %s exists", c.lockFile))
	}

	info.Path = c.lockFile
	data, err := json.Marshal(info)
	if err != nil {
		return "", c.lockError(err)
	}

	check := fmt.Sprintf("%x", md5.Sum(data))
	err = c.putObject(c.lockFile, data)
	if err != nil {
		return "", c.lockError(err)
	}

	return check, nil
}

// Unlock unlock remote state file
func (c *remoteClient) Unlock(check string) error {
	log.Printf("[DEBUG] unlock remote state file %s", c.lockFile)

	info, err := c.lockInfo()
	if err != nil {
		return c.lockError(err)
	}

	if info.ID != check {
		return c.lockError(fmt.Errorf("lock id mismatch, %v != %v", info.ID, check))
	}

	err = c.deleteObject(c.lockFile)
	if err != nil {
		return c.lockError(err)
	}

	err = c.cosUnlock(c.bucket, c.lockFile)
	if err != nil {
		return c.lockError(err)
	}

	return nil
}

// lockError returns statemgr.LockError
func (c *remoteClient) lockError(err error) *statemgr.LockError {
	log.Printf("[DEBUG] failed to lock or unlock %s: %v", c.lockFile, err)

	lockErr := &statemgr.LockError{
		Err: err,
	}

	info, infoErr := c.lockInfo()
	if infoErr != nil {
		lockErr.Err = multierror.Append(lockErr.Err, infoErr)
	} else {
		lockErr.Info = info
	}

	return lockErr
}

// lockInfo returns LockInfo from lock file
func (c *remoteClient) lockInfo() (*statemgr.LockInfo, error) {
	exists, data, checksum, err := c.getObject(c.lockFile)
	if err != nil {
		return nil, err
	}

	if !exists {
		return nil, fmt.Errorf("lock file %s not exists", c.lockFile)
	}

	info := &statemgr.LockInfo{}
	if err := json.Unmarshal(data, info); err != nil {
		return nil, err
	}

	info.ID = checksum

	return info, nil
}

// getObject get remote object
func (c *remoteClient) getObject(cosFile string) (exists bool, data []byte, checksum string, err error) {
	rsp, err := c.cosClient.Object.Get(c.cosContext, cosFile, nil)
	if rsp == nil {
		log.Printf("[DEBUG] getObject %s: error: %v", cosFile, err)
		err = fmt.Errorf("failed to open file at %v: %v", cosFile, err)
		return
	}
	defer rsp.Body.Close()

	log.Printf("[DEBUG] getObject %s: code: %d, error: %v", cosFile, rsp.StatusCode, err)
	if err != nil {
		if rsp.StatusCode == 404 {
			err = nil
		} else {
			err = fmt.Errorf("failed to open file at %v: %v", cosFile, err)
		}
		return
	}

	checksum = rsp.Header.Get("X-Cos-Meta-Md5")
	log.Printf("[DEBUG] getObject %s: checksum: %s", cosFile, checksum)
	if len(checksum) != 32 {
		err = fmt.Errorf("failed to open file at %v: checksum %s invalid", cosFile, checksum)
		return
	}

	exists = true
	data, err = ioutil.ReadAll(rsp.Body)
	log.Printf("[DEBUG] getObject %s: data length: %d", cosFile, len(data))
	if err != nil {
		err = fmt.Errorf("failed to open file at %v: %v", cosFile, err)
		return
	}

	check := fmt.Sprintf("%x", md5.Sum(data))
	log.Printf("[DEBUG] getObject %s: check: %s", cosFile, check)
	if check != checksum {
		err = fmt.Errorf("failed to open file at %v: checksum mismatch, %s != %s", cosFile, check, checksum)
		return
	}

	return
}

// putObject put object to remote
func (c *remoteClient) putObject(cosFile string, data []byte) error {
	opt := &cos.ObjectPutOptions{
		ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{
			XCosMetaXXX: &http.Header{
				"X-Cos-Meta-Md5": []string{fmt.Sprintf("%x", md5.Sum(data))},
			},
		},
		ACLHeaderOptions: &cos.ACLHeaderOptions{
			XCosACL: c.acl,
		},
	}

	if c.encrypt {
		opt.ObjectPutHeaderOptions.XCosServerSideEncryption = "AES256"
	}

	r := bytes.NewReader(data)
	rsp, err := c.cosClient.Object.Put(c.cosContext, cosFile, r, opt)
	if rsp == nil {
		log.Printf("[DEBUG] putObject %s: error: %v", cosFile, err)
		return fmt.Errorf("failed to save file to %v: %v", cosFile, err)
	}
	defer rsp.Body.Close()

	log.Printf("[DEBUG] putObject %s: code: %d, error: %v", cosFile, rsp.StatusCode, err)
	if err != nil {
		return fmt.Errorf("failed to save file to %v: %v", cosFile, err)
	}

	return nil
}

// deleteObject delete remote object
func (c *remoteClient) deleteObject(cosFile string) error {
	rsp, err := c.cosClient.Object.Delete(c.cosContext, cosFile)
	if rsp == nil {
		log.Printf("[DEBUG] deleteObject %s: error: %v", cosFile, err)
		return fmt.Errorf("failed to delete file %v: %v", cosFile, err)
	}
	defer rsp.Body.Close()

	log.Printf("[DEBUG] deleteObject %s: code: %d, error: %v", cosFile, rsp.StatusCode, err)
	if rsp.StatusCode == 404 {
		return nil
	}

	if err != nil {
		return fmt.Errorf("failed to delete file %v: %v", cosFile, err)
	}

	return nil
}

// getBucket list bucket by prefix
func (c *remoteClient) getBucket(prefix string) (obs []cos.Object, err error) {
	fs, rsp, err := c.cosClient.Bucket.Get(c.cosContext, &cos.BucketGetOptions{Prefix: prefix})
	if rsp == nil {
		log.Printf("[DEBUG] getBucket %s/%s: error: %v", c.bucket, prefix, err)
		err = fmt.Errorf("bucket %s not exists", c.bucket)
		return
	}
	defer rsp.Body.Close()

	log.Printf("[DEBUG] getBucket %s/%s: code: %d, error: %v", c.bucket, prefix, rsp.StatusCode, err)
	if rsp.StatusCode == 404 {
		err = fmt.Errorf("bucket %s not exists", c.bucket)
		return
	}

	if err != nil {
		return
	}

	return fs.Contents, nil
}

// putBucket create cos bucket
func (c *remoteClient) putBucket() error {
	rsp, err := c.cosClient.Bucket.Put(c.cosContext, nil)
	if rsp == nil {
		log.Printf("[DEBUG] putBucket %s: error: %v", c.bucket, err)
		return fmt.Errorf("failed to create bucket %v: %v", c.bucket, err)
	}
	defer rsp.Body.Close()

	log.Printf("[DEBUG] putBucket %s: code: %d, error: %v", c.bucket, rsp.StatusCode, err)
	if rsp.StatusCode == 409 {
		return nil
	}

	if err != nil {
		return fmt.Errorf("failed to create bucket %v: %v", c.bucket, err)
	}

	return nil
}

// deleteBucket delete cos bucket
func (c *remoteClient) deleteBucket(recursive bool) error {
	if recursive {
		obs, err := c.getBucket("")
		if err != nil {
			if strings.Contains(err.Error(), "not exists") {
				return nil
			}
			log.Printf("[DEBUG] deleteBucket %s: empty bucket error: %v", c.bucket, err)
			return fmt.Errorf("failed to empty bucket %v: %v", c.bucket, err)
		}
		for _, v := range obs {
			c.deleteObject(v.Key)
		}
	}

	rsp, err := c.cosClient.Bucket.Delete(c.cosContext)
	if rsp == nil {
		log.Printf("[DEBUG] deleteBucket %s: error: %v", c.bucket, err)
		return fmt.Errorf("failed to delete bucket %v: %v", c.bucket, err)
	}
	defer rsp.Body.Close()

	log.Printf("[DEBUG] deleteBucket %s: code: %d, error: %v", c.bucket, rsp.StatusCode, err)
	if rsp.StatusCode == 404 {
		return nil
	}

	if err != nil {
		return fmt.Errorf("failed to delete bucket %v: %v", c.bucket, err)
	}

	return nil
}

// cosLock lock cos for writing
func (c *remoteClient) cosLock(bucket, cosFile string) error {
	log.Printf("[DEBUG] lock cos file %s:%s", bucket, cosFile)

	cosPath := fmt.Sprintf("%s:%s", bucket, cosFile)
	lockTagValue := fmt.Sprintf("%x", md5.Sum([]byte(cosPath)))

	return c.CreateTag(lockTagKey, lockTagValue)
}

// cosUnlock unlock cos writing
func (c *remoteClient) cosUnlock(bucket, cosFile string) error {
	log.Printf("[DEBUG] unlock cos file %s:%s", bucket, cosFile)

	cosPath := fmt.Sprintf("%s:%s", bucket, cosFile)
	lockTagValue := fmt.Sprintf("%x", md5.Sum([]byte(cosPath)))

	var err error
	for i := 0; i < 30; i++ {
		tagExists, err := c.CheckTag(lockTagKey, lockTagValue)

		if err != nil {
			return err
		}

		if !tagExists {
			return nil
		}

		err = c.DeleteTag(lockTagKey, lockTagValue)
		if err == nil {
			return nil
		}
		time.Sleep(1 * time.Second)
	}

	return err
}

// CheckTag checks if tag key:value exists
func (c *remoteClient) CheckTag(key, value string) (exists bool, err error) {
	request := tag.NewDescribeTagsRequest()
	request.TagKey = &key
	request.TagValue = &value

	response, err := c.tagClient.DescribeTags(request)
	log.Printf("[DEBUG] create tag %s:%s: error: %v", key, value, err)
	if err != nil {
		return
	}

	if len(response.Response.Tags) == 0 {
		return
	}

	tagKey := response.Response.Tags[0].TagKey
	tagValue := response.Response.Tags[0].TagValue

	exists = key == *tagKey && value == *tagValue

	return
}

// CreateTag create tag by key and value
func (c *remoteClient) CreateTag(key, value string) error {
	request := tag.NewCreateTagRequest()
	request.TagKey = &key
	request.TagValue = &value

	_, err := c.tagClient.CreateTag(request)
	log.Printf("[DEBUG] create tag %s:%s: error: %v", key, value, err)
	if err != nil {
		return fmt.Errorf("failed to create tag: %s -> %s: %s", key, value, err)
	}

	return nil
}

// DeleteTag create tag by key and value
func (c *remoteClient) DeleteTag(key, value string) error {
	request := tag.NewDeleteTagRequest()
	request.TagKey = &key
	request.TagValue = &value

	_, err := c.tagClient.DeleteTag(request)
	log.Printf("[DEBUG] delete tag %s:%s: error: %v", key, value, err)
	if err != nil {
		return fmt.Errorf("failed to delete tag: %s -> %s: %s", key, value, err)
	}

	return nil
}
