// Package server provides HTTP server functionality for the sketch loop.
package server

import (
	"context"
	"crypto/rand"
	"embed"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"html"
	"html/template"
	"io"
	"log/slog"
	"net/http"
	"net/http/httputil"
	"net/http/pprof"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime/debug"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/creack/pty"
	"sketch.dev/claudetool/browse"
	"sketch.dev/embedded"
	"sketch.dev/git_tools"
	"sketch.dev/llm"
	"sketch.dev/llm/conversation"
	"sketch.dev/loop"
	"sketch.dev/loop/server/gzhandler"
)

//go:embed templates/*
var templateFS embed.FS

// Remote represents a git remote with display information.
type Remote struct {
	Name        string `json:"name"`
	URL         string `json:"url"`
	DisplayName string `json:"display_name"`
	IsGitHub    bool   `json:"is_github"`
}

// GitPushInfoResponse represents the response from /git/pushinfo
type GitPushInfoResponse struct {
	Hash    string   `json:"hash"`
	Subject string   `json:"subject"`
	Remotes []Remote `json:"remotes"`
}

// GitPushRequest represents the request body for /git/push
type GitPushRequest struct {
	Remote string `json:"remote"`
	Branch string `json:"branch"`
	Commit string `json:"commit"`
	DryRun bool   `json:"dry_run"`
	Force  bool   `json:"force"`
}

// GitPushResponse represents the response from /git/push
type GitPushResponse struct {
	Success bool   `json:"success"`
	Output  string `json:"output"`
	DryRun  bool   `json:"dry_run"`
	Error   string `json:"error,omitempty"`
}

// httpError logs the error and sends an HTTP error response
func httpError(w http.ResponseWriter, r *http.Request, message string, code int) {
	slog.Error("HTTP error", "method", r.Method, "path", r.URL.Path, "message", message, "code", code)
	http.Error(w, message, code)
}

// isGitHubURL checks if a URL is a GitHub URL
func isGitHubURL(url string) bool {
	return strings.Contains(url, "github.com")
}

// simplifyGitHubURL simplifies GitHub URLs to "owner/repo" format
// and also returns whether it's a github url
func simplifyGitHubURL(url string) (string, bool) {
	// Handle GitHub URLs in various formats
	if strings.Contains(url, "github.com") {
		// Extract owner/repo from URLs like:
		// https://github.com/owner/repo.git
		// git@github.com:owner/repo.git
		// https://github.com/owner/repo
		re := regexp.MustCompile(`github\.com[:/]([^/]+/[^/]+?)(?:\.git)?/?$`)
		if matches := re.FindStringSubmatch(url); len(matches) > 1 {
			return matches[1], true
		}
	}
	return url, false
}

// terminalSession represents a terminal session with its PTY and the event channel
type terminalSession struct {
	pty                *os.File
	eventsClients      map[chan []byte]bool
	lastEventClientID  int
	eventsClientsMutex sync.Mutex
	cmd                *exec.Cmd
}

// TerminalMessage represents a message sent from the client for terminal resize events
type TerminalMessage struct {
	Type string `json:"type"`
	Cols uint16 `json:"cols"`
	Rows uint16 `json:"rows"`
}

// TerminalResponse represents the response for a new terminal creation
type TerminalResponse struct {
	SessionID string `json:"sessionId"`
}

// TodoItem represents a single todo item for task management
type TodoItem struct {
	ID     string `json:"id"`
	Task   string `json:"task"`
	Status string `json:"status"` // queued, in-progress, completed
}

// TodoList represents a collection of todo items
type TodoList struct {
	Items []TodoItem `json:"items"`
}

type State struct {
	// null or 1: "old"
	// 2: supports SSE for message updates
	StateVersion         int                           `json:"state_version"`
	MessageCount         int                           `json:"message_count"`
	TotalUsage           *conversation.CumulativeUsage `json:"total_usage,omitempty"`
	InitialCommit        string                        `json:"initial_commit"`
	Slug                 string                        `json:"slug,omitempty"`
	BranchName           string                        `json:"branch_name,omitempty"`
	BranchPrefix         string                        `json:"branch_prefix,omitempty"`
	Hostname             string                        `json:"hostname"`    // deprecated
	WorkingDir           string                        `json:"working_dir"` // deprecated
	OS                   string                        `json:"os"`          // deprecated
	GitOrigin            string                        `json:"git_origin,omitempty"`
	GitUsername          string                        `json:"git_username,omitempty"`
	OutstandingLLMCalls  int                           `json:"outstanding_llm_calls"`
	OutstandingToolCalls []string                      `json:"outstanding_tool_calls"`
	SessionID            string                        `json:"session_id"`
	SSHAvailable         bool                          `json:"ssh_available"`
	SSHError             string                        `json:"ssh_error,omitempty"`
	InContainer          bool                          `json:"in_container"`
	FirstMessageIndex    int                           `json:"first_message_index"`
	AgentState           string                        `json:"agent_state,omitempty"`
	OutsideHostname      string                        `json:"outside_hostname,omitempty"`
	InsideHostname       string                        `json:"inside_hostname,omitempty"`
	OutsideOS            string                        `json:"outside_os,omitempty"`
	InsideOS             string                        `json:"inside_os,omitempty"`
	OutsideWorkingDir    string                        `json:"outside_working_dir,omitempty"`
	InsideWorkingDir     string                        `json:"inside_working_dir,omitempty"`
	TodoContent          string                        `json:"todo_content,omitempty"`          // Contains todo list JSON data
	SkabandAddr          string                        `json:"skaband_addr,omitempty"`          // URL of the skaband server
	LinkToGitHub         bool                          `json:"link_to_github,omitempty"`        // Enable GitHub branch linking in UI
	SSHConnectionString  string                        `json:"ssh_connection_string,omitempty"` // SSH connection string for container
	DiffLinesAdded       int                           `json:"diff_lines_added"`                // Lines added from sketch-base to HEAD
	DiffLinesRemoved     int                           `json:"diff_lines_removed"`              // Lines removed from sketch-base to HEAD
	OpenPorts            []Port                        `json:"open_ports,omitempty"`            // Currently open TCP ports
	TokenContextWindow   int                           `json:"token_context_window,omitempty"`
	Model                string                        `json:"model,omitempty"` // Name of the model being used
	SessionEnded         bool                          `json:"session_ended,omitempty"`
	CanSendMessages      bool                          `json:"can_send_messages,omitempty"`
	EndedAt              time.Time                     `json:"ended_at,omitempty"`
}

// Port represents an open TCP port
type Port struct {
	Proto   string `json:"proto"`   // "tcp" or "udp"
	Port    uint16 `json:"port"`    // port number
	Process string `json:"process"` // optional process name
	Pid     int    `json:"pid"`     // process ID
}

type InitRequest struct {
	// Passed to agent so that the URL it prints in the termui prompt is correct (when skaband is not used)
	HostAddr string `json:"host_addr"`

	// POST /init will start the SSH server with these configs
	SSHAuthorizedKeys  []byte `json:"ssh_authorized_keys"`
	SSHServerIdentity  []byte `json:"ssh_server_identity"`
	SSHContainerCAKey  []byte `json:"ssh_container_ca_key"`
	SSHHostCertificate []byte `json:"ssh_host_certificate"`
	SSHAvailable       bool   `json:"ssh_available"`
	SSHError           string `json:"ssh_error,omitempty"`
}

