package statemgr

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sync"
	"time"

	multierror "github.com/hashicorp/go-multierror"

	"github.com/hashicorp/terraform/internal/states"
	"github.com/hashicorp/terraform/internal/states/statefile"
	"github.com/hashicorp/terraform/internal/terraform"
)

// Filesystem is a full state manager that uses a file in the local filesystem
// for persistent storage.
//
// The transient storage for Filesystem is always in-memory.
type Filesystem struct {
	mu sync.Mutex

	// path is the location where a file will be created or replaced for
	// each persistent snapshot.
	path string

	// readPath is read by RefreshState instead of "path" until the first
	// call to PersistState, after which it is ignored.
	//
	// The file at readPath must never be written to by this manager.
	readPath string

	// backupPath is an optional extra path which, if non-empty, will be
	// created or overwritten with the first state snapshot we read if there
	// is a subsequent call to write a different state.
	backupPath string

	// the file handle corresponding to PathOut
	stateFileOut *os.File

	// While the stateFileOut will correspond to the lock directly,
	// store and check the lock ID to maintain a strict statemgr.Locker
	// implementation.
	lockID string

	// created is set to true if stateFileOut didn't exist before we created it.
	// This is mostly so we can clean up empty files during tests, but doesn't
	// hurt to remove file we never wrote to.
	created bool

	file          *statefile.File
	readFile      *statefile.File
	backupFile    *statefile.File
	writtenBackup bool
}

var (
	_ Full           = (*Filesystem)(nil)
	_ PersistentMeta = (*Filesystem)(nil)
	_ Migrator       = (*Filesystem)(nil)
)

// NewFilesystem creates a filesystem-based state manager that reads and writes
// state snapshots at the given filesystem path.
//
// This is equivalent to calling NewFileSystemBetweenPaths with statePath as
// both of the path arguments.
func NewFilesystem(statePath string) *Filesystem {
	return &Filesystem{
		path:     statePath,
		readPath: statePath,
	}
}

// NewFilesystemBetweenPaths creates a filesystem-based state manager that
// reads an initial snapshot from readPath and then writes all new snapshots to
// writePath.
func NewFilesystemBetweenPaths(readPath, writePath string) *Filesystem {
	return &Filesystem{
		path:     writePath,
		readPath: readPath,
	}
}

// SetBackupPath configures the receiever so that it will create a local
// backup file of the next state snapshot it reads (in State) if a different
// snapshot is subsequently written (in WriteState). Only one backup is
// written for the lifetime of the object, unless reset as described below.
//
// For correct operation, this must be called before any other state methods
// are called. If called multiple times, each call resets the backup
// function so that the next read will become the backup snapshot and a
// following write will save a backup of it.
func (s *Filesystem) SetBackupPath(path string) {
	s.backupPath = path
	s.backupFile = nil
	s.writtenBackup = false
}

// BackupPath returns the manager's backup path if backup files are enabled,
// or an empty string otherwise.
func (s *Filesystem) BackupPath() string {
	return s.backupPath
}

// State is an implementation of Reader.
func (s *Filesystem) State() *states.State {
	defer s.mutex()()
	if s.file == nil {
		return nil
	}
	return s.file.DeepCopy().State
}

// WriteState is an incorrect implementation of Writer that actually also
// persists.
func (s *Filesystem) WriteState(state *states.State) error {
	// TODO: this should use a more robust method of writing state, by first
	// writing to a temp file on the same filesystem, and renaming the file over
	// the original.

	defer s.mutex()()

	if s.readFile == nil {
		err := s.refreshState()
		if err != nil {
			return err
		}
	}

	return s.writeState(state, nil)
}

