package main

import (
	"html/template"
	"io"
	"log"
	"net/http"
)

// RequestData holds all the information we want to display about a request
type RequestData struct {
	Method      string
	URL         string
	Protocol    string
	Scheme      string
	Host        string
	Path        string
	RawQuery    string
	QueryParams map[string][]string
	Headers     map[string][]string
	Body        string
	HasQuery    bool
}

// collectRequestData extracts all relevant information from the HTTP request
func collectRequestData(r *http.Request) (*RequestData, error) {
	body, err := io.ReadAll(r.Body)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()

	bodyString := string(body)
	if len(bodyString) == 0 {
		bodyString = "(empty)"
	}

	data := &RequestData{
		Method:      r.Method,
		URL:         r.URL.String(),
		Protocol:    r.Proto,
		Scheme:      r.URL.Scheme,
		Host:        r.Host,
		Path:        r.URL.Path,
		RawQuery:    r.URL.RawQuery,
		QueryParams: r.URL.Query(),
		Headers:     r.Header,
		Body:        bodyString,
		HasQuery:    len(r.URL.Query()) > 0,
	}

	return data, nil
}

const echoTemplate = `
<div id="echo">
	<div >
		<h1>Request Echo</h1>
		
		<div >
			<h2>Request Line</h2>
			<p><span class="label">Method:</span><span class="value">{{.Method}}</span></p>
			<p><span class="label">URL:</span><span class="value">{{.URL}}</span></p>
			<p><span class="label">Protocol:</span><span class="value">{{.Protocol}}</span></p>
		</div>

		<div >
			<h2>URL Components</h2>
			<p><span class="label">Scheme:</span><span class="value">{{.Scheme}}</span></p>
			<p><span class="label">Host:</span><span class="value">{{.Host}}</span></p>
			<p><span class="label">Path:</span><span class="value">{{.Path}}</span></p>
			<p><span class="label">RawQuery:</span><span class="value">{{.RawQuery}}</span></p>
		</div>

		<div >
			<h2>Query Parameters</h2>
			{{if .HasQuery}}
				{{range $key, $values := .QueryParams}}
					{{range $values}}
						<p><span class="label">{{$key}}:</span><span class="value">{{.}}</span></p>
					{{end}}
				{{end}}
			{{else}}
				<p>No query parameters</p>
			{{end}}
		</div>

		<div >
			<h2>Headers</h2>
			<table>
				<tr>
					<th>Header</th>
					<th>Value</th>
				</tr>
				{{range $name, $values := .Headers}}
					<tr>
						<td>{{$name}}</td>
						<td>{{range $i, $v := $values}}{{if $i}}, {{end}}{{$v}}{{end}}</td>
					</tr>
				{{end}}
			</table>
		</div>

		<div >
			<h2>Body</h2>
			<pre>{{.Body}}</pre>
		</div>
	</div>
</div>
`

var tmpl *template.Template

func init() {
	var err error
	tmpl, err = template.New("echo").Parse(echoTemplate)
	if err != nil {
		log.Fatal("Error parsing template:", err)
	}
}

func echoHandler(w http.ResponseWriter, r *http.Request) {
	data, err := collectRequestData(r)
	if err != nil {
		http.Error(w, "Error reading request body", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "text/html; charset=utf-8")

	err = tmpl.Execute(w, data)
	if err != nil {
		log.Printf("Error executing template: %v", err)
		http.Error(w, "Error rendering response", http.StatusInternalServerError)
	}
}

func main() {
	http.HandleFunc("/echo", echoHandler)

	fs := http.FileServer(http.Dir("./frontend"))
	http.Handle("/", fs)

	log.Println("Starting server on http://localhost:8080")
	log.Println("Echo endpoint available at http://localhost:8080/echo")

	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}
