package main

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"crowdsec-dashy/internal/config"
	"crowdsec-dashy/internal/crowdsec"
	"crowdsec-dashy/internal/router"
	webfiles "crowdsec-dashy/web"
)

func main() {
	// ----------------------------------------------------------------
	// CLI flags
	// ----------------------------------------------------------------
	pwhash := flag.String("pwhash", "", "hash a password for use as ui_password in app_config.conf")
	flag.Parse()

	if *pwhash != "" {
		hash, err := config.HashPassword(*pwhash)
		if err != nil {
			log.Fatalf("hash password: %v", err)
		}
		fmt.Println(hash)
		os.Exit(0)
	}

	// ----------------------------------------------------------------
	// Configuration
	// ----------------------------------------------------------------
	cfg, err := config.Load()
	if err != nil {
		var firstRun *config.FirstRunError
		if errors.As(err, &firstRun) {
			log.Println(firstRun.Error())
			os.Exit(0)
		}
		log.Fatalf("configuration error: %v", err)
	}

	// ----------------------------------------------------------------
	// CrowdSec LAPI — authenticate at startup
	// ----------------------------------------------------------------
	lapi := crowdsec.NewLAPIClient(cfg.CrowdSecAPIURL, cfg.CrowdSecAPILogin, cfg.CrowdSecAPIPassword)

	log.Printf("connecting to CrowdSec LAPI at %s ...", cfg.CrowdSecAPIURL)
	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	if err := lapi.Login(ctx); err != nil {
		cancel()
		log.Fatalf("failed to authenticate with CrowdSec LAPI: %v\n"+
			"Check crowdsec_api_login / crowdsec_api_password in %s\n"+
			"Register the machine first: cscli machines add %s -a",
			err, config.ConfigFile(), cfg.CrowdSecAPILogin)
	}
	cancel()
	log.Println("authenticated with CrowdSec LAPI")

	// CLI availability
	if cfg.CscliAvailable() {
		log.Printf("cscli available at %s", cfg.CscliPath)
	} else {
		log.Printf("[WARN] cscli not found at %s — bouncer/machine/hub/metrics features disabled", cfg.CscliPath)
	}

	// ----------------------------------------------------------------
	// Build router
	// ----------------------------------------------------------------
	handler, err := router.New(cfg, lapi, webfiles.FS)
	if err != nil {
		log.Fatalf("failed to initialise router: %v", err)
	}

	// ----------------------------------------------------------------
	// HTTP server
	// ----------------------------------------------------------------
	srv := &http.Server{
		Addr:         cfg.Port,
		Handler:      handler,
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 60 * time.Second, // longer for hub operations
		IdleTimeout:  120 * time.Second,
	}

	log.Printf("CrowdSec UI listening on %s", srv.Addr)
	log.Printf("UI credentials: %s / [redacted]", cfg.UIUsername)
	if err := srv.ListenAndServe(); err != nil {
		log.Fatalf("server error: %v", err)
	}
}