// Server serves sketch HTTP. Server implements http.Handler.
type Server struct {
	mux      *http.ServeMux
	agent    loop.CodingAgent
	hostname string
	logFile  *os.File
	// Mutex to protect terminalSessions
	ptyMutex         sync.Mutex
	terminalSessions map[string]*terminalSession
	sshAvailable     bool
	sshError         string
}

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Check if Host header matches "p<port>.localhost" pattern and proxy to that port
	if port := s.ParsePortProxyHost(r.Host); port != "" {
		s.proxyToPort(w, r, port)
		return
	}

	s.mux.ServeHTTP(w, r)
}

// ParsePortProxyHost checks if host matches "p<port>.localhost" pattern and returns the port
func (s *Server) ParsePortProxyHost(host string) string {
	// Remove port suffix if present (e.g., "p8000.localhost:8080" -> "p8000.localhost")
	hostname := host
	if idx := strings.LastIndex(host, ":"); idx > 0 {
		hostname = host[:idx]
	}

	// Check if hostname matches p<port>.localhost pattern
	if strings.HasSuffix(hostname, ".localhost") {
		prefix := strings.TrimSuffix(hostname, ".localhost")
		if strings.HasPrefix(prefix, "p") && len(prefix) > 1 {
			port := prefix[1:] // Remove 'p' prefix
			// Basic validation - port should be numeric and in valid range
			if portNum, err := strconv.Atoi(port); err == nil && portNum > 0 && portNum <= 65535 {
				return port
			}
		}
	}

	return ""
}

// proxyToPort proxies the request to localhost:<port>
func (s *Server) proxyToPort(w http.ResponseWriter, r *http.Request, port string) {
	// Create a reverse proxy to localhost:<port>
	target, err := url.Parse(fmt.Sprintf("http://localhost:%s", port))
	if err != nil {
		httpError(w, r, "Failed to parse proxy target", http.StatusInternalServerError)
		return
	}

	proxy := httputil.NewSingleHostReverseProxy(target)

	// Customize the Director to modify the request
	originalDirector := proxy.Director
	proxy.Director = func(req *http.Request) {
		originalDirector(req)
		// Set the target host
		req.URL.Host = target.Host
		req.URL.Scheme = target.Scheme
		req.Host = target.Host
	}

	// Handle proxy errors
	proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
		slog.Error("Proxy error", "error", err, "target", target.String(), "port", port)
		httpError(w, r, "Proxy error: "+err.Error(), http.StatusBadGateway)
	}

	proxy.ServeHTTP(w, r)
}

