package handlers

import (
	"encoding/base64"
	"encoding/json"
	"log"
	"net/http"
	"strings"

	"mgit.msbls.de/m/paliad/internal/auth"
	"mgit.msbls.de/m/paliad/internal/services"
)

type linkCategory struct {
	ID     string `json:"id"`
	NameDE string `json:"nameDE"`
	NameEN string `json:"nameEN"`
}

type link struct {
	ID       string `json:"id"`
	Category string `json:"category"`
	Title    string `json:"title"`
	URL      string `json:"url"`
	DescDE   string `json:"descDE"`
	DescEN   string `json:"descEN"`
}

type linksResponse struct {
	Categories []linkCategory `json:"categories"`
	Links      []link         `json:"links"`
}

var linkCategories = []linkCategory{
	{ID: "courts", NameDE: "Gerichte & Ämter", NameEN: "Courts & Offices"},
	{ID: "recherche", NameDE: "Recherche", NameEN: "Research"},
	{ID: "upc", NameDE: "UPC", NameEN: "UPC"},
	{ID: "gesetze", NameDE: "Gesetze", NameEN: "Legislation"},
}

var curatedLinks = []link{
	// Gerichte & Ämter
	{
		ID: "upc-cms", Category: "courts",
		Title:  "UPC Case Management System",
		URL:    "https://www.unified-patent-court.org/en/registry/case-management-system",
		DescDE: "Verfahrensverwaltung des Einheitlichen Patentgerichts. Klageschriften, Schriftsätze und Verfahrensstatus.",
		DescEN: "Case management of the Unified Patent Court. Statements of claim, written pleadings, and case status.",
	},
	{
		ID: "upc-register", Category: "courts",
		Title:  "UPC Register",
		URL:    "https://www.unified-patent-court.org/en/registry",
		DescDE: "Öffentliches Register des UPC. Verfahrensdokumente und Entscheidungen.",
		DescEN: "Public register of the UPC. Case documents and decisions.",
	},
	{
		ID: "epo", Category: "courts",
		Title:  "Europäisches Patentamt (EPO)",
		URL:    "https://www.epo.org",
		DescDE: "Europäisches Patentamt. Patentanmeldungen, Recherchen und Prüfungsverfahren.",
		DescEN: "European Patent Office. Patent applications, searches, and examination procedures.",
	},
	{
		ID: "dpma", Category: "courts",
		Title:  "DPMA",
		URL:    "https://www.dpma.de",
		DescDE: "Deutsches Patent- und Markenamt. Nationale Patente, Marken und Designs.",
		DescEN: "German Patent and Trade Mark Office. National patents, trade marks, and designs.",
	},
	{
		ID: "bpatg", Category: "courts",
		Title:  "Bundespatentgericht",
		URL:    "https://www.bundespatentgericht.de",
		DescDE: "Bundespatentgericht. Nichtigkeitsverfahren und Beschwerden gegen DPMA-Entscheidungen.",
		DescEN: "Federal Patent Court. Nullity proceedings and appeals against DPMA decisions.",
	},
	{
		ID: "euipo", Category: "courts",
		Title:  "EUIPO",
		URL:    "https://euipo.europa.eu",
		DescDE: "Amt der Europäischen Union für geistiges Eigentum. EU-Marken und Gemeinschaftsgeschmacksmuster.",
		DescEN: "European Union Intellectual Property Office. EU trade marks and Community designs.",
	},

	// Recherche
	{
		ID: "espacenet", Category: "recherche",
		Title:  "Espacenet",
		URL:    "https://worldwide.espacenet.com",
		DescDE: "Weltweite Patentdatenbank des EPO. Über 150 Mio. Patentdokumente durchsuchbar.",
		DescEN: "Worldwide patent database of the EPO. Over 150 million patent documents searchable.",
	},
	{
		ID: "dpma-register", Category: "recherche",
		Title:  "DPMAregister",
		URL:    "https://register.dpma.de",
		DescDE: "Amtliches Register für deutsche Patente, Marken und Designs. Rechts- und Verfahrensstand.",
		DescEN: "Official register for German patents, trade marks, and designs. Legal and procedural status.",
	},
	{
		ID: "depatisnet", Category: "recherche",
		Title:  "DEPATISnet",
		URL:    "https://depatisnet.dpma.de",
		DescDE: "Recherchesystem des DPMA. Weltweite Patentrecherche mit Klassifikationssuche.",
		DescEN: "DPMA search system. Worldwide patent searches with classification search.",
	},
	{
		ID: "google-patents", Category: "recherche",
		Title:  "Google Patents",
		URL:    "https://patents.google.com",
		DescDE: "Google-Patentsuche. Volltextrecherche und maschinelle Übersetzung von Patentschriften.",
		DescEN: "Google patent search. Full-text search and machine translation of patent documents.",
	},
	{
		ID: "patentscope", Category: "recherche",
		Title:  "Patentscope (WIPO)",
		URL:    "https://patentscope.wipo.int",
		DescDE: "Internationale Patentdatenbank der WIPO. PCT-Anmeldungen und nationale Sammlungen.",
		DescEN: "International patent database of WIPO. PCT applications and national collections.",
	},

	// UPC
	{
		ID: "upc-rop", Category: "upc",
		Title:  "Rules of Procedure",
		URL:    "https://www.unified-patent-court.org/en/court/legal-documents/rules-of-procedure",
		DescDE: "Verfahrensordnung des Einheitlichen Patentgerichts. Vollständiger Regeltext mit Anhängen.",
		DescEN: "Rules of Procedure of the Unified Patent Court. Complete rule text with annexes.",
	},
	{
		ID: "upc-fees", Category: "upc",
		Title:  "Schedule of Fees",
		URL:    "https://www.unified-patent-court.org/en/court/legal-documents/court-fees",
		DescDE: "Gebührenordnung des UPC. Feste und streitwertabhängige Gerichtsgebühren.",
		DescEN: "UPC fee schedule. Fixed and value-based court fees.",
	},
	{
		ID: "upc-practice", Category: "upc",
		Title:  "Practice Directions",
		URL:    "https://www.unified-patent-court.org/en/court/legal-documents/practice-directions",
		DescDE: "Praxisanweisungen des UPC. Praktische Hinweise zu Verfahrensabläufen.",
		DescEN: "UPC practice directions. Practical guidance on procedural matters.",
	},
	{
		ID: "upc-website", Category: "upc",
		Title:  "UPC Website",
		URL:    "https://www.unified-patent-court.org",
		DescDE: "Offizielle Website des Einheitlichen Patentgerichts. Nachrichten, Appointments und Informationen.",
		DescEN: "Official website of the Unified Patent Court. News, events, and information.",
	},
	{
		ID: "youpc-judgments", Category: "upc",
		Title:  "UPC Case Law (youpc.org)",
		URL:    "https://youpc.org/judgments",
		DescDE: "Durchsuchbare Datenbank aller UPC-Entscheidungen mit Zusammenfassungen und Themen-Tags.",
		DescEN: "Searchable database of all UPC decisions with summaries and topic tags.",
	},

	// Gesetze
	{
		ID: "patg", Category: "gesetze",
		Title:  "PatG — Patentgesetz",
		URL:    "https://dejure.org/gesetze/PatG",
		DescDE: "Deutsches Patentgesetz. Volltext mit Querverweisen und Rechtsprechung.",
		DescEN: "German Patent Act. Full text with cross-references and case law.",
	},
	{
		ID: "epue", Category: "gesetze",
		Title:  "EPÜ — Europäisches Patentübereinkommen",
		URL:    "https://dejure.org/gesetze/EPUe",
		DescDE: "Europäisches Patentübereinkommen. Materialien und Querverweise auf dejure.org.",
		DescEN: "European Patent Convention. Materials and cross-references on dejure.org.",
	},
	{
		ID: "upca", Category: "gesetze",
		Title:  "UPCA — Übereinkommen über ein Einheitliches Patentgericht",
		URL:    "https://www.unified-patent-court.org/en/court/legal-documents/agreement",
		DescDE: "Übereinkommen über ein Einheitliches Patentgericht (EPGÜ). Gründungsvertrag des UPC.",
		DescEN: "Agreement on a Unified Patent Court. Founding treaty of the UPC.",
	},
	{
		ID: "gkg", Category: "gesetze",
		Title:  "GKG — Gerichtskostengesetz",
		URL:    "https://dejure.org/gesetze/GKG",
		DescDE: "Gerichtskostengesetz. Gebührentabellen und Streitwertvorschriften.",
		DescEN: "Court Fees Act. Fee tables and dispute value provisions.",
	},
	{
		ID: "rvg", Category: "gesetze",
		Title:  "RVG — Rechtsanwaltsvergütungsgesetz",
		URL:    "https://dejure.org/gesetze/RVG",
		DescDE: "Rechtsanwaltsvergütungsgesetz. Anwaltsgebühren und Vergütungsverzeichnis.",
		DescEN: "Lawyers' Remuneration Act. Attorney fees and remuneration schedule.",
	},
	{
		ID: "zpo", Category: "gesetze",
		Title:  "ZPO — Zivilprozessordnung",
		URL:    "https://dejure.org/gesetze/ZPO",
		DescDE: "Zivilprozessordnung. Verfahrensrechtliche Grundlage für Patentverletzungsklagen.",
		DescEN: "Code of Civil Procedure. Procedural basis for patent infringement actions.",
	},
}

