package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

type HAR struct {
	Log struct {
		Entries []struct {
			Request struct {
				Method string `json:"method"`
				URL    string `json:"url"`
			} `json:"request"`
			WebSocketMessages []struct {
				Type string `json:"type"`
				Data string `json:"data"`
				Time float64 `json:"time"`
			} `json:"_webSocketMessages"`
		} `json:"entries"`
	} `json:"log"`
}

type WSMessage struct {
	ID      string                 `json:"id"`
	Type    string                 `json:"type"`
	Payload map[string]interface{} `json:"payload"`
}

func main() {
	if len(os.Args) < 2 {
		log.Fatal("Usage: parse-har <har-file>")
	}

	data, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}

	var har HAR
	if err := json.Unmarshal(data, &har); err != nil {
		log.Fatal(err)
	}

	// First pass: collect all responses
	responses := make(map[string]bool) // ID -> has data
	for _, entry := range har.Log.Entries {
		for _, wsMsg := range entry.WebSocketMessages {
			if wsMsg.Type != "receive" {
				continue
			}

			var msg WSMessage
			if err := json.Unmarshal([]byte(wsMsg.Data), &msg); err != nil {
				continue
			}

			if msg.Type == "next" {
				// Check if payload has data
				if data, ok := msg.Payload["data"].(map[string]interface{}); ok && len(data) > 0 {
					responses[msg.ID] = true
				}
			}
		}
	}

	fmt.Println("=== WebSocket Operations (in order) ===\n")

	msgCount := 0
	for _, entry := range har.Log.Entries {
		for _, wsMsg := range entry.WebSocketMessages {
			if wsMsg.Type != "send" {
				continue
			}

			var msg WSMessage
			if err := json.Unmarshal([]byte(wsMsg.Data), &msg); err != nil {
				continue
			}

			if msg.Type == "connection_init" {
				fmt.Printf("[%d] connection_init\n", msgCount)
				msgCount++
				continue
			}

			if msg.Type == "subscribe" {
				opName := ""
				query := ""
				variables := map[string]interface{}{}
				extensions := map[string]interface{}{}

				if payload, ok := msg.Payload["operationName"].(string); ok {
					opName = payload
				}
				if q, ok := msg.Payload["query"].(string); ok {
					query = q
				}
				if v, ok := msg.Payload["variables"].(map[string]interface{}); ok {
					variables = v
				}
				if e, ok := msg.Payload["extensions"].(map[string]interface{}); ok {
					extensions = e
				}

				hasResponse := ""
				if responses[msg.ID] {
					hasResponse = " ✅ GOT DATA"
				} else {
					hasResponse = " ❌ NO DATA"
				}
				fmt.Printf("[%d] %s (ID: %s)%s\n", msgCount, opName, msg.ID, hasResponse)
				
				// Show query type
				if strings.Contains(query, "mutation") {
					fmt.Printf("    Type: MUTATION\n")
				} else if strings.Contains(query, "subscription") {
					fmt.Printf("    Type: SUBSCRIPTION\n")
				} else if strings.Contains(query, "query") {
					fmt.Printf("    Type: QUERY\n")
				}

				// Show variables
				if len(variables) > 0 {
					fmt.Printf("    Variables: %v\n", variables)
				}

				// Show extensions
				if len(extensions) > 0 {
					fmt.Printf("    Extensions: %v\n", extensions)
				}

				fmt.Println()
				msgCount++
			}
		}
	}

	fmt.Printf("\nTotal operations: %d\n", msgCount)
}

