package main

import (
	"flag"
	"fmt"
	"log/slog"
	"os"
	"path/filepath"

	"archivmail/config"
	"archivmail/internal/index"
	"archivmail/internal/storage"
)

func main() {
	configPath := flag.String("config", "/etc/archivmail/config.yml", "path to config file")
	format := flag.String("format", "eml", "export format: eml or pdf")
	outDir := flag.String("out", "./export", "output directory")
	flag.Parse()

	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))

	if *format == "pdf" {
		fmt.Fprintln(os.Stdout, "PDF export not yet implemented")
		os.Exit(0)
	}

	if *format != "eml" {
		fmt.Fprintf(os.Stderr, "unknown format: %s (supported: eml, pdf)\n", *format)
		os.Exit(1)
	}

	cfg, err := config.Load(*configPath)
	if err != nil {
		logger.Error("failed to load config", "err", err)
		os.Exit(1)
	}

	mailStore, err := storage.New(cfg.Storage.StorePath)
	if err != nil {
		logger.Error("storage init failed", "err", err)
		os.Exit(1)
	}

	indexBackend := cfg.Index.Backend
	if indexBackend == "" {
		indexBackend = "manticore"
	}
	batchSize := cfg.Index.BatchSize
	if batchSize <= 0 {
		batchSize = 100
	}
	idx, err := index.New(cfg.Index.Path, batchSize, indexBackend)
	if err != nil {
		logger.Error("index init failed", "err", err)
		os.Exit(1)
	}
	defer idx.Close()

	if err := os.MkdirAll(*outDir, 0o755); err != nil {
		logger.Error("cannot create output directory", "dir", *outDir, "err", err)
		os.Exit(1)
	}

	// Fetch all indexed mails using pagination
	page := 0
	pageSize := 500
	exported := 0
	errors := 0

	for {
		result, err := idx.Search(index.SearchRequest{
			PageSize: pageSize,
			Page:     page,
		})
		if err != nil {
			logger.Error("search failed", "err", err)
			os.Exit(1)
		}

		if len(result.Hits) == 0 {
			break
		}

		for _, hit := range result.Hits {
			raw, err := mailStore.Load(hit.ID)
			if err != nil {
				logger.Error("load failed", "id", hit.ID, "err", err)
				errors++
				continue
			}

			outPath := filepath.Join(*outDir, hit.ID+".eml")
			if err := os.WriteFile(outPath, raw, 0o644); err != nil {
				logger.Error("write failed", "path", outPath, "err", err)
				errors++
				continue
			}

			exported++
		}

		logger.Info("export progress", "page", page, "exported", exported, "errors", errors)

		if exported+errors >= result.Total {
			break
		}
		page++
	}

	logger.Info("export complete",
		"format", *format,
		"out", *outDir,
		"exported", exported,
		"errors", errors,
	)
}
