// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package pluginshared

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"

	"github.com/hashicorp/go-getter"
	svchost "github.com/hashicorp/terraform-svchost"
	"github.com/hashicorp/terraform/internal/releaseauth"
)

// BinaryManager downloads, caches, and returns information about the
// plugin binary downloaded from the specified backend.
type BinaryManager struct {
	signingKey    string
	binaryName    string
	pluginName    string
	pluginDataDir string
	overridePath  string
	host          svchost.Hostname
	client        *BasePluginClient
	goos          string
	arch          string
	ctx           context.Context
}

// Binary is a struct containing the path to an authenticated binary corresponding to
// a backend service.
type Binary struct {
	Path                    string
	ProductVersion          string
	ResolvedFromCache       bool
	ResolvedFromDevOverride bool
}

const (
	KB = 1000
	MB = 1000 * KB
)

func (v BinaryManager) binaryLocation() string {
	return path.Join(v.pluginDataDir, "bin", fmt.Sprintf("%s_%s", v.goos, v.arch))
}

func (v BinaryManager) cachedVersion(version string) *string {
	binaryPath := path.Join(v.binaryLocation(), v.binaryName)

	if _, err := os.Stat(binaryPath); err != nil {
		return nil
	}

	// The version from the manifest must match the contents of ".version"
	versionData, err := os.ReadFile(path.Join(v.binaryLocation(), ".version"))
	if err != nil || strings.Trim(string(versionData), " \n\r\t") != version {
		return nil
	}

	return &binaryPath
}

// Resolve fetches, authenticates, and caches a plugin binary matching the specifications
// and returns its location and version.
func (v BinaryManager) Resolve() (*Binary, error) {
	if v.overridePath != "" {
		log.Printf("[TRACE] Using dev override for %s binary", v.pluginName)
		return v.resolveDev()
	}
	return v.resolveRelease()
}

func (v BinaryManager) resolveDev() (*Binary, error) {
	return &Binary{
		Path:                    v.overridePath,
		ProductVersion:          "dev",
		ResolvedFromDevOverride: true,
	}, nil
}

func (v BinaryManager) resolveRelease() (*Binary, error) {
	manifest, err := v.latestManifest(v.ctx)
	if err != nil {
		return nil, fmt.Errorf("could not resolve %s version for host %q: %w", v.pluginName, v.host.ForDisplay(), err)
	}

	buildInfo, err := manifest.Select(v.pluginName, v.goos, v.arch)
	if err != nil {
		return nil, err
	}

	// Check if there's a cached binary
	if cachedBinary := v.cachedVersion(manifest.Version); cachedBinary != nil {
		return &Binary{
			Path:              *cachedBinary,
			ProductVersion:    manifest.Version,
			ResolvedFromCache: true,
		}, nil
	}

	// Download the archive
	t, err := os.CreateTemp(os.TempDir(), v.binaryName)
	if err != nil {
		return nil, fmt.Errorf("failed to create temp file for download: %w", err)
	}
	defer os.Remove(t.Name())

	err = v.client.DownloadFile(buildInfo.URL, t)
	if err != nil {
		return nil, err
	}
	t.Close() // Close only returns an error if it's already been called

	// Authenticate the archive
	err = v.verifyPlugin(manifest, buildInfo, t.Name())
	if err != nil {
		return nil, fmt.Errorf("could not resolve %s version %q: %w", v.pluginName, manifest.Version, err)
	}

	// Unarchive
	unzip := getter.ZipDecompressor{
		FilesLimit:    3, // plugin binary, .version file, and LICENSE.txt
		FileSizeLimit: 500 * MB,
	}
	targetPath := v.binaryLocation()
	log.Printf("[TRACE] decompressing %q to %q", t.Name(), targetPath)

	err = unzip.Decompress(targetPath, t.Name(), true, 0000)
	if err != nil {
		return nil, fmt.Errorf("failed to decompress %s: %w", v.pluginName, err)
	}

	err = os.WriteFile(path.Join(targetPath, ".version"), []byte(manifest.Version), 0644)
	if err != nil {
		log.Printf("[ERROR] failed to write .version file to %q: %s", targetPath, err)
	}

	return &Binary{
		Path:              path.Join(targetPath, v.binaryName),
		ProductVersion:    manifest.Version,
		ResolvedFromCache: false,
	}, nil
}

