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

package planfile

import (
	"archive/zip"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path"
	"sort"
	"strings"
	"time"

	version "github.com/hashicorp/go-version"
	"github.com/hashicorp/terraform/internal/configs/configload"
)

const configSnapshotPrefix = "tfconfig/"
const configSnapshotManifestFile = configSnapshotPrefix + "modules.json"
const configSnapshotModulePrefix = configSnapshotPrefix + "m-"

type configSnapshotModuleRecord struct {
	Key        string `json:"Key"`
	SourceAddr string `json:"Source,omitempty"`
	VersionStr string `json:"Version,omitempty"`
	Dir        string `json:"Dir"`
}
type configSnapshotModuleManifest []configSnapshotModuleRecord

func readConfigSnapshot(z *zip.Reader) (*configload.Snapshot, error) {
	// Errors from this function are expected to be reported with some
	// additional prefix context about them being in a config snapshot,
	// so they should not themselves refer to the config snapshot.
	// They are also generally indicative of an invalid file, and so since
	// plan files should not be hand-constructed we don't need to worry
	// about making the messages user-actionable.

	snap := &configload.Snapshot{
		Modules: map[string]*configload.SnapshotModule{},
	}
	var manifestSrc []byte

	// For processing our source files, we'll just sweep over all the files
	// and react to the one-by-one to start, and then clean up afterwards
	// when we'll presumably have found the manifest file.
	for _, file := range z.File {
		switch {

		case file.Name == configSnapshotManifestFile:
			// It's the manifest file, so we'll just read it raw into
			// manifestSrc for now and process it below.
			r, err := file.Open()
			if err != nil {
				return nil, fmt.Errorf("failed to open module manifest: %s", r)
			}
			manifestSrc, err = ioutil.ReadAll(r)
			if err != nil {
				return nil, fmt.Errorf("failed to read module manifest: %s", r)
			}

		case strings.HasPrefix(file.Name, configSnapshotModulePrefix):
			relName := file.Name[len(configSnapshotModulePrefix):]
			moduleKey, fileName := path.Split(relName)

			// moduleKey should currently have a trailing slash on it, which we
			// can use to recognize the difference between the root module
			// (just a trailing slash) and no module path at all (empty string).
			if moduleKey == "" {
				// ignore invalid config entry
				continue
			}
			moduleKey = moduleKey[:len(moduleKey)-1] // trim trailing slash

			r, err := file.Open()
			if err != nil {
				return nil, fmt.Errorf("failed to open snapshot of %s from module %q: %s", fileName, moduleKey, err)
			}
			fileSrc, err := ioutil.ReadAll(r)
			if err != nil {
				return nil, fmt.Errorf("failed to read snapshot of %s from module %q: %s", fileName, moduleKey, err)
			}

			if _, exists := snap.Modules[moduleKey]; !exists {
				snap.Modules[moduleKey] = &configload.SnapshotModule{
					Files: map[string][]byte{},
					// Will fill in everything else afterwards, when we
					// process the manifest.
				}
			}
			snap.Modules[moduleKey].Files[fileName] = fileSrc
		}
	}

	if manifestSrc == nil {
		return nil, fmt.Errorf("config snapshot does not have manifest file")
	}

	var manifest configSnapshotModuleManifest
	err := json.Unmarshal(manifestSrc, &manifest)
	if err != nil {
		return nil, fmt.Errorf("invalid module manifest: %s", err)
	}

	for _, record := range manifest {
		modSnap, exists := snap.Modules[record.Key]
		if !exists {
			// We'll allow this, assuming that it's a module with no files.
			// This is still weird, since we generally reject modules with
			// no files, but we'll allow it because downstream errors will
			// catch it in that case.
			modSnap = &configload.SnapshotModule{
				Files: map[string][]byte{},
			}
			snap.Modules[record.Key] = modSnap
		}
		modSnap.SourceAddr = record.SourceAddr
		modSnap.Dir = record.Dir
		if record.VersionStr != "" {
			v, err := version.NewVersion(record.VersionStr)
			if err != nil {
				return nil, fmt.Errorf("manifest has invalid version string %q for module %q", record.VersionStr, record.Key)
			}
			modSnap.Version = v
		}
	}

	// Finally, we'll make sure we don't have any errant files for modules that
	// aren't in the manifest.
	for k := range snap.Modules {
		found := false
		for _, record := range manifest {
			if record.Key == k {
				found = true
				break
			}
		}
		if !found {
			return nil, fmt.Errorf("found files for module %q that isn't recorded in the manifest", k)
		}
	}

	return snap, nil
}

// writeConfigSnapshot adds to the given zip.Writer one or more files
// representing the given snapshot.
//
// This file creates new files in the writer, so any already-open writer
// for the file will be invalidated by this call. The writer remains open
// when this function returns.
func writeConfigSnapshot(snap *configload.Snapshot, z *zip.Writer) error {
	// Errors from this function are expected to be reported with some
	// additional prefix context about them being in a config snapshot,
	// so they should not themselves refer to the config snapshot.
	// They are also indicative of a bug in the caller, so they do not
	// need to be user-actionable.

	var manifest configSnapshotModuleManifest
	keys := make([]string, 0, len(snap.Modules))
	for k := range snap.Modules {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	// We'll re-use this fileheader for each Create we do below.

	for _, k := range keys {
		snapMod := snap.Modules[k]
		record := configSnapshotModuleRecord{
			Dir:        snapMod.Dir,
			Key:        k,
			SourceAddr: snapMod.SourceAddr,
		}
		if snapMod.Version != nil {
			record.VersionStr = snapMod.Version.String()
		}
		manifest = append(manifest, record)

		pathPrefix := fmt.Sprintf("%s%s/", configSnapshotModulePrefix, k)
		for filename, src := range snapMod.Files {
			zh := &zip.FileHeader{
				Name:     pathPrefix + filename,
				Method:   zip.Deflate,
				Modified: time.Now(),
			}
			w, err := z.CreateHeader(zh)
			if err != nil {
				return fmt.Errorf("failed to create snapshot of %s from module %q: %s", zh.Name, k, err)
			}
			_, err = w.Write(src)
			if err != nil {
				return fmt.Errorf("failed to write snapshot of %s from module %q: %s", zh.Name, k, err)
			}
		}
	}

	// Now we'll write our manifest
	{
		zh := &zip.FileHeader{
			Name:     configSnapshotManifestFile,
			Method:   zip.Deflate,
			Modified: time.Now(),
		}
		src, err := json.MarshalIndent(manifest, "", "  ")
		if err != nil {
			return fmt.Errorf("failed to serialize module manifest: %s", err)
		}
		w, err := z.CreateHeader(zh)
		if err != nil {
			return fmt.Errorf("failed to create module manifest: %s", err)
		}
		_, err = w.Write(src)
		if err != nil {
			return fmt.Errorf("failed to write module manifest: %s", err)
		}
	}

	return nil
}
