package main

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"os"
	"strings"

	bkosmi "github.com/42wim/matterbridge/bridge/kosmi"
	"github.com/sirupsen/logrus"
)

func main() {
	if len(os.Args) < 3 {
		fmt.Println("Usage: compare-auth <email> <password>")
		fmt.Println("")
		fmt.Println("This script will:")
		fmt.Println("1. Get an anonymous token")
		fmt.Println("2. Get an authenticated token via browser")
		fmt.Println("3. Decode and compare both JWT tokens")
		fmt.Println("4. Show what's different")
		os.Exit(1)
	}

	email := os.Args[1]
	password := os.Args[2]

	// Set up logging
	log := logrus.New()
	log.SetLevel(logrus.InfoLevel)
	entry := logrus.NewEntry(log)

	fmt.Println(strings.Repeat("=", 80))
	fmt.Println("COMPARING ANONYMOUS vs AUTHENTICATED TOKENS")
	fmt.Println(strings.Repeat("=", 80))
	fmt.Println()

	// Get anonymous token
	fmt.Println("📝 Step 1: Getting anonymous token...")
	client := bkosmi.NewGraphQLWSClient("https://app.kosmi.io/room/@test", "@test", entry)
	anonToken, err := client.GetAnonymousTokenForTest()
	if err != nil {
		fmt.Printf("❌ Failed to get anonymous token: %v\n", err)
		os.Exit(1)
	}
	fmt.Printf("✅ Anonymous token obtained (length: %d)\n", len(anonToken))
	fmt.Println()

	// Get authenticated token
	fmt.Println("📝 Step 2: Getting authenticated token via browser...")
	browserAuth := bkosmi.NewBrowserAuthManager(email, password, entry)
	authToken, err := browserAuth.GetToken()
	if err != nil {
		fmt.Printf("❌ Failed to get authenticated token: %v\n", err)
		os.Exit(1)
	}
	fmt.Printf("✅ Authenticated token obtained (length: %d)\n", len(authToken))
	fmt.Println()

	// Decode both tokens
	fmt.Println("📝 Step 3: Decoding JWT tokens...")
	fmt.Println()

	anonClaims := decodeJWT(anonToken)
	authClaims := decodeJWT(authToken)

	fmt.Println("ANONYMOUS TOKEN:")
	fmt.Println(strings.Repeat("=", 80))
	printClaims(anonClaims)
	fmt.Println()

	fmt.Println("AUTHENTICATED TOKEN:")
	fmt.Println(strings.Repeat("=", 80))
	printClaims(authClaims)
	fmt.Println()

	// Compare
	fmt.Println("DIFFERENCES:")
	fmt.Println(strings.Repeat("=", 80))
	compareClaims(anonClaims, authClaims)
	fmt.Println()

	fmt.Println("📝 Step 4: Testing connection with both tokens...")
	fmt.Println()
	
	// We can't easily test the actual connection here, but we've shown the token differences
	fmt.Println("✅ Analysis complete!")
	fmt.Println()
	fmt.Println("RECOMMENDATION:")
	fmt.Println("If the authenticated token has a different 'sub' (user ID), that user")
	fmt.Println("might not have the same permissions or profile as the anonymous user.")
}

func decodeJWT(token string) map[string]interface{} {
	parts := strings.Split(token, ".")
	if len(parts) != 3 {
		return map[string]interface{}{"error": "invalid JWT format"}
	}

	// Decode payload
	payload := parts[1]
	// Add padding if needed
	switch len(payload) % 4 {
	case 2:
		payload += "=="
	case 3:
		payload += "="
	}

	// Replace URL-safe characters
	payload = strings.ReplaceAll(payload, "-", "+")
	payload = strings.ReplaceAll(payload, "_", "/")

	decoded, err := base64.StdEncoding.DecodeString(payload)
	if err != nil {
		return map[string]interface{}{"error": fmt.Sprintf("decode error: %v", err)}
	}

	var claims map[string]interface{}
	if err := json.Unmarshal(decoded, &claims); err != nil {
		return map[string]interface{}{"error": fmt.Sprintf("parse error: %v", err)}
	}

	return claims
}

func printClaims(claims map[string]interface{}) {
	keys := []string{"sub", "aud", "iss", "typ", "iat", "exp", "nbf", "jti"}
	for _, key := range keys {
		if val, ok := claims[key]; ok {
			fmt.Printf("  %-10s: %v\n", key, val)
		}
	}
}

func compareClaims(anon, auth map[string]interface{}) {
	allKeys := make(map[string]bool)
	for k := range anon {
		allKeys[k] = true
	}
	for k := range auth {
		allKeys[k] = true
	}

	different := false
	for key := range allKeys {
		anonVal := anon[key]
		authVal := auth[key]

		if fmt.Sprintf("%v", anonVal) != fmt.Sprintf("%v", authVal) {
			different = true
			fmt.Printf("  %-10s: ANON=%v  AUTH=%v\n", key, anonVal, authVal)
		}
	}

	if !different {
		fmt.Println("  (No differences found - tokens are essentially the same)")
	}
}