// New creates a new HTTP server.
func New(agent loop.CodingAgent, logFile *os.File) (*Server, error) {
	s := &Server{
		mux:              http.NewServeMux(),
		agent:            agent,
		hostname:         getHostname(),
		logFile:          logFile,
		terminalSessions: make(map[string]*terminalSession),
		sshAvailable:     false,
		sshError:         "",
	}

	s.mux.HandleFunc("/stream", s.handleSSEStream)

	// Git tool endpoints
	s.mux.HandleFunc("/git/rawdiff", s.handleGitRawDiff)
	s.mux.HandleFunc("/git/show", s.handleGitShow)
	s.mux.HandleFunc("/git/cat", s.handleGitCat)
	s.mux.HandleFunc("/git/save", s.handleGitSave)
	s.mux.HandleFunc("/git/recentlog", s.handleGitRecentLog)
	s.mux.HandleFunc("/git/untracked", s.handleGitUntracked)

	s.mux.HandleFunc("/diff", func(w http.ResponseWriter, r *http.Request) {
		// Check if a specific commit hash was requested
		commit := r.URL.Query().Get("commit")

		// Get the diff, optionally for a specific commit
		var diff string
		var err error
		if commit != "" {
			// Validate the commit hash format
			if !isValidGitSHA(commit) {
				httpError(w, r, fmt.Sprintf("Invalid git commit SHA format: %s", commit), http.StatusBadRequest)
				return
			}

			diff, err = agent.Diff(&commit)
		} else {
			diff, err = agent.Diff(nil)
		}

		if err != nil {
			httpError(w, r, fmt.Sprintf("Error generating diff: %v", err), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "text/plain")
		w.Write([]byte(diff))
	})

	// Handler for initialization called by host sketch binary when inside docker.
	s.mux.HandleFunc("/init", func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if err := recover(); err != nil {
				slog.ErrorContext(r.Context(), "/init panic", slog.Any("recovered_err", err))

				// Return an error response to the client
				httpError(w, r, fmt.Sprintf("panic: %v\n", err), http.StatusInternalServerError)
			}
		}()

		if r.Method != "POST" {
			httpError(w, r, "POST required", http.StatusBadRequest)
			return
		}

		body, err := io.ReadAll(r.Body)
		r.Body.Close()
		if err != nil {
			httpError(w, r, "failed to read request body: "+err.Error(), http.StatusBadRequest)
			return
		}

		m := &InitRequest{}
		if err := json.Unmarshal(body, m); err != nil {
			httpError(w, r, "bad request body: "+err.Error(), http.StatusBadRequest)
			return
		}

		// Store SSH availability info
		s.sshAvailable = m.SSHAvailable
		s.sshError = m.SSHError

		// Start the SSH server if the init request included ssh keys.
		if len(m.SSHAuthorizedKeys) > 0 && len(m.SSHServerIdentity) > 0 {
			go func() {
				ctx := context.Background()
				if err := s.ServeSSH(ctx, m.SSHServerIdentity, m.SSHAuthorizedKeys, m.SSHContainerCAKey, m.SSHHostCertificate); err != nil {
					slog.ErrorContext(r.Context(), "/init ServeSSH", slog.String("err", err.Error()))
					// Update SSH error if server fails to start
					s.sshAvailable = false
					s.sshError = err.Error()
				}
			}()
		}

		ini := loop.AgentInit{
			InDocker: true,
			HostAddr: m.HostAddr,
		}
		if err := agent.Init(ini); err != nil {
			httpError(w, r, "init failed: "+err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		io.WriteString(w, "{}\n")
	})

	// Handler for /messages?start=N&end=M (start/end are optional)
	s.mux.HandleFunc("/messages", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		// Extract query parameters for range
		var start, end int
		var err error

		currentCount := agent.MessageCount()

		startParam := r.URL.Query().Get("start")
		if startParam != "" {
			start, err = strconv.Atoi(startParam)
			if err != nil {
				httpError(w, r, "Invalid 'start' parameter", http.StatusBadRequest)
				return
			}
		}

		endParam := r.URL.Query().Get("end")
		if endParam != "" {
			end, err = strconv.Atoi(endParam)
			if err != nil {
				httpError(w, r, "Invalid 'end' parameter", http.StatusBadRequest)
				return
			}
		} else {
			end = currentCount
		}

		if start < 0 || start > end || end > currentCount {
			httpError(w, r, fmt.Sprintf("Invalid range: start %d end %d currentCount %d", start, end, currentCount), http.StatusBadRequest)
			return
		}

		start = max(0, start)
		end = min(agent.MessageCount(), end)
		messages := agent.Messages(start, end)

		// Create a JSON encoder with indentation for pretty-printing
		encoder := json.NewEncoder(w)
		encoder.SetIndent("", "  ") // Two spaces for each indentation level

		err = encoder.Encode(messages)
		if err != nil {
			httpError(w, r, err.Error(), http.StatusInternalServerError)
		}
	})

	// Handler for /debug/logs - displays the contents of the log file
	s.mux.HandleFunc("/debug/logs", func(w http.ResponseWriter, r *http.Request) {
		if s.logFile == nil {
			httpError(w, r, "log file not set", http.StatusNotFound)
			return
		}
		logContents, err := os.ReadFile(s.logFile.Name())
		if err != nil {
			httpError(w, r, "error reading log file: "+err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		fmt.Fprintf(w, "<!DOCTYPE html>\n<html>\n<head>\n<title>Sketchy Log File</title>\n</head>\n<body>\n")
		fmt.Fprintf(w, "<pre>%s</pre>\n", html.EscapeString(string(logContents)))
		fmt.Fprintf(w, "</body>\n</html>")
	})

	// Handler for /download - downloads both messages and status as a JSON file
	s.mux.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) {
		// Set headers for file download
		w.Header().Set("Content-Type", "application/octet-stream")

		// Generate filename with format: sketch-YYYYMMDD-HHMMSS.json
		timestamp := time.Now().Format("20060102-150405")
		filename := fmt.Sprintf("sketch-%s.json", timestamp)

		w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))

		// Get all messages
		messageCount := agent.MessageCount()
		messages := agent.Messages(0, messageCount)

		// Get status information (usage and other metadata)
		totalUsage := agent.TotalUsage()
		hostname := getHostname()
		workingDir := getWorkingDir()

		// Create a combined structure with all information
		downloadData := struct {
			Messages     []loop.AgentMessage          `json:"messages"`
			MessageCount int                          `json:"message_count"`
			TotalUsage   conversation.CumulativeUsage `json:"total_usage"`
			Hostname     string                       `json:"hostname"`
			WorkingDir   string                       `json:"working_dir"`
			DownloadTime string                       `json:"download_time"`
		}{
			Messages:     messages,
			MessageCount: messageCount,
			TotalUsage:   totalUsage,
			Hostname:     hostname,
			WorkingDir:   workingDir,
			DownloadTime: time.Now().Format(time.RFC3339),
		}

		// Marshal the JSON with indentation for better readability
		jsonData, err := json.MarshalIndent(downloadData, "", "  ")
		if err != nil {
			httpError(w, r, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Write(jsonData)
	})

	// The latter doesn't return until the number of messages has changed (from seen
	// or from when this was called.)
	s.mux.HandleFunc("/state", func(w http.ResponseWriter, r *http.Request) {
		pollParam := r.URL.Query().Get("poll")
		seenParam := r.URL.Query().Get("seen")

		// Get the client's current message count (if provided)
		clientMessageCount := -1
		var err error
		if seenParam != "" {
			clientMessageCount, err = strconv.Atoi(seenParam)
			if err != nil {
				httpError(w, r, "Invalid 'seen' parameter", http.StatusBadRequest)
				return
			}
		}

		serverMessageCount := agent.MessageCount()

		// Let lazy clients not have to specify this.
		if clientMessageCount == -1 {
			clientMessageCount = serverMessageCount
		}

		if pollParam == "true" {
			ch := make(chan string)
			go func() {
				it := agent.NewIterator(r.Context(), clientMessageCount)
				it.Next()
				close(ch)
				it.Close()
			}()
			select {
			case <-r.Context().Done():
				slog.DebugContext(r.Context(), "abandoned poll request")
				return
			case <-time.After(90 * time.Second):
				// Let the user call /state again to get the latest to limit how long our long polls hang out.
				slog.DebugContext(r.Context(), "longish poll request")
				break
			case <-ch:
				break
			}
		}

		w.Header().Set("Content-Type", "application/json")

		// Use the shared getState function
		state := s.getState()

		// Create a JSON encoder with indentation for pretty-printing
		encoder := json.NewEncoder(w)
		encoder.SetIndent("", "  ") // Two spaces for each indentation level

		err = encoder.Encode(state)
		if err != nil {
			httpError(w, r, err.Error(), http.StatusInternalServerError)
		}
	})

	s.mux.Handle("/static/", http.StripPrefix("/static/", gzhandler.New(embedded.WebUIFS())))

	// Terminal WebSocket handler
	// Terminal endpoints - predefined terminals 1-9
	// TODO: The UI doesn't actually know how to use terminals 2-9!
	s.mux.HandleFunc("/terminal/events/", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodGet {
			httpError(w, r, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}
		pathParts := strings.Split(r.URL.Path, "/")
		if len(pathParts) < 4 {
			httpError(w, r, "Invalid terminal ID", http.StatusBadRequest)
			return
		}

		sessionID := pathParts[3]
		// Validate that the terminal ID is between 1-9
		if len(sessionID) != 1 || sessionID[0] < '1' || sessionID[0] > '9' {
			httpError(w, r, "Terminal ID must be between 1 and 9", http.StatusBadRequest)
			return
		}

		s.handleTerminalEvents(w, r, sessionID)
	})

	s.mux.HandleFunc("/terminal/input/", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			httpError(w, r, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}
		pathParts := strings.Split(r.URL.Path, "/")
		if len(pathParts) < 4 {
			httpError(w, r, "Invalid terminal ID", http.StatusBadRequest)
			return
		}
		sessionID := pathParts[3]
		s.handleTerminalInput(w, r, sessionID)
	})

	// Handler for interface selection via URL parameters (?m for mobile)
	s.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		webuiFS := embedded.WebUIFS()
		appShell := "sketch-app-shell.html"
		if r.URL.Query().Has("m") {
			appShell = "mobile-app-shell.html"
		}
		http.ServeFileFS(w, r, webuiFS, appShell)
	})

	// Handler for /commit-description - returns the description of a git commit
	s.mux.HandleFunc("/commit-description", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodGet {
			httpError(w, r, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}

		// Get the revision parameter
		revision := r.URL.Query().Get("revision")
		if revision == "" {
			httpError(w, r, "Missing revision parameter", http.StatusBadRequest)
			return
		}

		// Run git command to get commit description
		cmd := exec.Command("git", "log", "--oneline", "--decorate", "-n", "1", revision)
		// Use the working directory from the agent
		cmd.Dir = s.agent.WorkingDir()

		output, err := cmd.CombinedOutput()
		if err != nil {
			httpError(w, r, "Failed to get commit description: "+err.Error(), http.StatusInternalServerError)
			return
		}

		// Prepare the response
		resp := map[string]string{
			"description": strings.TrimSpace(string(output)),
		}

		w.Header().Set("Content-Type", "application/json")
		if err := json.NewEncoder(w).Encode(resp); err != nil {
			slog.ErrorContext(r.Context(), "Error encoding commit description response", slog.Any("err", err))
		}
	})

	// Handler for /screenshot/{id} - serves screenshot images
	s.mux.HandleFunc("/screenshot/", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodGet {
			httpError(w, r, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}

		// Extract the screenshot ID from the path
		pathParts := strings.Split(r.URL.Path, "/")
		if len(pathParts) < 3 {
			httpError(w, r, "Invalid screenshot ID", http.StatusBadRequest)
			return
		}

		screenshotID := pathParts[2]

		// Validate the ID format (prevent directory traversal)
		if strings.Contains(screenshotID, "/") || strings.Contains(screenshotID, "\\") {
			httpError(w, r, "Invalid screenshot ID format", http.StatusBadRequest)
			return
		}

		// Get the screenshot file path
		filePath := browse.GetScreenshotPath(screenshotID)

		// Check if the file exists
		if _, err := os.Stat(filePath); os.IsNotExist(err) {
			httpError(w, r, "Screenshot not found", http.StatusNotFound)
			return
		}

		// Serve the file
		w.Header().Set("Content-Type", "image/png")
		w.Header().Set("Cache-Control", "max-age=3600") // Cache for an hour
		http.ServeFile(w, r, filePath)
	})

	// Handler for POST /chat
	s.mux.HandleFunc("/chat", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			httpError(w, r, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}

		// Parse the request body
		var requestBody struct {
			Message string `json:"message"`
		}

		decoder := json.NewDecoder(r.Body)
		if err := decoder.Decode(&requestBody); err != nil {
			httpError(w, r, "Invalid request body: "+err.Error(), http.StatusBadRequest)
			return
		}
		defer r.Body.Close()

		if requestBody.Message == "" {
			httpError(w, r, "Message cannot be empty", http.StatusBadRequest)
			return
		}

		agent.UserMessage(r.Context(), requestBody.Message)

		w.WriteHeader(http.StatusOK)
	})

	// Handler for POST /upload - uploads a file to /tmp
	s.mux.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			httpError(w, r, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}

		// Limit to 10MB file size
		r.Body = http.MaxBytesReader(w, r.Body, 10*1024*1024)

		// Parse the multipart form
		if err := r.ParseMultipartForm(10 * 1024 * 1024); err != nil {
			httpError(w, r, "Failed to parse form: "+err.Error(), http.StatusBadRequest)
			return
		}

		// Get the file from the multipart form
		file, handler, err := r.FormFile("file")
		if err != nil {
			httpError(w, r, "Failed to get uploaded file: "+err.Error(), http.StatusBadRequest)
			return
		}
		defer file.Close()

		// Generate a unique ID (8 random bytes converted to 16 hex chars)
		randBytes := make([]byte, 8)
		if _, err := rand.Read(randBytes); err != nil {
			httpError(w, r, "Failed to generate random filename: "+err.Error(), http.StatusInternalServerError)
			return
		}

		// Get file extension from the original filename
		ext := filepath.Ext(handler.Filename)

		// Create a unique filename in the /tmp directory
		filename := fmt.Sprintf("/tmp/sketch_file_%s%s", hex.EncodeToString(randBytes), ext)

		// Create the destination file
		destFile, err := os.Create(filename)
		if err != nil {
			httpError(w, r, "Failed to create destination file: "+err.Error(), http.StatusInternalServerError)
			return
		}
		defer destFile.Close()

		// Copy the file contents to the destination file
		if _, err := io.Copy(destFile, file); err != nil {
			httpError(w, r, "Failed to save file: "+err.Error(), http.StatusInternalServerError)
			return
		}

		// Return the path to the saved file
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(map[string]string{"path": filename})
	})

	// Handler for /git/pushinfo - returns HEAD commit and remotes for push dialog
	s.mux.HandleFunc("/git/pushinfo", s.handleGitPushInfo)

	// Handler for /git/push - handles git push operations
	s.mux.HandleFunc("/git/push", s.handleGitPush)

	// Handler for /cancel - cancels the current inner loop in progress
	s.mux.HandleFunc("/cancel", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			httpError(w, r, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}

		// Parse the request body (optional)
		var requestBody struct {
			Reason     string `json:"reason"`
			ToolCallID string `json:"tool_call_id"`
		}

		decoder := json.NewDecoder(r.Body)
		if err := decoder.Decode(&requestBody); err != nil && err != io.EOF {
			httpError(w, r, "Invalid request body: "+err.Error(), http.StatusBadRequest)
			return
		}
		defer r.Body.Close()

		cancelReason := "user requested cancellation"
		if requestBody.Reason != "" {
			cancelReason = requestBody.Reason
		}

		if requestBody.ToolCallID != "" {
			err := agent.CancelToolUse(requestBody.ToolCallID, fmt.Errorf("%s", cancelReason))
			if err != nil {
				httpError(w, r, err.Error(), http.StatusBadRequest)
				return
			}
			// Return a success response
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(map[string]string{
				"status":     "cancelled",
				"too_use_id": requestBody.ToolCallID,
				"reason":     cancelReason,
			})
			return
		}
		// Call the CancelTurn method
		agent.CancelTurn(fmt.Errorf("%s", cancelReason))
		// Return a success response
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(map[string]string{"status": "cancelled", "reason": cancelReason})
	})

	// Handler for /end - shuts down the inner sketch process
	s.mux.HandleFunc("/end", func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			httpError(w, r, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}

		// Parse the request body (optional)
		var requestBody struct {
			Reason  string `json:"reason"`
			Happy   *bool  `json:"happy,omitempty"`
			Comment string `json:"comment,omitempty"`
		}

		decoder := json.NewDecoder(r.Body)
		if err := decoder.Decode(&requestBody); err != nil && err != io.EOF {
			httpError(w, r, "Invalid request body: "+err.Error(), http.StatusBadRequest)
			return
		}
		defer r.Body.Close()

		endReason := "user requested end of session"
		if requestBody.Reason != "" {
			endReason = requestBody.Reason
		}

		// Send success response before exiting
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(map[string]string{"status": "ending", "reason": endReason})
		if f, ok := w.(http.Flusher); ok {
			f.Flush()
		}

		// Log that we're shutting down
		slog.Info("Ending session", "reason", endReason)

		// Give a brief moment for the response to be sent before exiting
		go func() {
			time.Sleep(100 * time.Millisecond)
			os.Exit(0)
		}()
	})

	debugMux := initDebugMux(agent)
	s.mux.HandleFunc("/debug/", func(w http.ResponseWriter, r *http.Request) {
		debugMux.ServeHTTP(w, r)
	})

	return s, nil
}

