package main

import (
	"encoding/json"
	"fmt"
	"log/slog"
	"net/http"
	"os"
	"time"

	"github.com/0xArch3r/chips"
	"github.com/google/uuid"
	"github.com/joho/godotenv"
)

func checkExpiration(tokenObj *chips.TokenObject) error {
	if tokenObj.Settings == nil {
		return fmt.Errorf("token settings are nil")
	}

	expiration, ok := tokenObj.Settings["expiration"].(string)
	if !ok {
		return fmt.Errorf("expiration not found in token settings")
	}

	exp_time, err := time.Parse(time.RFC3339, expiration)
	if err != nil {
		return fmt.Errorf("failed to parse expiration time: %w", err)
	}

	if exp_time.Before(time.Now()) {
		return fmt.Errorf("token has expired")
	}

	return nil
}

func main() {
	godotenv.Load()

	handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
		Level: slog.LevelDebug, // Set the desired log level here
	})

	// Create a new logger with the configured handler
	logger := slog.New(handler)

	slog.SetDefault(logger)

	staticDir := http.Dir("./static")

	// Create a FileServer handler that serves files from the specified directory.
	fileServer := http.FileServer(staticDir)

	chips := chips.New(chips.WithLogger(logger), chips.WithSettingsFunc(checkExpiration))

	srv := http.NewServeMux()
	srv.Handle("/ws", http.HandlerFunc(chips.HandleWebSocket))

	srv.Handle("/token", http.HandlerFunc(testHandler))
	srv.Handle("/static/", http.StripPrefix("/static/", fileServer))

	srv.Handle("/remote", http.HandlerFunc(remoteHandler))

	srv_b := enableCORS(srv)

	err := http.ListenAndServe(":1234", srv_b)
	if err != nil {
		panic(err)
	}

}

func remoteHandler(w http.ResponseWriter, r *http.Request) {

	http.ServeFile(w, r, "index.html")
}

func enableCORS(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Set the Access-Control-Allow-Origin header.
		// For a single allowed origin:
		// w.Header().Set("Access-Control-Allow-Origin", "https://your-allowed-domain.com")

		// For multiple allowed origins (dynamic checking):
		allowedOrigins := map[string]bool{
			"http://localhost:5173": true,
			"http://localhost:3000": true,
		}
		origin := r.Header.Get("Origin")
		if allowedOrigins[origin] {
			w.Header().Set("Access-Control-Allow-Origin", origin)
		} else {
			// Optionally, handle requests from disallowed origins (e.g., return an error)
			// w.WriteHeader(http.StatusForbidden)
			// return
		}

		// Set other necessary CORS headers
		w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
		w.Header().Set("Access-Control-Allow-Credentials", "true") // If supporting credentials

		// Handle preflight requests (OPTIONS method)
		if r.Method == "OPTIONS" {
			w.WriteHeader(http.StatusOK)
			return
		}

		// Call the next handler in the chain
		next.ServeHTTP(w, r)
	})
}

func testHandler(w http.ResponseWriter, r *http.Request) {
	t := time.Now().Add(5 * time.Minute)

	tokenObj := &chips.TokenObject{
		ConnType: "rdp",
		Id:       uuid.New().String(),
		Settings: map[string]interface{}{
			"username":    "administrator",
			"password":    "password",
			"hostname":    "localhost",
			"security":    "nla",
			"ignore-cert": true,
			"expiration":  t.Format(time.RFC3339),
		},
	}

	fmt.Println("t:", t.Format(time.RFC3339))

	b, err := json.Marshal(tokenObj)
	if err != nil {
		http.Error(w, "Failed to marshal token object", http.StatusInternalServerError)
		return
	}

	s, err := chips.EncryptToken(string(b))
	if err != nil {
		slog.Error("Failed to encrypt token", "err", err)
		http.Error(w, "Failed to encrypt token", http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "application/json")
	w.Write([]byte(fmt.Sprintf(`{ "token": "%s"  }`, s)))
}