// Useful for small files that can be decoded all at once
func (v BinaryManager) downloadFileBuffer(pathOrURL string) ([]byte, error) {
	buffer := bytes.Buffer{}
	err := v.client.DownloadFile(pathOrURL, &buffer)
	if err != nil {
		return nil, err
	}

	return buffer.Bytes(), err
}

// verifyPlugin authenticates the downloaded release archive
func (v BinaryManager) verifyPlugin(archiveManifest *Release, info *BuildArtifact, archiveLocation string) error {
	signature, err := v.downloadFileBuffer(archiveManifest.URLSHASumsSignatures[0])
	if err != nil {
		return fmt.Errorf("failed to download %s SHA256SUMS signature file: %w", v.pluginName, err)
	}
	sums, err := v.downloadFileBuffer(archiveManifest.URLSHASums)
	if err != nil {
		return fmt.Errorf("failed to download %s SHA256SUMS file: %w", v.pluginName, err)
	}

	checksums, err := releaseauth.ParseChecksums(sums)
	if err != nil {
		return fmt.Errorf("failed to parse %s SHA256SUMS file: %w", v.pluginName, err)
	}

	filename := path.Base(info.URL)
	reportedSHA, ok := checksums[filename]
	if !ok {
		return fmt.Errorf("could not find checksum for file %q", filename)
	}

	sigAuth := releaseauth.NewSignatureAuthentication(signature, sums)
	if len(v.signingKey) > 0 {
		sigAuth.PublicKey = v.signingKey
	}

	all := releaseauth.AllAuthenticators(
		releaseauth.NewChecksumAuthentication(reportedSHA, archiveLocation),
		sigAuth,
	)

	return all.Authenticate()
}

func (v BinaryManager) latestManifest(ctx context.Context) (*Release, error) {
	manifestCacheLocation := path.Join(v.pluginDataDir, v.host.String(), "manifest.json")

	// Find the manifest cache for the hostname.
	data, err := os.ReadFile(manifestCacheLocation)
	modTime := time.Time{}
	var localManifest *Release
	if err != nil {
		log.Printf("[TRACE] no %s manifest cache found for host %q", v.pluginName, v.host)
	} else {
		log.Printf("[TRACE] %s manifest cache found for host %q", v.pluginName, v.host)

		localManifest, err = decodeManifest(bytes.NewBuffer(data))
		modTime = localManifest.TimestampUpdated
		if err != nil {
			log.Printf("[WARN] failed to decode %s manifest cache %q: %s", v.pluginName, manifestCacheLocation, err)
		}
	}

	// Even though we may have a local manifest, always see if there is a newer remote manifest
	result, err := v.client.FetchManifest(modTime)
	// FetchManifest can return nil, nil (see below)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch %s manifest: %w", v.pluginName, err)
	}

	// No error and no remoteManifest means the existing manifest is not modified
	// and it's safe to use the local manifest
	if result == nil && localManifest != nil {
		result = localManifest
	} else {
		data, err := json.Marshal(result)
		if err != nil {
			return nil, fmt.Errorf("failed to dump %s manifest to JSON: %w", v.pluginName, err)
		}

		// Ensure target directory exists
		if err := os.MkdirAll(filepath.Dir(manifestCacheLocation), 0755); err != nil {
			return nil, fmt.Errorf("failed to create %s manifest cache directory: %w", v.pluginName, err)
		}

		output, err := os.Create(manifestCacheLocation)
		if err != nil {
			return nil, fmt.Errorf("failed to create %s manifest cache: %w", v.pluginName, err)
		}

		_, err = output.Write(data)
		if err != nil {
			return nil, fmt.Errorf("failed to write %s manifest cache: %w", v.pluginName, err)
		}
		log.Printf("[TRACE] wrote %s manifest cache to %q", v.pluginName, manifestCacheLocation)
	}

	return result, nil
}