// Utility functions
func getHostname() string {
	hostname, err := os.Hostname()
	if err != nil {
		return "unknown"
	}
	return hostname
}

func getWorkingDir() string {
	wd, err := os.Getwd()
	if err != nil {
		return "unknown"
	}
	return wd
}

// createTerminalSession creates a new terminal session with the given ID
func (s *Server) createTerminalSession(sessionID string) (*terminalSession, error) {
	// Start a new shell process
	shellPath := getShellPath()
	cmd := exec.Command(shellPath)

	// Get working directory from the agent if possible
	workDir := getWorkingDir()
	cmd.Dir = workDir

	// Set up environment
	cmd.Env = append(os.Environ(), "TERM=xterm-256color")

	// Start the command with a pty
	ptmx, err := pty.Start(cmd)
	if err != nil {
		slog.Error("Failed to start pty", "error", err)
		return nil, err
	}

	// Create the terminal session
	session := &terminalSession{
		pty:           ptmx,
		eventsClients: make(map[chan []byte]bool),
		cmd:           cmd,
	}

	// Start goroutine to read from pty and broadcast to all connected SSE clients
	go s.readFromPtyAndBroadcast(sessionID, session)

	return session, nil
}

// handleTerminalEvents handles SSE connections for terminal output
func (s *Server) handleTerminalEvents(w http.ResponseWriter, r *http.Request, sessionID string) {
	// Check if the session exists, if not, create it
	s.ptyMutex.Lock()
	session, exists := s.terminalSessions[sessionID]

	if !exists {
		// Create a new terminal session
		var err error
		session, err = s.createTerminalSession(sessionID)
		if err != nil {
			s.ptyMutex.Unlock()
			httpError(w, r, fmt.Sprintf("Failed to create terminal: %v", err), http.StatusInternalServerError)
			return
		}

		// Store the new session
		s.terminalSessions[sessionID] = session
	}
	s.ptyMutex.Unlock()

	// Set headers for SSE
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")
	w.Header().Set("Access-Control-Allow-Origin", "*")

	// Create a channel for this client
	events := make(chan []byte, 4096) // Buffer to prevent blocking

	// Register this client's channel
	session.eventsClientsMutex.Lock()
	clientID := session.lastEventClientID + 1
	session.lastEventClientID = clientID
	session.eventsClients[events] = true
	session.eventsClientsMutex.Unlock()

	// When the client disconnects, remove their channel
	defer func() {
		session.eventsClientsMutex.Lock()
		delete(session.eventsClients, events)
		close(events)
		session.eventsClientsMutex.Unlock()
	}()

	// Flush to send headers to client immediately
	if f, ok := w.(http.Flusher); ok {
		f.Flush()
	}

	// Send events to the client as they arrive
	for {
		select {
		case <-r.Context().Done():
			return
		case data := <-events:
			// Format as SSE with base64 encoding
			fmt.Fprintf(w, "data: %s\n\n", base64.StdEncoding.EncodeToString(data))

			// Flush the data immediately
			if f, ok := w.(http.Flusher); ok {
				f.Flush()
			}
		}
	}
}

