package translate

import (
	"context"
	"log/slog"
	"net/http"
	"strings"
)

func (s *Service) Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		path := r.URL.Path
		segments := []string{}
		for segment := range strings.SplitSeq(path, "/") {
			if segment != "" {
				segments = append(segments, segment)
			}
		}

		// 1. Check if the first segment is a supported language.
		var currentLang string
		if len(segments) >= 1 {
			potentialLang := segments[0]
			if _, ok := s.translations[potentialLang]; ok {
				currentLang = potentialLang
			}
		}

		if currentLang != "" {
			// CASE A: Language is present in the URL.
			// Remove the language from the path so the router sees the clean path.
			newPath := "/" + strings.Join(segments[1:], "/")
			if newPath == "" {
				newPath = "/"
			}

			// Update the request URL path.
			r.URL.Path = newPath

			// Inject translator into context.
			ctx := context.WithValue(r.Context(), serviceKey, s)
			ctx = context.WithValue(ctx, langKey, currentLang)

			// Pass control to the next handler with the modified request.
			next.ServeHTTP(w, r.WithContext(ctx))
			return
		}

		// CASE B: Language is NOT in the URL.
		// Detect best language from Accept-Language header.
		detectedLang := s.detectLanguage(r.Header.Get("Accept-Language"))

		// Redirect to the URL with the language prefix.
		targetURL := "/" + detectedLang + path
		if r.URL.RawQuery != "" {
			targetURL += "?" + r.URL.RawQuery
		}

		slog.Debug("redirecting for translated url", "old", path, "new", targetURL)
		http.Redirect(w, r, targetURL, http.StatusFound)
	})
}

// detectLanguage parses the Accept-Language header and returns the best matching supported language.
func (s *Service) detectLanguage(header string) string {
	if header == "" {
		return s.defaultLanguage
	}

	// Simple parser for Accept-Language: en-US,en;q=0.9,de;q=0.8
	// We only care about the first match for simplicity here, or we could rank them.
	parts := strings.Split(header, ",")
	for _, part := range parts {
		tag := strings.Split(strings.TrimSpace(part), ";")[0]
		// Check for exact match (e.g., "en-US")
		if _, ok := s.translations[tag]; ok {
			return tag
		}
		// Check for base match (e.g., "en" from "en-US")
		base := strings.Split(tag, "-")[0]
		if _, ok := s.translations[base]; ok {
			return base
		}
	}

	return s.defaultLanguage
}
