package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/emersion/go-imap"
	"github.com/emersion/go-imap/client"
	"github.com/emersion/go-message/mail"
)

func main() {
	host := os.Getenv("IMAP_HOST")
	username := os.Getenv("IMAP_USERNAME")
	password := os.Getenv("IMAP_PASSWORD")

	if host == "" || username == "" || password == "" {
		log.Fatal("Environment variables IMAP_HOST, IMAP_USERNAME, and IMAP_PASSWORD must be set")
	}

	log.Println("Connecting to server...")

	// Connect to the IMAP server
	c, err := client.DialTLS(host, nil)
	if err != nil {
		log.Fatalf("Failed to connect to IMAP server: %v", err)
	}
	log.Println("Connected")
	defer c.Logout()

	// Login
	if err := c.Login(username, password); err != nil {
		log.Fatalf("Failed to log in: %v", err)
	}
	log.Println("Logged in")

	// Select INBOX
	_, err = c.Select("INBOX", false)
	if err != nil {
		log.Fatalf("Failed to select INBOX: %v", err)
	}

	// Set up criteria to search for new unseen emails
	criteria := imap.NewSearchCriteria()
	criteria.WithoutFlags = []string{imap.SeenFlag}
	ids, err := c.Search(criteria)
	if err != nil {
		log.Fatalf("Failed to search emails: %v", err)
	}
	if len(ids) == 0 {
		log.Println("No new emails")
		return
	}

	seqset := new(imap.SeqSet)
	seqset.AddNum(ids...)

	section := &imap.BodySectionName{}
	items := []imap.FetchItem{section.FetchItem(), imap.FetchEnvelope}
	messages := make(chan *imap.Message)
	go func() {
		if err := c.Fetch(seqset, items, messages); err != nil {
			log.Fatalf("Failed to fetch emails: %v", err)
		}
	}()

	for msg := range messages {
		if msg == nil {
			continue
		}

		r := mail.NewReader(msg.GetBody(section))
		email, err := r.NextPart()
		if err != nil {
			log.Fatalf("Failed to read message body: %v", err)
		}

		body, err := ioutil.ReadAll(email)
		if err != nil {
			log.Fatalf("Failed to read body content: %v", err)
		}

		emailData := map[string]interface{}{
			"subject": msg.Envelope.Subject,
			"from":    msg.Envelope.From,
			"to":      msg.Envelope.To,
			"date":    msg.Envelope.Date,
			"body":    string(body),
		}

		emailJSON, err := json.MarshalIndent(emailData, "", "  ")
		if err != nil {
			log.Fatalf("Failed to marshal JSON: %v", err)
		}

		timestamp := time.Now().Format("20060102-150405")
		fileName := fmt.Sprintf("email-%s.json", timestamp)
		err = os.WriteFile(fileName, emailJSON, 0644)
		if err != nil {
			log.Fatalf("Failed to write file %s: %v", fileName, err)
		}
		log.Printf("Saved %s", fileName)
	}
}