func (s *Filesystem) writeState(state *states.State, meta *SnapshotMeta) error {
	if s.stateFileOut == nil {
		if err := s.createStateFiles(); err != nil {
			return nil
		}
	}
	defer s.stateFileOut.Sync()

	// We'll try to write our backup first, so we can be sure we've created
	// it successfully before clobbering the original file it came from.
	if !s.writtenBackup && s.backupFile != nil && s.backupPath != "" {
		if !statefile.StatesMarshalEqual(state, s.backupFile.State) {
			log.Printf("[TRACE] statemgr.Filesystem: creating backup snapshot at %s", s.backupPath)
			bfh, err := os.Create(s.backupPath)
			if err != nil {
				return fmt.Errorf("failed to create local state backup file: %s", err)
			}
			defer bfh.Close()

			err = statefile.Write(s.backupFile, bfh)
			if err != nil {
				return fmt.Errorf("failed to write to local state backup file: %s", err)
			}

			s.writtenBackup = true
		} else {
			log.Print("[TRACE] statemgr.Filesystem: not making a backup, because the new snapshot is identical to the old")
		}
	} else {
		// This branch is all just logging, to help understand why we didn't make a backup.
		switch {
		case s.backupPath == "":
			log.Print("[TRACE] statemgr.Filesystem: state file backups are disabled")
		case s.writtenBackup:
			log.Printf("[TRACE] statemgr.Filesystem: have already backed up original %s to %s on a previous write", s.path, s.backupPath)
		case s.backupFile == nil:
			log.Printf("[TRACE] statemgr.Filesystem: no original state snapshot to back up")
		default:
			log.Printf("[TRACE] statemgr.Filesystem: not creating a backup for an unknown reason")
		}
	}

	s.file = s.file.DeepCopy()
	if s.file == nil {
		s.file = NewStateFile()
	}
	s.file.State = state.DeepCopy()

	if _, err := s.stateFileOut.Seek(0, io.SeekStart); err != nil {
		return err
	}
	if err := s.stateFileOut.Truncate(0); err != nil {
		return err
	}

	if state == nil {
		// if we have no state, don't write anything else.
		log.Print("[TRACE] statemgr.Filesystem: state is nil, so leaving the file empty")
		return nil
	}

	if meta == nil {
		if s.readFile == nil || !statefile.StatesMarshalEqual(s.file.State, s.readFile.State) {
			s.file.Serial++
			log.Printf("[TRACE] statemgr.Filesystem: state has changed since last snapshot, so incrementing serial to %d", s.file.Serial)
		} else {
			log.Print("[TRACE] statemgr.Filesystem: no state changes since last snapshot")
		}
	} else {
		// Force new metadata
		s.file.Lineage = meta.Lineage
		s.file.Serial = meta.Serial
		log.Printf("[TRACE] statemgr.Filesystem: forcing lineage %q serial %d for migration/import", s.file.Lineage, s.file.Serial)
	}

	log.Printf("[TRACE] statemgr.Filesystem: writing snapshot at %s", s.path)
	if err := statefile.Write(s.file, s.stateFileOut); err != nil {
		return err
	}

	// Any future reads must come from the file we've now updated
	s.readPath = s.path
	return nil
}

// PersistState is an implementation of Persister that does nothing because
// this type's Writer implementation does its own persistence.
func (s *Filesystem) PersistState(schemas *terraform.Schemas) error {
	return nil
}

// RefreshState is an implementation of Refresher.
func (s *Filesystem) RefreshState() error {
	defer s.mutex()()
	return s.refreshState()
}

func (s *Filesystem) GetRootOutputValues() (map[string]*states.OutputValue, error) {
	err := s.RefreshState()
	if err != nil {
		return nil, err
	}

	state := s.State()
	if state == nil {
		state = states.NewState()
	}

	return state.RootModule().OutputValues, nil
}