// handleTerminalInput processes input to the terminal
func (s *Server) handleTerminalInput(w http.ResponseWriter, r *http.Request, sessionID string) {
	// Check if the session exists
	s.ptyMutex.Lock()
	session, exists := s.terminalSessions[sessionID]
	s.ptyMutex.Unlock()

	if !exists {
		httpError(w, r, "Terminal session not found", http.StatusNotFound)
		return
	}

	// Read the request body (terminal input or resize command)
	body, err := io.ReadAll(r.Body)
	if err != nil {
		httpError(w, r, "Failed to read request body", http.StatusBadRequest)
		return
	}

	// Check if it's a resize message
	if len(body) > 0 && body[0] == '{' {
		var msg TerminalMessage
		if err := json.Unmarshal(body, &msg); err == nil && msg.Type == "resize" {
			if msg.Cols > 0 && msg.Rows > 0 {
				pty.Setsize(session.pty, &pty.Winsize{
					Cols: msg.Cols,
					Rows: msg.Rows,
				})

				// Respond with success
				w.WriteHeader(http.StatusOK)
				return
			}
		}
	}

	// Regular terminal input
	_, err = session.pty.Write(body)
	if err != nil {
		slog.Error("Failed to write to pty", "error", err)
		httpError(w, r, "Failed to write to terminal", http.StatusInternalServerError)
		return
	}

	// Respond with success
	w.WriteHeader(http.StatusOK)
}

// readFromPtyAndBroadcast reads output from the PTY and broadcasts it to all connected clients
func (s *Server) readFromPtyAndBroadcast(sessionID string, session *terminalSession) {
	buf := make([]byte, 4096)
	defer func() {
		// Clean up when done
		s.ptyMutex.Lock()
		delete(s.terminalSessions, sessionID)
		s.ptyMutex.Unlock()

		// Close the PTY
		session.pty.Close()

		// Ensure process is terminated
		if session.cmd.Process != nil {
			session.cmd.Process.Kill()
		}
		session.cmd.Wait()

		// Close all client channels
		session.eventsClientsMutex.Lock()
		for ch := range session.eventsClients {
			delete(session.eventsClients, ch)
			close(ch)
		}
		session.eventsClientsMutex.Unlock()
	}()

	for {
		n, err := session.pty.Read(buf)
		if err != nil {
			if err != io.EOF {
				slog.Error("Failed to read from pty", "error", err)
			}
			break
		}

		// Make a copy of the data for each client
		data := make([]byte, n)
		copy(data, buf[:n])

		// Broadcast to all connected clients
		session.eventsClientsMutex.Lock()
		for ch := range session.eventsClients {
			// Try to send, but don't block if channel is full
			select {
			case ch <- data:
			default:
				// Channel is full, drop the message for this client
			}
		}
		session.eventsClientsMutex.Unlock()
	}
}

// getShellPath returns the path to the shell to use
func getShellPath() string {
	// Try to use the user's preferred shell
	shell := os.Getenv("SHELL")
	if shell != "" {
		return shell
	}

	// Default to bash on Unix-like systems
	if _, err := os.Stat("/bin/bash"); err == nil {
		return "/bin/bash"
	}

	// Fall back to sh
	return "/bin/sh"
}

func initDebugMux(agent loop.CodingAgent) *http.ServeMux {
	mux := http.NewServeMux()
	build := "unknown build"
	bi, ok := debug.ReadBuildInfo()
	if ok {
		build = fmt.Sprintf("%s@%v\n", bi.Path, bi.Main.Version)
	}
	mux.HandleFunc("GET /debug/{$}", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		// TODO: pid is not as useful as "outside pid"
		fmt.Fprintf(w, `<!doctype html>
			<html><head><title>sketch debug</title></head><body>
			<h1>sketch debug</h1>
			pid %d<br>
			build %s<br>
			<ul>
				<li><a href="pprof/cmdline">pprof/cmdline</a></li>
				<li><a href="pprof/profile">pprof/profile</a></li>
				<li><a href="pprof/symbol">pprof/symbol</a></li>
				<li><a href="pprof/trace">pprof/trace</a></li>
				<li><a href="pprof/goroutine?debug=1">pprof/goroutine?debug=1</a></li>
				<li><a href="conversation-history">conversation-history</a></li>
				<li><a href="tools">tools</a></li>
				<li><a href="system-prompt">system-prompt</a></li>
				<li><a href="logs">logs</a></li>
			</ul>
			</body>
			</html>
			`, os.Getpid(), build)
	})
	mux.HandleFunc("GET /debug/pprof/", pprof.Index)
	mux.HandleFunc("GET /debug/pprof/cmdline", pprof.Cmdline)
	mux.HandleFunc("GET /debug/pprof/profile", pprof.Profile)
	mux.HandleFunc("GET /debug/pprof/symbol", pprof.Symbol)
	mux.HandleFunc("GET /debug/pprof/trace", pprof.Trace)

	// Add conversation history debug handler
	mux.HandleFunc("GET /debug/conversation-history", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		// Use type assertion to access the GetConvo method
		type ConvoProvider interface {
			GetConvo() loop.ConvoInterface
		}

		if convoProvider, ok := agent.(ConvoProvider); ok {
			// Call the DebugJSON method to get the conversation history
			historyJSON, err := convoProvider.GetConvo().DebugJSON()
			if err != nil {
				httpError(w, r, fmt.Sprintf("Error getting conversation history: %v", err), http.StatusInternalServerError)
				return
			}

			// Write the JSON response
			w.Write(historyJSON)
		} else {
			httpError(w, r, "Agent does not support conversation history debugging", http.StatusNotImplemented)
		}
	})

	// Add tools debug handler
	mux.HandleFunc("GET /debug/tools", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html; charset=utf-8")

		// Try to get the conversation and its tools
		type ConvoProvider interface {
			GetConvo() loop.ConvoInterface
		}

		convoProvider, ok := agent.(ConvoProvider)
		if !ok {
			http.Error(w, "Agent does not support conversation debugging", http.StatusNotImplemented)
			return
		}

		convoInterface := convoProvider.GetConvo()
		convo, ok := convoInterface.(*conversation.Convo)
		if !ok {
			http.Error(w, "Unable to access conversation tools", http.StatusInternalServerError)
			return
		}

		// Render the tools debug page
		renderToolsDebugPage(w, convo.Tools)
	})

	// Add system prompt debug handler
	mux.HandleFunc("GET /debug/system-prompt", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html; charset=utf-8")

		// Try to get the conversation and its system prompt
		type ConvoProvider interface {
			GetConvo() loop.ConvoInterface
		}

		convoProvider, ok := agent.(ConvoProvider)
		if !ok {
			http.Error(w, "Agent does not support conversation debugging", http.StatusNotImplemented)
			return
		}

		convoInterface := convoProvider.GetConvo()
		convo, ok := convoInterface.(*conversation.Convo)
		if !ok {
			http.Error(w, "Unable to access conversation system prompt", http.StatusInternalServerError)
			return
		}

		// Render the system prompt debug page
		renderSystemPromptDebugPage(w, convo.SystemPrompt)
	})

	return mux
}