func handleLinksPage(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "dist/links.html")
}

func handleLinksAPI(w http.ResponseWriter, r *http.Request) {
	writeJSON(w, http.StatusOK, linksResponse{
		Categories: linkCategories,
		Links:      curatedLinks,
	})
}

type linkSuggestion struct {
	Title       string `json:"title"`
	URL         string `json:"url"`
	Category    string `json:"category"`
	Description string `json:"description"`
}

func handleLinkSuggest(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	var req linkSuggestion
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request"})
		return
	}
	if req.Title == "" || req.URL == "" || req.Category == "" {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "title, url, and category are required"})
		return
	}

	if err := dbSvc.link.InsertSuggestion(r.Context(), services.LinkSuggestionInput{
		Title:       req.Title,
		URL:         req.URL,
		Category:    req.Category,
		Description: req.Description,
		SuggestedBy: extractEmailFromCookie(r),
	}); err != nil {
		log.Printf("link suggest insert: %v", err)
		writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "could not save suggestion"})
		return
	}

	writeJSON(w, http.StatusCreated, map[string]string{"status": "ok"})
}

type linkFeedback struct {
	LinkID  string `json:"linkId"`
	Type    string `json:"type"`
	Message string `json:"message"`
}

func handleLinkFeedback(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	var req linkFeedback
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request"})
		return
	}
	if req.LinkID == "" || req.Type == "" {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "linkId and type are required"})
		return
	}

	if err := dbSvc.link.InsertFeedback(r.Context(), services.LinkFeedbackInput{
		LinkID:       req.LinkID,
		FeedbackType: req.Type,
		Message:      req.Message,
		SubmittedBy:  extractEmailFromCookie(r),
	}); err != nil {
		log.Printf("link feedback insert: %v", err)
		writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "could not save feedback"})
		return
	}

	writeJSON(w, http.StatusCreated, map[string]string{"status": "ok"})
}

