package main

import (
	"bufio"
	"fmt"
	"golang.org/x/crypto/ssh"
	"io"
	"os"
	"strings"
	"time"
	"golang.org/x/term"
	"syscall"
)

func main() {
	// Minta input IP WLC, username, password, MAC address, file name, dan monitor time interval dari user
	reader := bufio.NewReader(os.Stdin)

	fmt.Print("Enter WLC IP or hostname: ")
	wlcHost, _ := reader.ReadString('\n')
	wlcHost = strings.TrimSpace(wlcHost)

	fmt.Print("Enter username: ")
	user, _ := reader.ReadString('\n')
	user = strings.TrimSpace(user)

	fmt.Print("Enter password: ")
	bytePassword, _ := term.ReadPassword(int(syscall.Stdin))
	password := string(bytePassword)
	fmt.Println()
	password = strings.TrimSpace(password)

	fmt.Print("Enter MAC address (format xxxx.xxxx.xxxx): ")
	mac, _ := reader.ReadString('\n')
	mac = strings.TrimSpace(mac)

	fmt.Print("Enter file name to save trace (e.g. 1c2f.a261.d2d6-test.txt): ")
	filename, _ := reader.ReadString('\n')
	filename = strings.TrimSpace(filename)

	fmt.Print("Enter monitor time interval in seconds: ")
	var monitorTime int
	fmt.Scanf("%d", &monitorTime)

	// Loop iterasi untuk jalankan debug trace dan append hasil
	for i := 1; ; i++ {
		fmt.Printf("Starting iteration %d\n", i)

		// Buat koneksi baru untuk setiap iterasi
		client, err := connectToWLC(wlcHost, user, password)
		if err != nil {
			fmt.Println("Failed to connect to WLC: ", err)
			fmt.Println("Waiting 30 seconds before retry...")
			time.Sleep(30 * time.Second)
			continue
		}

		fmt.Println("Connected to WLC successfully")

		// Buat session
		session, err := client.NewSession()
		if err != nil {
			fmt.Println("Failed to create session: ", err)
			client.Close()
			fmt.Println("Waiting 30 seconds before retry...")
			time.Sleep(30 * time.Second)
			continue
		}

		// Jalankan perintah debug wireless mac ...
		cmd := fmt.Sprintf("debug wireless mac %s to-file flash:/%s level debug monitor-time %d", mac, filename, monitorTime)
		fmt.Println("Running command: ", cmd)

		// Jalankan perintah dan tunggu sampai selesai
		err = session.Run(cmd)
		session.Close()

		if err != nil {
			fmt.Println("Command execution failed: ", err)
			client.Close()
			// Lanjut ke iterasi berikutnya
			time.Sleep(5 * time.Second)
			continue
		}

		// Tunggu sesuai monitor time + sedikit buffer
		fmt.Printf("Waiting for %d seconds to complete trace...\n", monitorTime)
		time.Sleep(time.Duration(monitorTime+15) * time.Second)

		// Buat koneksi baru untuk operasi download dan delete
		client2, err := connectToWLC(wlcHost, user, password)
		if err != nil {
			fmt.Println("Failed to reconnect to WLC for file operations: ", err)
			fmt.Println("Skipping file operations for this iteration")
		} else {
			// Download file dari WLC
			fmt.Println("Downloading trace file from WLC...")
			content := downloadFile(client2, filename)
			if content != nil {
				// Append ke file lokal
				appendToFile(filename, content)
				fmt.Println("Trace file downloaded and appended successfully")
			} else {
				fmt.Println("Failed to download trace file")
			}

			// Hapus file di WLC
			fmt.Println("Deleting trace file from WLC...")
			deleteFile(client2, filename)
			client2.Close()
		}

		client.Close()
		fmt.Printf("Iteration %d done. Press Ctrl+C to stop or wait for next iteration.\n", i)
		time.Sleep(10 * time.Second)
	}
}

func connectToWLC(wlcHost, user, password string) (*ssh.Client, error) {
	// Konfigurasi SSH
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		Timeout: 30 * time.Second,
	}

	// Connect ke WLC
	client, err := ssh.Dial("tcp", wlcHost+":22", config)
	return client, err
}

func downloadFile(client *ssh.Client, filename string) []byte {
	session, err := client.NewSession()
	if err != nil {
		fmt.Println("Failed to create session for download: ", err)
		return nil
	}
	defer session.Close()

	cmd := fmt.Sprintf("more flash:/%s", filename)
	output, err := session.CombinedOutput(cmd)
	if err != nil {
		fmt.Println("Failed to download file: ", err)
		return nil
	}

	return output
}

func appendToFile(filename string, content []byte) {
	f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Println("Failed to open local file for append: ", err)
		return
	}
	defer f.Close()

	_, err = f.Write(content)
	if err != nil {
		fmt.Println("Failed to append to local file: ", err)
	}
}

func deleteFile(client *ssh.Client, filename string) {
	session, err := client.NewSession()
	if err != nil {
		fmt.Println("Failed to create session for delete: ", err)
		return
	}
	defer session.Close()

	cmd := fmt.Sprintf("delete flash:/%s", filename)
	stdin, err := session.StdinPipe()
	if err != nil {
		fmt.Println("Failed to get stdin pipe: ", err)
		return
	}

	go func() {
		defer stdin.Close()
		io.WriteString(stdin, "y\n")
	}()

	output, err := session.CombinedOutput(cmd)
	if err != nil {
		fmt.Println("Failed to delete file: ", err)
		return
	}

	fmt.Println("Delete output:", string(output))
}

/* Removed duplicate function definitions of downloadFile, appendToFile, and deleteFile.
   The correct implementations remain elsewhere in this file. */
	// Duplicate trace helper functions removed; canonical implementations
	// (downloadFile, deleteFile, appendToFile) remain elsewhere in this file.
	// This removed section prevented a syntax error caused by duplicate
	// function definitions and an extra closing brace.