// renderToolsDebugPage renders an HTML page showing all available tools
func renderToolsDebugPage(w http.ResponseWriter, tools []*llm.Tool) {
	fmt.Fprintf(w, `<!DOCTYPE html>
<html>
<head>
	<title>Sketch Tools Debug</title>
	<style>
		body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; margin: 40px; }
		h1 { color: #333; }
		.tool { background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; padding: 20px; margin: 20px 0; }
		.tool-name { font-size: 1.2em; font-weight: bold; color: #0366d6; margin-bottom: 8px; }
		.tool-description { color: #586069; margin-bottom: 12px; }
		.tool-schema { background: #f6f8fa; border: 1px solid #d0d7de; border-radius: 4px; padding: 12px; font-family: 'SF Mono', Monaco, monospace; font-size: 12px; overflow-x: auto; }
		.tool-meta { font-size: 0.9em; color: #656d76; margin-top: 8px; }
		.summary { background: #e6f3ff; border-left: 4px solid #0366d6; padding: 16px; margin-bottom: 30px; }
	</style>
</head>
<body>
	<h1>Sketch Tools Debug</h1>
	<div class="summary">
		<strong>Total Tools Available:</strong> %d
	</div>
`, len(tools))

	for i, tool := range tools {
		fmt.Fprintf(w, `	<div class="tool">
		<div class="tool-name">%d. %s</div>
`, i+1, html.EscapeString(tool.Name))

		if tool.Description != "" {
			fmt.Fprintf(w, `		<div class="tool-description">%s</div>
`, html.EscapeString(tool.Description))
		}

		// Display schema
		if tool.InputSchema != nil {
			// Pretty print the JSON schema
			var schemaFormatted string
			if prettySchema, err := json.MarshalIndent(json.RawMessage(tool.InputSchema), "", "  "); err == nil {
				schemaFormatted = string(prettySchema)
			} else {
				schemaFormatted = string(tool.InputSchema)
			}
			fmt.Fprintf(w, `		<div class="tool-schema">%s</div>
`, html.EscapeString(schemaFormatted))
		}

		// Display metadata
		var metaParts []string
		if tool.Type != "" {
			metaParts = append(metaParts, fmt.Sprintf("Type: %s", tool.Type))
		}
		if tool.EndsTurn {
			metaParts = append(metaParts, "Ends Turn: true")
		}
		if len(metaParts) > 0 {
			fmt.Fprintf(w, `		<div class="tool-meta">%s</div>
`, html.EscapeString(strings.Join(metaParts, " | ")))
		}

		fmt.Fprintf(w, `	</div>
`)
	}

	fmt.Fprintf(w, `</body>
</html>`)
}

// SystemPromptDebugData holds the data for the system prompt debug template
type SystemPromptDebugData struct {
	SystemPrompt string
	Length       int
	Lines        int
}

// renderSystemPromptDebugPage renders an HTML page showing the system prompt
func renderSystemPromptDebugPage(w http.ResponseWriter, systemPrompt string) {
	// Calculate stats
	length := len(systemPrompt)
	lines := strings.Count(systemPrompt, "\n") + 1

	// Parse template
	tmpl, err := template.ParseFS(templateFS, "templates/system_prompt_debug.html")
	if err != nil {
		http.Error(w, "Error loading template: "+err.Error(), http.StatusInternalServerError)
		return
	}

	// Execute template
	data := SystemPromptDebugData{
		SystemPrompt: systemPrompt,
		Length:       length,
		Lines:        lines,
	}

	if err := tmpl.Execute(w, data); err != nil {
		http.Error(w, "Error executing template: "+err.Error(), http.StatusInternalServerError)
	}
}

// isValidGitSHA validates if a string looks like a valid git SHA hash.
// Git SHAs are hexadecimal strings of at least 4 characters but typically 7, 8, or 40 characters.
func isValidGitSHA(sha string) bool {
	// Git SHA must be a hexadecimal string with at least 4 characters
	if len(sha) < 4 || len(sha) > 40 {
		return false
	}

	// Check if the string only contains hexadecimal characters
	for _, char := range sha {
		if !(char >= '0' && char <= '9') && !(char >= 'a' && char <= 'f') && !(char >= 'A' && char <= 'F') {
			return false
		}
	}

	return true
}

// /stream?from=N endpoint for Server-Sent Events
func (s *Server) handleSSEStream(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")
	w.Header().Set("Access-Control-Allow-Origin", "*")

	// Extract the 'from' parameter
	fromParam := r.URL.Query().Get("from")
	var fromIndex int
	var err error
	if fromParam != "" {
		fromIndex, err = strconv.Atoi(fromParam)
		if err != nil {
			httpError(w, r, "Invalid 'from' parameter", http.StatusBadRequest)
			return
		}
	}

	// Ensure 'from' is valid
	currentCount := s.agent.MessageCount()
	if fromIndex < 0 {
		fromIndex = 0
	} else if fromIndex > currentCount {
		fromIndex = currentCount
	}

	// Send the current state immediately
	state := s.getState()

	// Create JSON encoder
	encoder := json.NewEncoder(w)

	// Send state as an event
	fmt.Fprintf(w, "event: state\n")
	fmt.Fprintf(w, "data: ")
	encoder.Encode(state)
	fmt.Fprintf(w, "\n\n")

	if f, ok := w.(http.Flusher); ok {
		f.Flush()
	}

	// Create a context for the SSE stream
	ctx := r.Context()

	// Setup heartbeat timer
	heartbeatTicker := time.NewTicker(45 * time.Second)
	defer heartbeatTicker.Stop()

	// Create a channel for messages
	messageChan := make(chan *loop.AgentMessage, 10)

	// Create a channel for state transitions
	stateChan := make(chan *loop.StateTransition, 10)

	// Start a goroutine to read messages without blocking the heartbeat
	go func() {
		// Create an iterator to receive new messages as they arrive
		iterator := s.agent.NewIterator(ctx, fromIndex) // Start from the requested index
		defer iterator.Close()
		defer close(messageChan)
		for {
			// This can block, but it's in its own goroutine
			newMessage := iterator.Next()
			if newMessage == nil {
				// No message available (likely due to context cancellation)
				slog.InfoContext(ctx, "No more messages available, ending message stream")
				return
			}

			select {
			case messageChan <- newMessage:
				// Message sent to channel
			case <-ctx.Done():
				// Context cancelled
				return
			}
		}
	}()

	// Start a goroutine to read state transitions
	go func() {
		// Create an iterator to receive state transitions
		stateIterator := s.agent.NewStateTransitionIterator(ctx)
		defer stateIterator.Close()
		defer close(stateChan)
		for {
			// This can block, but it's in its own goroutine
			newTransition := stateIterator.Next()
			if newTransition == nil {
				// No transition available (likely due to context cancellation)
				slog.InfoContext(ctx, "No more state transitions available, ending state stream")
				return
			}

			select {
			case stateChan <- newTransition:
				// Transition sent to channel
			case <-ctx.Done():
				// Context cancelled
				return
			}
		}
	}()

	// Stay connected and stream real-time updates
	for {
		select {
		case <-heartbeatTicker.C:
			// Send heartbeat event
			fmt.Fprintf(w, "event: heartbeat\n")
			fmt.Fprintf(w, "data: %d\n\n", time.Now().Unix())

			// Flush to send the heartbeat immediately
			if f, ok := w.(http.Flusher); ok {
				f.Flush()
			}

		case <-ctx.Done():
			// Client disconnected
			slog.InfoContext(ctx, "Client disconnected from SSE stream")
			return

		case _, ok := <-stateChan:
			if !ok {
				// Channel closed
				slog.InfoContext(ctx, "State transition channel closed, ending SSE stream")
				return
			}

			// Get updated state
			state = s.getState()

			// Send updated state after the state transition
			fmt.Fprintf(w, "event: state\n")
			fmt.Fprintf(w, "data: ")
			encoder.Encode(state)
			fmt.Fprintf(w, "\n\n")

			// Flush to send the state immediately
			if f, ok := w.(http.Flusher); ok {
				f.Flush()
			}

		case newMessage, ok := <-messageChan:
			if !ok {
				// Channel closed
				slog.InfoContext(ctx, "Message channel closed, ending SSE stream")
				return
			}

			// Send the new message as an event
			fmt.Fprintf(w, "event: message\n")
			fmt.Fprintf(w, "data: ")
			encoder.Encode(newMessage)
			fmt.Fprintf(w, "\n\n")

			// Get updated state
			state = s.getState()

			// Send updated state after the message
			fmt.Fprintf(w, "event: state\n")
			fmt.Fprintf(w, "data: ")
			encoder.Encode(state)
			fmt.Fprintf(w, "\n\n")

			// Flush to send the message and state immediately
			if f, ok := w.(http.Flusher); ok {
				f.Flush()
			}
		}
	}
}

