// main.go wires configuration, dependencies, and HTTP runtime startup.
// Layer: cmd/weatherapi executable composition root.
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"strings"
	"syscall"

	feedapp "gitea.maximumdirect.net/ejr/feedapi/app"
	"gitea.maximumdirect.net/ejr/feedapi/config"
	"gitea.maximumdirect.net/ejr/feedapi/db"
	httpapi "gitea.maximumdirect.net/ejr/weatherapi/internal/adapters/inbound/httpapi"
	wfpq "gitea.maximumdirect.net/ejr/weatherapi/internal/adapters/outbound/postgres"
	"gitea.maximumdirect.net/ejr/weatherapi/internal/app"

	_ "github.com/lib/pq"
)

func main() {
	log.SetFlags(log.LstdFlags | log.Lmicroseconds)

	cfgPath := flag.String("config", envOrDefault("WEATHERAPI_CONFIG", "config.yml"), "Path to config YAML")
	flag.Parse()

	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
	defer cancel()

	if err := run(ctx, *cfgPath); err != nil {
		log.Fatalf("weatherapi failed: %v", err)
	}
}

func run(ctx context.Context, cfgPath string) error {
	cfg, err := config.Load(cfgPath)
	if err != nil {
		return fmt.Errorf("load config: %w", err)
	}
	if len(cfg.Databases) == 0 {
		return fmt.Errorf("config.databases requires at least one entry")
	}

	reg, err := db.OpenAll(cfg.Databases)
	if err != nil {
		return fmt.Errorf("open databases: %w", err)
	}
	defer func() {
		if cerr := reg.Close(); cerr != nil {
			log.Printf("database close error: %v", cerr)
		}
	}()

	primaryName := cfg.Databases[0].Name
	primary, err := reg.Get(primaryName)
	if err != nil {
		return fmt.Errorf("select primary database %q: %w", primaryName, err)
	}

	repo := wfpq.NewRepository(primary)
	svc := app.NewService(repo)
	defs := httpapi.Definitions(svc)

	a, err := feedapp.New(cfg,
		feedapp.WithDBRegistry(reg),
		feedapp.WithEndpoints(defs...),
	)
	if err != nil {
		return fmt.Errorf("build app: %w", err)
	}

	return a.Start(ctx)
}

func envOrDefault(key, fallback string) string {
	v := strings.TrimSpace(os.Getenv(key))
	if v == "" {
		return fallback
	}
	return v
}
