package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"mail2couch/config"
	"mail2couch/couch"
	"mail2couch/mail"
)

func main() {
	cfg, err := config.LoadConfigWithDiscovery()
	if err != nil {
		log.Fatalf("Failed to load configuration: %v", err)
	}

	// Initialize CouchDB client
	couchClient, err := couch.NewClient(&cfg.CouchDb)
	if err != nil {
		log.Fatalf("Failed to create CouchDB client: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	err = couchClient.EnsureDB(ctx, cfg.CouchDb.Database)
	if err != nil {
		log.Printf("Could not ensure CouchDB database exists (is it running?): %v", err)
	} else {
		fmt.Printf("CouchDB database '%s' is ready.\n", cfg.CouchDb.Database)
	}

	fmt.Printf("Found %d mail source(s) to process.\n", len(cfg.MailSources))
	for _, source := range cfg.MailSources {
		if !source.Enabled {
			continue
		}

		fmt.Printf(" - Processing source: %s\n", source.Name)
		if source.Protocol == "imap" {
			err := processImapSource(&source, couchClient, cfg.CouchDb.Database)
			if err != nil {
				log.Printf("   ERROR: Failed to process IMAP source %s: %v", source.Name, err)
			}
		}
	}
}

func processImapSource(source *config.MailSource, couchClient *couch.Client, dbName string) error {
	fmt.Printf("   Connecting to IMAP server: %s:%d\n", source.Host, source.Port)
	imapClient, err := mail.NewImapClient(source)
	if err != nil {
		return fmt.Errorf("failed to connect to IMAP server: %w", err)
	}
	defer imapClient.Logout()

	fmt.Println("   IMAP connection successful.")

	mailboxes, err := imapClient.ListMailboxes()
	if err != nil {
		return fmt.Errorf("failed to list mailboxes: %w", err)
	}

	fmt.Printf("   Found %d mailboxes.\n", len(mailboxes))

	// Parse the since date if provided
	var sinceDate *time.Time
	if source.MessageFilter.Since != "" {
		parsed, err := time.Parse("2006-01-02", source.MessageFilter.Since)
		if err != nil {
			log.Printf("   WARNING: Invalid since date format '%s', ignoring filter", source.MessageFilter.Since)
		} else {
			sinceDate = &parsed
		}
	}

	totalMessages := 0
	totalStored := 0

	// Process each mailbox
	for _, mailbox := range mailboxes {
		// Check if this mailbox should be processed based on filters
		if !imapClient.ShouldProcessMailbox(mailbox, &source.FolderFilter) {
			fmt.Printf("   Skipping mailbox: %s (filtered)\n", mailbox)
			continue
		}

		fmt.Printf("   Processing mailbox: %s\n", mailbox)

		// Retrieve messages from the mailbox
		messages, err := imapClient.GetMessages(mailbox, sinceDate)
		if err != nil {
			log.Printf("   ERROR: Failed to get messages from %s: %v", mailbox, err)
			continue
		}

		if len(messages) == 0 {
			fmt.Printf("     No messages found in %s\n", mailbox)
			continue
		}

		fmt.Printf("     Found %d messages in %s\n", len(messages), mailbox)
		totalMessages += len(messages)

		// Convert messages to CouchDB documents
		var docs []*couch.MailDocument
		for _, msg := range messages {
			doc := couch.ConvertMessage(msg, mailbox)
			docs = append(docs, doc)
		}

		// Store messages in CouchDB
		ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
		stored := 0
		for _, doc := range docs {
			err := couchClient.StoreMessage(ctx, dbName, doc)
			if err != nil {
				log.Printf("     ERROR: Failed to store message %s: %v", doc.ID, err)
			} else {
				stored++
			}
		}
		cancel()

		fmt.Printf("     Stored %d/%d messages from %s\n", stored, len(messages), mailbox)
		totalStored += stored
	}

	fmt.Printf("   Summary: Processed %d messages, stored %d new messages\n", totalMessages, totalStored)
	return nil
}
