package main

import (
	"fmt"
	"golang.org/x/crypto/ssh"
	"io"
	"log"
)

func isExitMissingError(err error) bool {
	_, isExitMissingError := err.(*ssh.ExitMissingError)
	return isExitMissingError
}

func deploy(manifest Manifest) error {
	connectionData, err := provideConnection(manifest)
	if err != nil {
		return fmt.Errorf("error while obtaining connection data: %w", err)
	}
	sshClient, err := openSshClient(connectionData)
	if err != nil {
		return fmt.Errorf("error while opening ssh client: %w", err)
	}
	defer sshClient.Close()

	for _, file := range manifest.Files {
		sshSession, err := openSshSession(sshClient)
		if err != nil {
			return fmt.Errorf("error while opening ssh session: %w", err)
		}
		log.Printf("copying file %s to %s with mode 0%d \n", file.Source, file.Target, file.Mode)
		if err := copyFile(sshSession, file); err != nil && !isExitMissingError(err) {
			_ = sshSession.Close()
			return fmt.Errorf("error while copying file %s: %w", file.Target, err)
		}
		if err := sshSession.Close(); err != nil && err != io.EOF {
			return fmt.Errorf("error while closing ssh session: %w", err)
		}
	}

	for _, file := range manifest.Files {
		if file.Execute {
			sshSession, err := openSshSession(sshClient)
			if err != nil {
				return fmt.Errorf("error while opening ssh session: %w", err)
			}
			log.Printf("running command %s\n", file.Target)
			if err := sshSession.Run(file.Target); err != nil && !isExitMissingError(err) {
				_ = sshSession.Close()
				return fmt.Errorf("error while running command: %w", err)
			}
			if err := sshSession.Close(); err != nil && err != io.EOF {
				return fmt.Errorf("error while closing ssh session: %w", err)
			}
		}
	}

	return nil
}