// Helper function to get the current state
func (s *Server) getState() State {
	serverMessageCount := s.agent.MessageCount()
	totalUsage := s.agent.TotalUsage()

	// Get diff stats
	diffAdded, diffRemoved := s.agent.DiffStats()

	return State{
		StateVersion: 2,
		MessageCount: serverMessageCount,
		TotalUsage:   &totalUsage,
		Hostname:     s.hostname,
		WorkingDir:   getWorkingDir(),
		// TODO: Rename this field to sketch-base?
		InitialCommit:        s.agent.SketchGitBase(),
		Slug:                 s.agent.Slug(),
		BranchName:           s.agent.BranchName(),
		BranchPrefix:         s.agent.BranchPrefix(),
		OS:                   s.agent.OS(),
		OutsideHostname:      s.agent.OutsideHostname(),
		InsideHostname:       s.hostname,
		OutsideOS:            s.agent.OutsideOS(),
		InsideOS:             s.agent.OS(),
		OutsideWorkingDir:    s.agent.OutsideWorkingDir(),
		InsideWorkingDir:     getWorkingDir(),
		GitOrigin:            s.agent.GitOrigin(),
		GitUsername:          s.agent.GitUsername(),
		OutstandingLLMCalls:  s.agent.OutstandingLLMCallCount(),
		OutstandingToolCalls: s.agent.OutstandingToolCalls(),
		SessionID:            s.agent.SessionID(),
		SSHAvailable:         s.sshAvailable,
		SSHError:             s.sshError,
		InContainer:          s.agent.IsInContainer(),
		FirstMessageIndex:    s.agent.FirstMessageIndex(),
		AgentState:           s.agent.CurrentStateName(),
		TodoContent:          s.agent.CurrentTodoContent(),
		SkabandAddr:          s.agent.SkabandAddr(),
		LinkToGitHub:         s.agent.LinkToGitHub(),
		SSHConnectionString:  s.agent.SSHConnectionString(),
		DiffLinesAdded:       diffAdded,
		DiffLinesRemoved:     diffRemoved,
		OpenPorts:            s.getOpenPorts(),
		TokenContextWindow:   s.agent.TokenContextWindow(),
		Model:                s.agent.ModelName(),
	}
}

// getOpenPorts retrieves the current open ports from the agent
func (s *Server) getOpenPorts() []Port {
	ports := s.agent.GetPorts()
	if ports == nil {
		return nil
	}

	result := make([]Port, len(ports))
	for i, port := range ports {
		result[i] = Port{
			Proto:   port.Proto,
			Port:    port.Port,
			Process: port.Process,
			Pid:     port.Pid,
		}
	}
	return result
}

func (s *Server) handleGitRawDiff(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Get the git repository root directory from agent
	repoDir := s.agent.RepoRoot()

	// Parse query parameters
	query := r.URL.Query()
	commit := query.Get("commit")
	from := query.Get("from")
	to := query.Get("to")

	// If commit is specified, use commit^ and commit as from and to
	if commit != "" {
		from = commit + "^"
		to = commit
	}

	// Check if we have enough parameters
	if from == "" {
		httpError(w, r, "Missing required parameter: either 'commit' or at least 'from'", http.StatusBadRequest)
		return
	}
	// Note: 'to' can be empty to indicate working directory (unstaged changes)

	// Call the git_tools function
	diff, err := git_tools.GitRawDiff(repoDir, from, to)
	if err != nil {
		httpError(w, r, fmt.Sprintf("Error getting git diff: %v", err), http.StatusInternalServerError)
		return
	}

	// Return the result as JSON
	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(diff); err != nil {
		httpError(w, r, fmt.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError)
		return
	}
}

func (s *Server) handleGitShow(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Get the git repository root directory from agent
	repoDir := s.agent.RepoRoot()

	// Parse query parameters
	hash := r.URL.Query().Get("hash")
	if hash == "" {
		httpError(w, r, "Missing required parameter: 'hash'", http.StatusBadRequest)
		return
	}

	// Call the git_tools function
	show, err := git_tools.GitShow(repoDir, hash)
	if err != nil {
		httpError(w, r, fmt.Sprintf("Error running git show: %v", err), http.StatusInternalServerError)
		return
	}

	// Create a JSON response
	response := map[string]string{
		"hash":   hash,
		"output": show,
	}

	// Return the result as JSON
	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(response); err != nil {
		httpError(w, r, fmt.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError)
		return
	}
}

func (s *Server) handleGitRecentLog(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Get the git repository root directory and initial commit from agent
	repoDir := s.agent.RepoRoot()
	initialCommit := s.agent.SketchGitBaseRef()

	// Call the git_tools function
	log, err := git_tools.GitRecentLog(repoDir, initialCommit)
	if err != nil {
		httpError(w, r, fmt.Sprintf("Error getting git log: %v", err), http.StatusInternalServerError)
		return
	}

	// Return the result as JSON
	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(log); err != nil {
		httpError(w, r, fmt.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError)
		return
	}
}

func (s *Server) handleGitCat(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Get the git repository root directory from agent
	repoDir := s.agent.RepoRoot()

	// Parse query parameters
	query := r.URL.Query()
	path := query.Get("path")

	// Check if path is provided
	if path == "" {
		httpError(w, r, "Missing required parameter: path", http.StatusBadRequest)
		return
	}

	// Get file content using GitCat
	content, err := git_tools.GitCat(repoDir, path)
	switch {
	case err == nil:
		// continued below
	case errors.Is(err, os.ErrNotExist), strings.Contains(err.Error(), "not tracked by git"):
		w.WriteHeader(http.StatusNoContent)
		return
	default:
		httpError(w, r, fmt.Sprintf("error reading file: %v", err), http.StatusInternalServerError)
		return
	}

	// Return the content as JSON for consistency with other endpoints
	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(map[string]string{"output": content}); err != nil {
		httpError(w, r, fmt.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError)
		return
	}
}

