package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"os/exec"
	"os/user"
	"strings"
	"time"
)

// Hardcoded Pushover credentials
const pushoverURL = "https://api.pushover.net/1/messages.json"
const pushoverToken = "aunhi15sq2ervgjzyxm1msnnmucv41"
const pushoverUserKey = "ujFeJyjYFJd2Lwbygfw9cSCoeYiLBi"

// Hastebin server URL
const hastebinServerURL = "https://haste.nixc.us/documents"

func main() {
	// Generate a unique filename for the asciinema recording
	timestamp := time.Now().Format("20060102150405")
	filename := fmt.Sprintf("asciinema-%s.cast", timestamp)

	// Inform the user how to stop the recording
	fmt.Println("Starting asciinema recording. Press Ctrl+D or type 'exit' to stop the recording.")

	// Start asciinema recording
	cmd := exec.Command("asciinema", "rec", filename)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin

	err := cmd.Start()
	if err != nil {
		log.Fatalf("Failed to start asciinema recording: %v", err)
	}

	err = cmd.Wait()
	if err != nil {
		log.Fatalf("Asciinema recording process exited with error: %v", err)
	}

	log.Println("Asciinema recording finished:", filename)

	// Collect system details
	hostname, _ := os.Hostname()
	currentUser, _ := user.Current()

	// Create the message with system details
	message := fmt.Sprintf("New asciinema recording from host: %s, user: %s", hostname, currentUser.Username)
	log.Println("Message to be sent:", message)

	// Upload the recording to Hastebin and get the URL
	hastebinURL, err := uploadToHastebin(filename)
	if err != nil {
		log.Fatalf("Failed to upload recording to Hastebin: %v", err)
	}

	// Update the message with the Hastebin URL
	message = fmt.Sprintf("New asciinema recording from host: %s, user: %s, URL: %s", hostname, currentUser.Username, hastebinURL)

	// Ask the user if this is a priority notification
	isPriority := askPriority()
	log.Println("Priority status:", isPriority)

	// Send the updated message to Pushover
	err = sendToPushover(message, isPriority)
	if err != nil {
		log.Fatalf("Failed to send recording to Pushover: %v", err)
	}

	log.Println("Recording sent to Pushover successfully.")
}

// uploadToHastebin uploads the asciinema recording to Hastebin and returns the resulting URL
func uploadToHastebin(filename string) (string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return "", fmt.Errorf("failed to open recording file: %w", err)
	}
	defer file.Close()

	body := &bytes.Buffer{}
	_, err = io.Copy(body, file)
	if err != nil {
		return "", fmt.Errorf("failed to copy file content: %w", err)
	}

	req, err := http.NewRequest("POST", hastebinServerURL, body)
	if err != nil {
		return "", fmt.Errorf("failed to create request: %w", err)
	}
	req.Header.Set("Content-Type", "text/plain")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("failed to send request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("received non-200 response: %d", resp.StatusCode)
	}

	var result struct {
		Key string `json:"key"`
	}
	err = json.NewDecoder(resp.Body).Decode(&result)
	if err != nil {
		return "", fmt.Errorf("failed to decode response: %w", err)
	}

	return fmt.Sprintf("https://haste.nixc.us/%s", result.Key), nil
}

// askPriority prompts the user to specify if the notification is a priority
func askPriority() bool {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("Is this a priority notification? (yes/no): ")
	response, err := reader.ReadString('\n')
	if err != nil {
		log.Fatalf("Failed to read user input: %v", err)
	}
	response = strings.TrimSpace(strings.ToLower(response))
	return response == "yes"
}

// sendToPushover sends the message to the Pushover URL
func sendToPushover(message string, priority bool) error {
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	writer.WriteField("token", pushoverToken)
	writer.WriteField("user", pushoverUserKey)
	writer.WriteField("message", message)
	if priority {
		writer.WriteField("priority", "2")
		writer.WriteField("retry", "60")
		writer.WriteField("expire", "1800")
	}

	err := writer.Close()
	if err != nil {
		return fmt.Errorf("failed to close writer: %w", err)
	}

	req, err := http.NewRequest("POST", pushoverURL, body)
	if err != nil {
		return fmt.Errorf("failed to create request: %w", err)
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("failed to send request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("received non-200 response: %d", resp.StatusCode)
	}

	return nil
}
