package web

import (
	"encoding/json"
	"fmt"
	"io/fs"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"testing"
	"time"

	"pete/internal/config"
	"pete/internal/storage"
)

// TestDrive is not a test. It is a hand crank: it stands the casino up on a real
// port with one funded player so a browser can be pointed at it. Skipped unless
// PETE_DRIVE is set. Delete it if it ever stops earning its keep.
func TestDrive(t *testing.T) {
	if os.Getenv("PETE_DRIVE") == "" {
		t.Skip("set PETE_DRIVE=1 to hand-drive the casino")
	}
	// Built through New() with the tables already open, because the /games routes
	// are registered at construction — newCasino() switches them on afterwards,
	// which is fine for handler tests and useless for a browser.
	storage.Close()
	if err := storage.Init(filepath.Join(t.TempDir(), "drive.db")); err != nil {
		t.Fatal(err)
	}
	defer storage.Close()

	s, err := New(config.WebConfig{
		SiteTitle:  "Pete",
		ListenAddr: ":0",
		BaseURL:    "http://127.0.0.1",
		Games:      config.GamesConfig{Enabled: true, MatrixServer: "parodia.dev"},
	}, nil, true, config.AdventureConfig{}, nil)
	if err != nil {
		t.Fatal(err)
	}
	// New() only mounts the casino when auth is live, and auth means an OIDC
	// discovery call. Sign the cookie by hand and mount the routes here instead —
	// the handshake is not what a browser is here to look at.
	s.auth = &Authenticator{secret: []byte("test-secret-key-at-least-16")}
	fund(t, 5000)

	static, err := fs.Sub(staticFS, "static")
	if err != nil {
		t.Fatal(err)
	}
	mux := http.NewServeMux()
	mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.FS(static))))
	mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(200) })
	mux.HandleFunc("GET /games", s.handleLobby)
	mux.HandleFunc("GET /games/blackjack", s.handleBlackjack)
	mux.HandleFunc("GET /api/games/table", s.handleTable)
	mux.HandleFunc("POST /api/games/buyin", s.handleBuyIn)
	mux.HandleFunc("POST /api/games/cashout", s.handleCashOut)
	mux.HandleFunc("POST /api/games/blackjack/deal", s.handleDeal)
	mux.HandleFunc("POST /api/games/blackjack/move", s.handleMove)

	srv := httptest.NewServer(mux)
	defer srv.Close()

	payload, _ := json.Marshal(SessionUser{
		Sub: "sub-1", Username: "reala", Exp: time.Now().Add(time.Hour).Unix(),
	})
	fmt.Printf("DRIVE_URL=%s\nDRIVE_COOKIE=%s=%s\n", srv.URL, sessionCookie, s.auth.sign(payload))

	// Long enough for a browser to buy in, deal a few hands, and be screenshotted.
	deadline := time.Now().Add(3 * time.Minute)
	for time.Now().Before(deadline) {
		time.Sleep(500 * time.Millisecond)
		if _, err := http.Get(srv.URL + "/healthz"); err != nil {
			return
		}
	}
}