func (s *Server) handleGitSave(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Get the git repository root directory from agent
	repoDir := s.agent.RepoRoot()

	// Parse request body
	var requestBody struct {
		Path    string `json:"path"`
		Content string `json:"content"`
	}

	if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil {
		httpError(w, r, fmt.Sprintf("Error parsing request body: %v", err), http.StatusBadRequest)
		return
	}
	defer r.Body.Close()

	// Check if path is provided
	if requestBody.Path == "" {
		httpError(w, r, "Missing required parameter: path", http.StatusBadRequest)
		return
	}

	// Save file content using GitSaveFile
	err := git_tools.GitSaveFile(repoDir, requestBody.Path, requestBody.Content)
	if err != nil {
		httpError(w, r, fmt.Sprintf("Error saving file: %v", err), http.StatusInternalServerError)
		return
	}

	// Auto-commit the changes
	err = git_tools.AutoCommitDiffViewChanges(r.Context(), repoDir, requestBody.Path)
	if err != nil {
		httpError(w, r, fmt.Sprintf("Error auto-committing changes: %v", err), http.StatusInternalServerError)
		return
	}

	// Detect git changes to push and notify user
	if err = s.agent.DetectGitChanges(r.Context()); err != nil {
		httpError(w, r, fmt.Sprintf("Error detecting git changes: %v", err), http.StatusInternalServerError)
		return
	}

	// Return simple success response
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("ok"))
}

func (s *Server) handleGitUntracked(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	repoDir := s.agent.RepoRoot()
	untrackedFiles, err := git_tools.GitGetUntrackedFiles(repoDir)
	if err != nil {
		httpError(w, r, fmt.Sprintf("Error getting untracked files: %v", err), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	response := map[string][]string{
		"untracked_files": untrackedFiles,
	}
	_ = json.NewEncoder(w).Encode(response) // can't do anything useful with errors anyway
}

// handleGitPushInfo returns the current HEAD commit info and remotes for push dialog
func (s *Server) handleGitPushInfo(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	repoDir := s.agent.RepoRoot()

	// Get the current HEAD commit hash and subject in one command
	cmd := exec.Command("git", "log", "-n", "1", "--format=%H%x00%s", "HEAD")
	cmd.Dir = repoDir
	output, err := cmd.Output()
	if err != nil {
		httpError(w, r, fmt.Sprintf("Error getting HEAD commit: %v", err), http.StatusInternalServerError)
		return
	}

	parts := strings.Split(strings.TrimSpace(string(output)), "\x00")
	if len(parts) != 2 {
		httpError(w, r, "Unexpected git log output format", http.StatusInternalServerError)
		return
	}
	hash := parts[0]
	subject := parts[1]

	// Get list of remote names
	cmd = exec.Command("git", "remote")
	cmd.Dir = repoDir
	output, err = cmd.Output()
	if err != nil {
		httpError(w, r, fmt.Sprintf("Error getting remotes: %v", err), http.StatusInternalServerError)
		return
	}

	remoteNames := strings.Fields(strings.TrimSpace(string(output)))

	remotes := make([]Remote, 0, len(remoteNames))

	// Get URL and display name for each remote
	for _, remoteName := range remoteNames {
		cmd = exec.Command("git", "remote", "get-url", remoteName)
		cmd.Dir = repoDir
		urlOutput, err := cmd.Output()
		if err != nil {
			// Skip this remote if we can't get its URL
			continue
		}
		url := strings.TrimSpace(string(urlOutput))

		// Set display name based on passthrough-upstream and remote name
		var displayName string
		var isGitHub bool
		if s.agent.PassthroughUpstream() && remoteName == "origin" {
			// For passthrough upstream, origin displays as "outside_hostname:outside_working_dir"
			displayName = fmt.Sprintf("%s:%s", s.agent.OutsideHostname(), s.agent.OutsideWorkingDir())
			isGitHub = false
		} else if remoteName == "origin" || remoteName == "upstream" {
			// Use git_origin value, simplified for GitHub URLs
			displayName, isGitHub = simplifyGitHubURL(s.agent.GitOrigin())
		} else {
			// For other remotes, use the remote URL directly
			displayName, isGitHub = simplifyGitHubURL(url)
		}

		remotes = append(remotes, Remote{
			Name:        remoteName,
			URL:         url,
			DisplayName: displayName,
			IsGitHub:    isGitHub,
		})
	}

	w.Header().Set("Content-Type", "application/json")
	response := GitPushInfoResponse{
		Hash:    hash,
		Subject: subject,
		Remotes: remotes,
	}
	_ = json.NewEncoder(w).Encode(response)
}

// handleGitPush handles git push operations
func (s *Server) handleGitPush(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Parse request body
	var requestBody GitPushRequest

	if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil {
		httpError(w, r, fmt.Sprintf("Error parsing request body: %v", err), http.StatusBadRequest)
		return
	}
	defer r.Body.Close()

	if requestBody.Remote == "" || requestBody.Branch == "" || requestBody.Commit == "" {
		httpError(w, r, "Missing required parameters: remote, branch, and commit", http.StatusBadRequest)
		return
	}

	repoDir := s.agent.RepoRoot()

	// Build the git push command
	args := []string{"push"}
	if requestBody.DryRun {
		args = append(args, "--dry-run")
	}
	if requestBody.Force {
		args = append(args, "--force")
	}

	// Determine the target refspec
	var targetRef string
	if s.agent.PassthroughUpstream() && requestBody.Remote == "upstream" {
		// Special case: upstream with passthrough-upstream pushes to refs/remotes/origin/<branch>
		targetRef = fmt.Sprintf("refs/remotes/origin/%s", requestBody.Branch)
	} else {
		// Normal case: push to refs/heads/<branch>
		targetRef = fmt.Sprintf("refs/heads/%s", requestBody.Branch)
	}

	args = append(args, requestBody.Remote, fmt.Sprintf("%s:%s", requestBody.Commit, targetRef))

	// Log the git push command being executed
	slog.InfoContext(r.Context(), "executing git push command",
		"command", "git",
		"args", args,
		"remote", requestBody.Remote,
		"branch", requestBody.Branch,
		"commit", requestBody.Commit,
		"target_ref", targetRef,
		"dry_run", requestBody.DryRun,
		"force", requestBody.Force,
		"repo_dir", repoDir)

	cmd := exec.Command("git", args...)
	cmd.Dir = repoDir
	// Ideally we want to pass an extra HTTP header so that the
	// server can know that this was likely a user initiated action
	// and not an agent-initiated action. However, git push weirdly
	// doesn't take a "-c" option, and the only handy env variable that
	// because a header is the user agent, so we abuse it...
	cmd.Env = append(os.Environ(), "GIT_HTTP_USER_AGENT=sketch-intentional-push")
	output, err := cmd.CombinedOutput()

	// Log the result of the git push command
	if err != nil {
		slog.WarnContext(r.Context(), "git push command failed",
			"error", err,
			"output", string(output),
			"args", args)
	} else {
		slog.InfoContext(r.Context(), "git push command completed successfully",
			"output", string(output),
			"args", args)
	}

	// Prepare response
	response := GitPushResponse{
		Success: err == nil,
		Output:  string(output),
		DryRun:  requestBody.DryRun,
	}

	if err != nil {
		response.Error = err.Error()
	}

	w.Header().Set("Content-Type", "application/json")
	_ = json.NewEncoder(w).Encode(response)
}
