package main

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

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

func main() {
	configPath := flag.String("config", "/etc/archivmail/config.yml", "path to config file")
	flag.Parse()

	args := flag.Args()
	if len(args) == 0 {
		fmt.Fprintln(os.Stderr, "usage: archivmail-import --config <path> <directory-or-file>")
		os.Exit(1)
	}
	target := args[0]

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

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

	mailStore, err := storage.New(storage.Config{
		Dir:     cfg.Storage.StorePath,
		Keyfile: cfg.Storage.Keyfile,
		DSN:     cfg.Database.DSN(),
	})
	if err != nil {
		logger.Error("storage init failed", "err", err)
		os.Exit(1)
	}
	defer mailStore.Close()

	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()

	var emlFiles []string

	info, err := os.Stat(target)
	if err != nil {
		logger.Error("target not found", "path", target, "err", err)
		os.Exit(1)
	}

	if info.IsDir() {
		err = filepath.Walk(target, func(path string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if !fi.IsDir() && strings.HasSuffix(strings.ToLower(fi.Name()), ".eml") {
				emlFiles = append(emlFiles, path)
			}
			return nil
		})
		if err != nil {
			logger.Error("walk failed", "err", err)
			os.Exit(1)
		}
	} else {
		emlFiles = []string{target}
	}

	logger.Info("found EML files", "count", len(emlFiles))

	imported := 0
	skipped := 0
	errors := 0

	for i, path := range emlFiles {
		raw, err := os.ReadFile(path)
		if err != nil {
			logger.Error("read file failed", "path", path, "err", err)
			errors++
			continue
		}

		pm, err := mailparser.Parse(raw)
		if err != nil {
			logger.Error("parse failed", "path", path, "err", err)
			errors++
			continue
		}

		id, err := mailStore.Save(context.Background(), raw, pm.Date, nil)
		if err != nil {
			logger.Error("save failed", "path", path, "err", err)
			errors++
			continue
		}

		// Build attachment names list
		var attachNames []string
		for _, att := range pm.Attachments {
			attachNames = append(attachNames, att.Filename)
		}

		doc := index.MailDocument{
			ID:            id,
			From:          pm.From,
			To:            strings.Join(pm.To, " "),
			CC:            strings.Join(pm.CC, " "),
			Subject:       pm.Subject,
			Body:          pm.TextBody + " " + pm.HTMLBody,
			AttachNames:   strings.Join(attachNames, " "),
			HasAttachment: len(pm.Attachments) > 0,
			Date:          pm.Date,
			Size:          int64(len(raw)),
		}

		if err := idx.IndexSync(doc); err != nil {
			logger.Error("index failed", "id", id, "err", err)
			errors++
			continue
		}

		imported++
		if (i+1)%100 == 0 || i+1 == len(emlFiles) {
			fmt.Printf("Progress: %d/%d (imported: %d, skipped: %d, errors: %d)\n",
				i+1, len(emlFiles), imported, skipped, errors)
		}
	}

	logger.Info("import complete",
		"total", len(emlFiles),
		"imported", imported,
		"skipped", skipped,
		"errors", errors,
	)
}