// handleSuggestionCount intentionally swallows DB errors and returns 0 so the
// admin badge never breaks page rendering — the count is informational, not
// load-bearing. When DATABASE_URL isn't set the service is nil and we return 0
// rather than 503: knowledge-platform-only deployments still serve the page.
func handleSuggestionCount(w http.ResponseWriter, r *http.Request) {
	if dbSvc == nil {
		writeJSON(w, http.StatusOK, map[string]int{"count": 0})
		return
	}
	count, err := dbSvc.link.CountPendingSuggestions(r.Context())
	if err != nil {
		writeJSON(w, http.StatusOK, map[string]int{"count": 0})
		return
	}
	writeJSON(w, http.StatusOK, map[string]int{"count": count})
}

// extractEmailFromCookie decodes the user's email from the session JWT.
func extractEmailFromCookie(r *http.Request) string {
	c, err := r.Cookie(auth.SessionCookieName)
	if err != nil || c.Value == "" {
		return ""
	}
	value := c.Value
	parts := strings.Split(value, ".")
	if len(parts) != 3 {
		return ""
	}
	payload, err := base64.RawURLEncoding.DecodeString(parts[1])
	if err != nil {
		return ""
	}
	var claims struct {
		Email string `json:"email"`
	}
	if err := json.Unmarshal(payload, &claims); err != nil {
		return ""
	}
	return claims.Email
}