func (s *Filesystem) refreshState() error {
	var reader io.Reader

	// The s.readPath file is only OK to read if we have not written any state out
	// (in which case the same state needs to be read in), and no state output file
	// has been opened (possibly via a lock) or the input path is different
	// than the output path.
	// This is important for Windows, as if the input file is the same as the
	// output file, and the output file has been locked already, we can't open
	// the file again.
	if s.stateFileOut == nil || s.readPath != s.path {
		// we haven't written a state file yet, so load from readPath
		log.Printf("[TRACE] statemgr.Filesystem: reading initial snapshot from %s", s.readPath)
		f, err := os.Open(s.readPath)
		if err != nil {
			// It is okay if the file doesn't exist; we'll treat that as a nil state.
			if !os.IsNotExist(err) {
				return err
			}

			// we need a non-nil reader for ReadState and an empty buffer works
			// to return EOF immediately
			reader = bytes.NewBuffer(nil)

		} else {
			defer f.Close()
			reader = f
		}
	} else {
		log.Printf("[TRACE] statemgr.Filesystem: reading latest snapshot from %s", s.path)
		// no state to refresh
		if s.stateFileOut == nil {
			return nil
		}

		// we have a state file, make sure we're at the start
		s.stateFileOut.Seek(0, io.SeekStart)
		reader = s.stateFileOut
	}

	f, err := statefile.Read(reader)
	// if there's no state then a nil file is fine
	if err != nil {
		if err != statefile.ErrNoState {
			return err
		}
		log.Printf("[TRACE] statemgr.Filesystem: snapshot file has nil snapshot, but that's okay")
	}

	s.file = f
	s.readFile = s.file.DeepCopy()
	if s.file != nil {
		log.Printf("[TRACE] statemgr.Filesystem: read snapshot with lineage %q serial %d", s.file.Lineage, s.file.Serial)
	} else {
		log.Print("[TRACE] statemgr.Filesystem: read nil snapshot")
	}
	return nil
}

// Lock implements Locker using filesystem discretionary locks.
func (s *Filesystem) Lock(info *LockInfo) (string, error) {
	defer s.mutex()()

	if s.stateFileOut == nil {
		if err := s.createStateFiles(); err != nil {
			return "", err
		}
	}

	if s.lockID != "" {
		return "", fmt.Errorf("state %q already locked", s.stateFileOut.Name())
	}

	if err := s.lock(); err != nil {
		info, infoErr := s.lockInfo()
		if infoErr != nil {
			err = multierror.Append(err, infoErr)
		}

		lockErr := &LockError{
			Info: info,
			Err:  err,
		}

		return "", lockErr
	}

	s.lockID = info.ID
	return s.lockID, s.writeLockInfo(info)
}

// Unlock is the companion to Lock, completing the implemention of Locker.
func (s *Filesystem) Unlock(id string) error {
	defer s.mutex()()

	if s.lockID == "" {
		return fmt.Errorf("LocalState not locked")
	}

	if id != s.lockID {
		idErr := fmt.Errorf("invalid lock id: %q. current id: %q", id, s.lockID)
		info, err := s.lockInfo()
		if err != nil {
			idErr = multierror.Append(idErr, err)
		}

		return &LockError{
			Err:  idErr,
			Info: info,
		}
	}

	lockInfoPath := s.lockInfoPath()
	log.Printf("[TRACE] statemgr.Filesystem: removing lock metadata file %s", lockInfoPath)
	os.Remove(lockInfoPath)

	fileName := s.stateFileOut.Name()

	unlockErr := s.unlock()

	s.stateFileOut.Close()
	s.stateFileOut = nil
	s.lockID = ""

	// clean up the state file if we created it an never wrote to it
	stat, err := os.Stat(fileName)
	if err == nil && stat.Size() == 0 && s.created {
		os.Remove(fileName)
	}

	return unlockErr
}

// StateSnapshotMeta returns the metadata from the most recently persisted
// or refreshed persistent state snapshot.
//
// This is an implementation of PersistentMeta.
func (s *Filesystem) StateSnapshotMeta() SnapshotMeta {
	if s.file == nil {
		return SnapshotMeta{} // placeholder
	}

	return SnapshotMeta{
		Lineage: s.file.Lineage,
		Serial:  s.file.Serial,

		TerraformVersion: s.file.TerraformVersion,
	}
}

// StateForMigration is part of our implementation of Migrator.
func (s *Filesystem) StateForMigration() *statefile.File {
	return s.file.DeepCopy()
}

// WriteStateForMigration is part of our implementation of Migrator.
func (s *Filesystem) WriteStateForMigration(f *statefile.File, force bool) error {
	defer s.mutex()()

	if s.readFile == nil {
		err := s.refreshState()
		if err != nil {
			return err
		}
	}

	if !force {
		err := CheckValidImport(f, s.readFile)
		if err != nil {
			return err
		}
	}

	if s.readFile != nil {
		log.Printf(
			"[TRACE] statemgr.Filesystem: Importing snapshot with lineage %q serial %d over snapshot with lineage %q serial %d at %s",
			f.Lineage, f.Serial,
			s.readFile.Lineage, s.readFile.Serial,
			s.path,
		)
	} else {
		log.Printf(
			"[TRACE] statemgr.Filesystem: Importing snapshot with lineage %q serial %d as the initial state snapshot at %s",
			f.Lineage, f.Serial,
			s.path,
		)
	}

	err := s.writeState(f.State, &SnapshotMeta{Lineage: f.Lineage, Serial: f.Serial})
	if err != nil {
		return err
	}

	return nil
}

// Open the state file, creating the directories and file as needed.
func (s *Filesystem) createStateFiles() error {
	log.Printf("[TRACE] statemgr.Filesystem: preparing to manage state snapshots at %s", s.path)

	// This could race, but we only use it to clean up empty files
	if _, err := os.Stat(s.path); os.IsNotExist(err) {
		s.created = true
	}

	// Create all the directories
	if err := os.MkdirAll(filepath.Dir(s.path), 0755); err != nil {
		return err
	}

	f, err := os.OpenFile(s.path, os.O_RDWR|os.O_CREATE, 0666)
	if err != nil {
		return err
	}

	s.stateFileOut = f

	// If the file already existed with content then that'll be the content
	// of our backup file if we write a change later.
	s.backupFile, err = statefile.Read(s.stateFileOut)
	if err != nil {
		if err != statefile.ErrNoState {
			return err
		}
		log.Printf("[TRACE] statemgr.Filesystem: no previously-stored snapshot exists")
	} else {
		log.Printf("[TRACE] statemgr.Filesystem: existing snapshot has lineage %q serial %d", s.backupFile.Lineage, s.backupFile.Serial)
	}

	// Refresh now, to load in the snapshot if the file already existed
	return nil
}

// return the path for the lockInfo metadata.
func (s *Filesystem) lockInfoPath() string {
	stateDir, stateName := filepath.Split(s.path)
	if stateName == "" {
		panic("empty state file path")
	}

	if stateName[0] == '.' {
		stateName = stateName[1:]
	}

	return filepath.Join(stateDir, fmt.Sprintf(".%s.lock.info", stateName))
}

// lockInfo returns the data in a lock info file
func (s *Filesystem) lockInfo() (*LockInfo, error) {
	path := s.lockInfoPath()
	infoData, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	info := LockInfo{}
	err = json.Unmarshal(infoData, &info)
	if err != nil {
		return nil, fmt.Errorf("state file %q locked, but could not unmarshal lock info: %s", s.readPath, err)
	}
	return &info, nil
}

// write a new lock info file
func (s *Filesystem) writeLockInfo(info *LockInfo) error {
	path := s.lockInfoPath()
	info.Path = s.readPath
	info.Created = time.Now().UTC()

	log.Printf("[TRACE] statemgr.Filesystem: writing lock metadata to %s", path)
	err := ioutil.WriteFile(path, info.Marshal(), 0600)
	if err != nil {
		return fmt.Errorf("could not write lock info for %q: %s", s.readPath, err)
	}
	return nil
}

func (s *Filesystem) mutex() func() {
	s.mu.Lock()
	return s.mu.Unlock
}
