package handlers

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
	"time"

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

// Court represents a court, division, or registry relevant to the firm's
// patent practice. Fields left empty where details could not be reliably
// verified at build time.
type Court struct {
	ID        string   `json:"id"`
	NameDE    string   `json:"nameDE"`
	NameEN    string   `json:"nameEN"`
	Type      string   `json:"type"`    // taxonomy key, see CourtTypes below
	Group     string   `json:"group"`   // high-level filter: UPC | DE | EPA | National
	Country   string   `json:"country"` // ISO-3166 alpha-2
	City      string   `json:"city"`
	Address   string   `json:"address,omitempty"`
	Phone     string   `json:"phone,omitempty"`
	Fax       string   `json:"fax,omitempty"`
	Email     string   `json:"email,omitempty"`
	Website   string   `json:"website,omitempty"`
	Languages []string `json:"languages,omitempty"` // languages of proceedings
	Filing    string   `json:"filing,omitempty"`    // e-filing system / accepted formats
	NotesDE   string   `json:"notesDE,omitempty"`
	NotesEN   string   `json:"notesEN,omitempty"`
	HLContact string   `json:"hlContact,omitempty"` // firm-internal contact at this court; field name kept for API stability post-rebrand
	Source    string   `json:"source,omitempty"`    // internal reference URL, not rendered
}

// CourtType descriptor for filter pills and labels.
type CourtType struct {
	Key     string `json:"key"`
	LabelDE string `json:"labelDE"`
	LabelEN string `json:"labelEN"`
	Group   string `json:"group"`
}

var CourtTypes = []CourtType{
	{Key: "UPC-CD", LabelDE: "UPC Zentralkammer", LabelEN: "UPC Central Division", Group: "UPC"},
	{Key: "UPC-LD", LabelDE: "UPC Lokalkammer", LabelEN: "UPC Local Division", Group: "UPC"},
	{Key: "UPC-RD", LabelDE: "UPC Regionalkammer", LabelEN: "UPC Regional Division", Group: "UPC"},
	{Key: "UPC-CoA", LabelDE: "UPC Berufungsgericht", LabelEN: "UPC Court of Appeal", Group: "UPC"},
	{Key: "DE-LG", LabelDE: "Landgericht", LabelEN: "Regional Court", Group: "DE"},
	{Key: "DE-OLG", LabelDE: "Oberlandesgericht", LabelEN: "Higher Regional Court", Group: "DE"},
	{Key: "DE-BGH", LabelDE: "Bundesgerichtshof", LabelEN: "Federal Court of Justice", Group: "DE"},
	{Key: "DE-BPatG", LabelDE: "Bundespatentgericht", LabelEN: "Federal Patent Court", Group: "DE"},
	{Key: "DE-DPMA", LabelDE: "DPMA", LabelEN: "German Patent & Trade Mark Office", Group: "DE"},
	{Key: "EPA", LabelDE: "Europäisches Patentamt", LabelEN: "European Patent Office", Group: "EPA"},
	{Key: "NAT", LabelDE: "Nationales Gericht", LabelEN: "National Court", Group: "National"},
}

// courts — hardcoded court directory. Addresses verified against official sources
// where possible (sources listed per-entry). Fields left empty rather than guessed.
var courts = []Court{
	// --- UPC Court of Appeal ---
	{
		ID:        "upc-coa-luxembourg",
		NameDE:    "UPC Berufungsgericht — Luxemburg",
		NameEN:    "UPC Court of Appeal — Luxembourg",
		Type:      "UPC-CoA", Group: "UPC", Country: "LU", City: "Luxembourg",
		Address:   "1, rue du Fort Thüngen, L-1499 Luxembourg",
		Email:     "contact_luxembourg.coa@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/court-appeal",
		Languages: []string{"EN", "DE", "FR"},
		Filing:    "Case Management System (CMS) der UPC — elektronische Einreichung Pflicht.",
		NotesDE:   "Zweite Instanz für alle UPC-Verfahren. Sprache der Berufung folgt in der Regel der ersten Instanz.",
		NotesEN:   "Second instance for all UPC proceedings. Language of appeal generally follows that of the first instance.",
		Source:    "https://upc.law/institutions/luxembourg-court-of-appeal/",
	},

	// --- UPC Central Division ---
	{
		ID:        "upc-cd-paris",
		NameDE:    "UPC Zentralkammer — Sitz Paris",
		NameEN:    "UPC Central Division — Paris Seat",
		Type:      "UPC-CD", Group: "UPC", Country: "FR", City: "Paris",
		Email:     "contact_paris.cd@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/central-division",
		Languages: []string{"EN", "FR", "DE"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Zuständig u.a. für Sektionen B (Chemie, Hüttenwesen) und D (Textil, Papier) — inkl. der nach Milan verlagerten London-Zuständigkeiten.",
		NotesEN:   "Competent for sections B (chemistry, metallurgy) and D (textiles, paper), among others — includes part of the former London competences.",
		Source:    "https://www.unified-patent-court.org/en/court/central-division",
	},
	{
		ID:        "upc-cd-munich",
		NameDE:    "UPC Zentralkammer — Sektion München",
		NameEN:    "UPC Central Division — Munich Section",
		Type:      "UPC-CD", Group: "UPC", Country: "DE", City: "München",
		Address:   "Cincinnatistraße 64, 81549 München, Deutschland",
		Email:     "contact_munich.cd@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/central-division",
		Languages: []string{"DE", "EN", "FR"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Zuständig für Sektion F (Maschinenbau, Beleuchtung, Heizung, Waffen, Sprengen) — teilt das Gebäude mit dem BPatG.",
		NotesEN:   "Competent for section F (mechanical engineering, lighting, heating, weapons, blasting) — shares the building with the Federal Patent Court.",
		Source:    "https://www.dasoertliche.de/Themen/Bundespatentgericht-München-München-Obergiesing-Cincinnatistr",
	},
	{
		ID:        "upc-cd-milan",
		NameDE:    "UPC Zentralkammer — Sektion Mailand",
		NameEN:    "UPC Central Division — Milan Section",
		Type:      "UPC-CD", Group: "UPC", Country: "IT", City: "Milano",
		Address:   "Via San Barnaba 50, 20122 Milano, Italien",
		Email:     "contact_milan.cd@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/central-division",
		Languages: []string{"EN", "IT"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Seit Juni 2024 operativ. Übernimmt Teile der ursprünglich London zugewiesenen Zuständigkeiten (Sektion A — human necessities).",
		NotesEN:   "Operational since June 2024. Takes over part of the competences originally allocated to London (section A — human necessities).",
		Source:    "https://www.ipinitalia.com/upc/upc-milan-central-division-here-we-are/",
	},

	// --- UPC Local Divisions (DE) ---
	{
		ID:        "upc-ld-muenchen",
		NameDE:    "UPC Lokalkammer München",
		NameEN:    "UPC Local Division Munich",
		Type:      "UPC-LD", Group: "UPC", Country: "DE", City: "München",
		Address:   "Denisstraße 3, 80335 München, Deutschland",
		Email:     "contact_munich.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"DE", "EN"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Eine der aktivsten UPC-Kammern. Zweite Kammer seit 2024 eingerichtet, um die Fallzahlen zu bewältigen.",
		NotesEN:   "One of the most active UPC divisions. A second panel was set up in 2024 to handle the caseload.",
		Source:    "https://upc.hoffmanneitle.com/en/news/2024-05-02-upc-local-division-munich-second-panel",
	},
	{
		ID:        "upc-ld-duesseldorf",
		NameDE:    "UPC Lokalkammer Düsseldorf",
		NameEN:    "UPC Local Division Düsseldorf",
		Type:      "UPC-LD", Group: "UPC", Country: "DE", City: "Düsseldorf",
		Address:   "Cecilienallee 3, 40474 Düsseldorf, Deutschland",
		Email:     "contact_dusseldorf.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"DE", "EN"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Öffnungszeiten: Mo–Fr 9–12 Uhr persönlich, 13–16 Uhr nach Voranmeldung. Zweite Kammer eingerichtet aufgrund Fallzahlen.",
		NotesEN:   "Opening hours: Mon–Fri 9am–noon in person, 1pm–4pm by prior appointment. A second panel was established due to caseload.",
		Source:    "https://upc.law/institutions/local-division/duesseldorf-local-division/",
	},
	{
		ID:      "upc-ld-mannheim",
		NameDE:  "UPC Lokalkammer Mannheim",
		NameEN:  "UPC Local Division Mannheim",
		Type:    "UPC-LD", Group: "UPC", Country: "DE", City: "Mannheim",
		Email:     "contact_mannheim.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"DE", "EN"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Zweite Kammer eingerichtet. Aktive Kammer mit starker Rechtsprechung zu Verletzungsverfahren.",
		NotesEN:   "Second panel established. Active division with substantial infringement case law.",
		Source:    "https://upc.law/institutions/local-division/mannheim-local-division/",
	},
	{
		ID:      "upc-ld-hamburg",
		NameDE:  "UPC Lokalkammer Hamburg",
		NameEN:  "UPC Local Division Hamburg",
		Type:    "UPC-LD", Group: "UPC", Country: "DE", City: "Hamburg",
		Email:     "contact_hamburg.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"DE", "EN"},
		Filing:    "UPC Case Management System (CMS).",
		Source:    "https://www.unified-patent-court.org/en/court/locations",
	},

	// --- UPC Local Divisions (other EU) ---
	{
		ID:      "upc-ld-paris",
		NameDE:  "UPC Lokalkammer Paris",
		NameEN:  "UPC Local Division Paris",
		Type:    "UPC-LD", Group: "UPC", Country: "FR", City: "Paris",
		Email:     "contact_paris.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"FR", "EN"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Adressen-Hinweis des Gerichts: Kartendienste sind nicht immer präzise — Orientierung am Théâtre du Châtelet.",
		NotesEN:   "Court note: map services are not always accurate — orient towards the Théâtre du Châtelet.",
		Source:    "https://www.unified-patent-court.org/en/court/locations",
	},
	{
		ID:      "upc-ld-milan",
		NameDE:  "UPC Lokalkammer Mailand",
		NameEN:  "UPC Local Division Milan",
		Type:    "UPC-LD", Group: "UPC", Country: "IT", City: "Milano",
		Address:   "Via San Barnaba 50, 20122 Milano, Italien",
		Email:     "contact_milan.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"IT", "EN"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Im selben Gebäude wie die Sektion Mailand der Zentralkammer.",
		NotesEN:   "Located in the same building as the Milan section of the Central Division.",
		Source:    "https://www.ipinitalia.com/upc/upc-milan-central-division-here-we-are/",
	},
	{
		ID:      "upc-ld-denhaag",
		NameDE:  "UPC Lokalkammer Den Haag",
		NameEN:  "UPC Local Division The Hague",
		Type:    "UPC-LD", Group: "UPC", Country: "NL", City: "Den Haag",
		Address:   "Prinses Beatrixlaan 2, 2595 AL Den Haag, Niederlande (Postfach: P.O. Box 10366, 2501 HJ Den Haag)",
		Email:     "contact_thehague.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"EN", "NL"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Verfahren werden überwiegend in englischer Sprache geführt.",
		NotesEN:   "Proceedings are predominantly conducted in English.",
		Source:    "https://www.twobirds.com/en/trending-topics/unitary-patents-and-the-unified-patent-court/up-and-upc-interactive-map/the-netherlands",
	},
	{
		ID:      "upc-ld-brussels",
		NameDE:  "UPC Lokalkammer Brüssel",
		NameEN:  "UPC Local Division Brussels",
		Type:    "UPC-LD", Group: "UPC", Country: "BE", City: "Brussels",
		Email:     "contact_brussels.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"EN", "FR", "NL", "DE"},
		Filing:    "UPC Case Management System (CMS).",
		Source:    "https://www.unified-patent-court.org/en/court/locations",
	},
	{
		ID:      "upc-ld-helsinki",
		NameDE:  "UPC Lokalkammer Helsinki",
		NameEN:  "UPC Local Division Helsinki",
		Type:    "UPC-LD", Group: "UPC", Country: "FI", City: "Helsinki",
		Address:   "Radanrakentajantie 5, 00520 Helsinki, Finnland",
		Email:     "contact_helsinki.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"EN", "FI", "SV"},
		Filing:    "UPC Case Management System (CMS). Besuch nur nach Voranmeldung.",
		NotesDE:   "Im selben Gebäude wie das finnische Marktgericht (Markkinaoikeus).",
		NotesEN:   "Shares premises with the Finnish Market Court (Markkinaoikeus).",
		Source:    "https://tuomioistuimet.fi/en/index/tuomioistuinlaitos/tuomioistuimet/erityistuomioistuimet/markkinaoikeus_1/unifiedpatentcourtanditslocaldivisioninfinland.html",
	},
	{
		ID:      "upc-ld-lisbon",
		NameDE:  "UPC Lokalkammer Lissabon",
		NameEN:  "UPC Local Division Lisbon",
		Type:    "UPC-LD", Group: "UPC", Country: "PT", City: "Lisboa",
		Address:   "Palácio da Justiça de Lisboa, Rua Marquês de Fronteira, 1098-001 Lisboa, Portugal",
		Email:     "contact_lisbon.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"EN", "PT"},
		Filing:    "UPC Case Management System (CMS).",
		Source:    "https://www.unified-patent-court.org/en/court/locations",
	},
	{
		ID:      "upc-ld-wien",
		NameDE:  "UPC Lokalkammer Wien",
		NameEN:  "UPC Local Division Vienna",
		Type:    "UPC-LD", Group: "UPC", Country: "AT", City: "Wien",
		Email:     "contact_vienna.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"DE", "EN"},
		Filing:    "UPC Case Management System (CMS). Besuch nur nach schriftlicher Voranmeldung (Di–Mi 9–11:30 Uhr).",
		NotesDE:   "Adresse wurde zum 01.01.2025 geändert — vor Besuch Kontaktdaten beim Gericht bestätigen.",
		NotesEN:   "Address changed as of 1 January 2025 — confirm current location with the division before any in-person visit.",
		Source:    "https://upc.law/institutions/local-division/vienna-local-division/",
	},
	{
		ID:      "upc-ld-ljubljana",
		NameDE:  "UPC Lokalkammer Ljubljana",
		NameEN:  "UPC Local Division Ljubljana",
		Type:    "UPC-LD", Group: "UPC", Country: "SI", City: "Ljubljana",
		Email:     "contact_ljubljana.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"EN", "SL"},
		Filing:    "UPC Case Management System (CMS).",
		Source:    "https://www.unified-patent-court.org/en/court/locations",
	},
	{
		ID:      "upc-ld-kopenhagen",
		NameDE:  "UPC Lokalkammer Kopenhagen",
		NameEN:  "UPC Local Division Copenhagen",
		Type:    "UPC-LD", Group: "UPC", Country: "DK", City: "København",
		Email:     "contact_copenhagen.loc@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"EN", "DA"},
		Filing:    "UPC Case Management System (CMS).",
		Source:    "https://www.unified-patent-court.org/en/court/locations",
	},

	// --- UPC Regional Division ---
	{
		ID:      "upc-rd-nordic-baltic",
		NameDE:  "UPC Regionalkammer Nord-Baltikum (Stockholm)",
		NameEN:  "UPC Nordic-Baltic Regional Division (Stockholm)",
		Type:    "UPC-RD", Group: "UPC", Country: "SE", City: "Stockholm",
		Email:     "contact_stockholm.rd@unified-patent-court.org",
		Website:   "https://www.unified-patent-court.org/en/court/locations",
		Languages: []string{"EN"},
		Filing:    "UPC Case Management System (CMS).",
		NotesDE:   "Gemeinsame Regionalkammer für Schweden, Estland, Lettland und Litauen. Verhandlungen auch in Riga, Tallinn und Vilnius.",
		NotesEN:   "Joint regional division for Sweden, Estonia, Latvia and Lithuania. Hearings may also be held in Riga, Tallinn and Vilnius.",
		Source:    "https://upc.law/institutions/regional-division/nordic-baltic-regional-division/",
	},

	// --- Germany (national) ---
	{
		ID:      "de-lg-muenchen1",
		NameDE:  "Landgericht München I — Patentstreitkammern (7./21. Zivilkammer)",
		NameEN:  "Regional Court Munich I — Patent Chambers (7th/21st)",
		Type:    "DE-LG", Group: "DE", Country: "DE", City: "München",
		Address:   "Prielmayerstraße 7, 80335 München (Postanschrift: 80316 München)",
		Phone:     "+49 89 5597-01",
		Website:   "https://www.justiz.bayern.de/courts-und-behoerden/landgericht/muenchen-1/",
		Languages: []string{"DE"},
		Filing:    "beA (besonderes elektronisches Anwaltspostfach) / EGVP; PDF gemäß ERVV.",
		NotesDE:   "Zwei Patentstreitkammern (7. und 21. Zivilkammer). Bevorzugt intensive Erörterung; mündliche Verhandlungen oft ganztägig.",
		NotesEN:   "Two patent litigation chambers (7th and 21st civil chambers). Known for intensive oral hearings.",
		Source:    "https://www.justiz.bayern.de/courts-und-behoerden/landgericht/muenchen-1/",
	},
	{
		ID:      "de-lg-duesseldorf",
		NameDE:  "Landgericht Düsseldorf — Patentstreitkammern (4a/4b/4c Zivilkammer)",
		NameEN:  "Regional Court Düsseldorf — Patent Chambers (4a/4b/4c)",
		Type:    "DE-LG", Group: "DE", Country: "DE", City: "Düsseldorf",
		Address:   "Werdener Straße 1, 40227 Düsseldorf (Postanschrift: Postfach 103461, 40025 Düsseldorf)",
		Phone:     "+49 211 8306-0",
		Fax:       "+49 211 87565-1260",
		Website:   "https://www.lg-duesseldorf.nrw.de/",
		Languages: []string{"DE"},
		Filing:    "beA / EGVP gemäß ERVV.",
		NotesDE:   "Größte Patentstreitgerichtsbarkeit Deutschlands. Mehrere spezialisierte Kammern (4a, 4b, 4c).",
		NotesEN:   "Largest patent litigation docket in Germany. Multiple specialised chambers (4a, 4b, 4c).",
		Source:    "https://www.lg-duesseldorf.nrw.de/kontakt/index.php",
	},
	{
		ID:      "de-lg-mannheim",
		NameDE:  "Landgericht Mannheim — Patentstreitkammern (2./7. Zivilkammer)",
		NameEN:  "Regional Court Mannheim — Patent Chambers (2nd/7th)",
		Type:    "DE-LG", Group: "DE", Country: "DE", City: "Mannheim",
		Website:   "https://landgericht-mannheim.justiz-bw.de/",
		Languages: []string{"DE"},
		Filing:    "beA / EGVP gemäß ERVV.",
		NotesDE:   "Ausschließliche Patentzuständigkeit für Baden-Württemberg. Bekannt für zügige Verfahrensführung.",
		NotesEN:   "Exclusive patent jurisdiction for Baden-Württemberg. Known for efficient case management.",
		Source:    "https://landgericht-mannheim.justiz-bw.de/",
	},
	{
		ID:      "de-lg-hamburg",
		NameDE:  "Landgericht Hamburg — Patentstreitkammern",
		NameEN:  "Regional Court Hamburg — Patent Chambers",
		Type:    "DE-LG", Group: "DE", Country: "DE", City: "Hamburg",
		Address:   "Sievekingplatz 1, 20355 Hamburg",
		Website:   "https://justiz.hamburg.de/courts/landgericht-hamburg/",
		Languages: []string{"DE"},
		Filing:    "beA / EGVP gemäß ERVV.",
		Source:    "https://justiz.hamburg.de/courts/landgericht-hamburg/kontakt",
	},
	{
		ID:      "de-olg-duesseldorf",
		NameDE:  "Oberlandesgericht Düsseldorf — 2./15. Zivilsenat",
		NameEN:  "Higher Regional Court Düsseldorf — 2nd/15th Civil Senate",
		Type:    "DE-OLG", Group: "DE", Country: "DE", City: "Düsseldorf",
		Address:   "Cecilienallee 3, 40474 Düsseldorf",
		Website:   "https://www.olg-duesseldorf.nrw.de/",
		Languages: []string{"DE"},
		Filing:    "beA / EGVP gemäß ERVV.",
		NotesDE:   "Berufungsinstanz für Patentverletzungssachen aus dem LG Düsseldorf.",
		NotesEN:   "Appeal instance for patent infringement cases from LG Düsseldorf.",
		Source:    "https://www.olg-duesseldorf.nrw.de/kontakt/index.php",
	},
	{
		ID:      "de-olg-muenchen",
		NameDE:  "Oberlandesgericht München — 6. Zivilsenat (Patentberufungen)",
		NameEN:  "Higher Regional Court Munich — 6th Civil Senate (patent appeals)",
		Type:    "DE-OLG", Group: "DE", Country: "DE", City: "München",
		Address:   "Prielmayerstraße 5, 80335 München",
		Website:   "https://www.justiz.bayern.de/courts-und-behoerden/oberlandesgerichte/muenchen/",
		Languages: []string{"DE"},
		Filing:    "beA / EGVP gemäß ERVV.",
		Source:    "https://www.justiz.bayern.de/courts-und-behoerden/oberlandesgerichte/muenchen/kontakt.php",
	},
	{
		ID:      "de-olg-karlsruhe",
		NameDE:  "Oberlandesgericht Karlsruhe — 6. Zivilsenat (Patentberufungen)",
		NameEN:  "Higher Regional Court Karlsruhe — 6th Civil Senate (patent appeals)",
		Type:    "DE-OLG", Group: "DE", Country: "DE", City: "Karlsruhe",
		Website:   "https://oberlandesgericht-karlsruhe.justiz-bw.de/",
		Languages: []string{"DE"},
		Filing:    "beA / EGVP gemäß ERVV.",
		NotesDE:   "Berufungsinstanz für Patentsachen aus dem LG Mannheim.",
		NotesEN:   "Appeal instance for patent cases from LG Mannheim.",
		Source:    "https://oberlandesgericht-karlsruhe.justiz-bw.de/",
	},
	{
		ID:      "de-bgh",
		NameDE:  "Bundesgerichtshof — X. Zivilsenat",
		NameEN:  "Federal Court of Justice — Xth Civil Senate",
		Type:    "DE-BGH", Group: "DE", Country: "DE", City: "Karlsruhe",
		Address:   "Herrenstraße 45a, 76133 Karlsruhe (Postanschrift: Bundesgerichtshof, 76125 Karlsruhe)",
		Website:   "https://www.bundesgerichtshof.de/",
		Languages: []string{"DE"},
		Filing:    "beA / EGVP gemäß ERVV.",
		NotesDE:   "X. Zivilsenat ist zuständig für Patentstreitigkeiten (Revision und Nichtigkeitsberufung).",
		NotesEN:   "The Xth Civil Senate is competent for patent matters (revision and nullity appeals).",
		Source:    "https://www.bundesgerichtshof.de/DE/Service/Kontakt/AnfahrtKarlsruhe/anfahrtKarlsruhe_node.html",
	},
	{
		ID:      "de-bpatg",
		NameDE:  "Bundespatentgericht (BPatG)",
		NameEN:  "Federal Patent Court (BPatG)",
		Type:    "DE-BPatG", Group: "DE", Country: "DE", City: "München",
		Address:   "Cincinnatistraße 64, 81549 München",
		Phone:     "+49 89 69937-0",
		Fax:       "+49 89 69937-5100",
		Website:   "https://www.bundespatentgericht.de/",
		Languages: []string{"DE"},
		Filing:    "beA / EGVP gemäß ERVV.",
		NotesDE:   "Erstinstanzlich für Nichtigkeits- und Zwangslizenzklagen; Beschwerden gegen Beschlüsse des DPMA. Teilt das Gebäude mit der UPC-Sektion München.",
		NotesEN:   "First instance for nullity and compulsory-licence actions; appeals against DPMA decisions. Shares the building with the UPC Munich section.",
		Source:    "https://www.bundespatentgericht.de/EN/Service/Contact/contact_node.html",
	},
	{
		ID:      "de-dpma",
		NameDE:  "Deutsches Patent- und Markenamt (DPMA) — Hauptsitz München",
		NameEN:  "German Patent and Trade Mark Office (DPMA) — Munich HQ",
		Type:    "DE-DPMA", Group: "DE", Country: "DE", City: "München",
		Address:   "Zweibrückenstraße 12, 80331 München (Patentabteilungen überwiegend Anzinger Straße 29, Werksviertel, ab 2025)",
		Website:   "https://www.dpma.de/",
		Languages: []string{"DE", "EN"},
		Filing:    "DPMAdirektPro (elektronische Einreichung) oder DPMAdirektWeb; Papiereinreichung weiterhin möglich.",
		NotesDE:   "Zentrale DPMA-Einheiten (Präsidium, Recht) an der Zweibrückenstraße; Patentprüfungs- und Patentverwaltungsabteilungen ab 2025 überwiegend im Werksviertel (Anzinger Straße 29).",
		NotesEN:   "Central DPMA functions (president, legal) at Zweibrückenstraße; patent examination and administration mostly at Anzinger Straße 29 from 2025 on.",
		Source:    "https://www.dpma.de/dpma/kontakt/muenchen/index.html",
	},

	// --- EPA ---
	{
		ID:      "epa-munich",
		NameDE:  "Europäisches Patentamt — Hauptsitz München (Isar-Gebäude)",
		NameEN:  "European Patent Office — Munich Headquarters (Isar Building)",
		Type:    "EPA", Group: "EPA", Country: "DE", City: "München",
		Address:   "Bob-van-Benthem-Platz 1, 80469 München",
		Phone:     "+49 89 2399-0",
		Website:   "https://www.epo.org/",
		Languages: []string{"EN", "DE", "FR"},
		Filing:    "EPO Online Filing (OLF) / MyEPO Portfolio; PCT-EASY / ePCT für internationale Anmeldungen.",
		NotesDE:   "Sitz der Prüfungsabteilungen, Einspruchsabteilungen und Beschwerdekammern (letztere in Haar, siehe eigene Position).",
		NotesEN:   "Seat of the Examining and Opposition Divisions; Boards of Appeal are located in Haar (see separate entry).",
		Source:    "https://www.epo.org/en/about-us/contact",
	},
	{
		ID:      "epa-boards-haar",
		NameDE:  "EPA Beschwerdekammern — Haar bei München",
		NameEN:  "EPO Boards of Appeal — Haar (Munich)",
		Type:    "EPA", Group: "EPA", Country: "DE", City: "Haar",
		Address:   "Richard-Reitzner-Allee 8, 85540 Haar, Deutschland",
		Website:   "https://www.epo.org/en/about-us/boards-of-appeal",
		Languages: []string{"EN", "DE", "FR"},
		Filing:    "Schriftsatzeinreichung per EPO Online Filing / MyEPO Portfolio; Fax und Post weiterhin zulässig.",
		NotesDE:   "Technische Beschwerdekammern und Große Beschwerdekammer sind seit 2017 am Standort Haar.",
		NotesEN:   "Technical Boards of Appeal and Enlarged Board of Appeal have been located in Haar since 2017.",
		Source:    "https://www.epo.org/en/about-us/boards-of-appeal",
	},
	{
		ID:      "epa-hague",
		NameDE:  "Europäisches Patentamt — Zweigstelle Den Haag (Rijswijk)",
		NameEN:  "European Patent Office — Branch The Hague (Rijswijk)",
		Type:    "EPA", Group: "EPA", Country: "NL", City: "Rijswijk",
		Address:   "Patentlaan 2, 2288 EE Rijswijk, Niederlande",
		Website:   "https://www.epo.org/",
		Languages: []string{"EN", "DE", "FR"},
		Filing:    "EPO Online Filing / MyEPO Portfolio.",
		NotesDE:   "Standort der Rechercheabteilungen und Teilen der Prüfung.",
		NotesEN:   "Home to the search divisions and parts of substantive examination.",
		Source:    "https://www.epo.org/en/about-us/contact",
	},

	// --- National non-UPC relevant courts ---
	{
		ID:      "nl-rechtbank-denhaag",
		NameDE:  "Rechtbank Den Haag — Patentkamer",
		NameEN:  "District Court The Hague — Patent Chamber",
		Type:    "NAT", Group: "National", Country: "NL", City: "Den Haag",
		Address:   "Prins Clauslaan 60, 2595 AJ Den Haag (Postanschrift: Postbus 20302, 2500 EH Den Haag)",
		Website:   "https://www.rechtspraak.nl/Organisatie-en-contact/Organisatie/Rechtbanken/Rechtbank-Den-Haag",
		Languages: []string{"NL", "EN"},
		Filing:    "KEI / webportaal rechtspraak.nl (für zivilrechtliche Patentverfahren).",
		NotesDE:   "Ausschließliche Patentzuständigkeit für die Niederlande in nicht-UPC-Verfahren. Zügige Verfahren, oft als versneld regime.",
		NotesEN:   "Exclusive patent jurisdiction for the Netherlands in non-UPC proceedings. Known for the accelerated regime (versneld regime).",
		Source:    "https://www.rechtspraak.nl/Organisatie-en-contact/Organisatie/Rechtbanken/Rechtbank-Den-Haag",
	},
	{
		ID:      "nl-gerechtshof-denhaag",
		NameDE:  "Gerechtshof Den Haag — Berufungsinstanz Patentsachen",
		NameEN:  "Court of Appeal The Hague — Patent Appeals",
		Type:    "NAT", Group: "National", Country: "NL", City: "Den Haag",
		Website:   "https://www.rechtspraak.nl/Organisatie-en-contact/Organisatie/Gerechtshoven/Gerechtshof-Den-Haag",
		Languages: []string{"NL", "EN"},
		NotesDE:   "Berufungsinstanz für Entscheidungen der Rechtbank Den Haag in Patentsachen.",
		NotesEN:   "Appeal instance for patent decisions of the Rechtbank The Hague.",
		Source:    "https://www.rechtspraak.nl/Organisatie-en-contact/Organisatie/Gerechtshoven/Gerechtshof-Den-Haag",
	},
	{
		ID:      "uk-patents-court",
		NameDE:  "UK Patents Court (High Court) — Rolls Building",
		NameEN:  "UK Patents Court (High Court) — Rolls Building",
		Type:    "NAT", Group: "National", Country: "GB", City: "London",
		Address:   "Rolls Building, 7 Rolls Buildings, Fetter Lane, London EC4A 1NL, United Kingdom",
		Website:   "https://www.gov.uk/courts-tribunals/patents-court",
		Languages: []string{"EN"},
		Filing:    "CE-File (elektronische Einreichung Pflicht); PDF-Format.",
		NotesDE:   "Spezialisierte Patentkammer der Business and Property Courts. UK ist kein UPC-Mitglied; UK-Patentverletzungsverfahren weiterhin national.",
		NotesEN:   "Specialist patent list within the Business and Property Courts. UK is not a UPC member; infringement matters remain domestic.",
		Source:    "https://www.judiciary.uk/courts-and-tribunals/business-and-property-courts/business-list-general-chancery/intellectual-property-list/",
	},
	{
		ID:      "uk-ipec",
		NameDE:  "Intellectual Property Enterprise Court (IPEC)",
		NameEN:  "Intellectual Property Enterprise Court (IPEC)",
		Type:    "NAT", Group: "National", Country: "GB", City: "London",
		Address:   "Rolls Building, 7 Rolls Buildings, Fetter Lane, London EC4A 1NL, United Kingdom",
		Website:   "https://www.gov.uk/courts-tribunals/intellectual-property-enterprise-court",
		Languages: []string{"EN"},
		Filing:    "CE-File; Small-Claims Track mit Streitwertgrenze.",
		NotesDE:   "Vereinfachtes Verfahren mit Streitwertobergrenze (derzeit GBP 500.000) und Kostendeckelung. Geeignet für KMU-Fälle und überschaubare Streitigkeiten.",
		NotesEN:   "Streamlined procedure with monetary cap (currently GBP 500,000) and cost caps. Suitable for SME disputes.",
		Source:    "https://www.gov.uk/courts-tribunals/intellectual-property-enterprise-court",
	},
	{
		ID:      "uk-ipo",
		NameDE:  "UK Intellectual Property Office (UKIPO)",
		NameEN:  "UK Intellectual Property Office (UKIPO)",
		Type:    "NAT", Group: "National", Country: "GB", City: "Newport",
		Address:   "Concept House, Cardiff Road, Newport NP10 8QQ, United Kingdom",
		Website:   "https://www.gov.uk/government/organisations/intellectual-property-office",
		Languages: []string{"EN"},
		Filing:    "Online services UKIPO (Patents Forms Online).",
		NotesDE:   "Nationale Anmeldung, Erteilung und Aufrechterhaltung von UK-Patenten; Opinion Service zu Verletzung und Gültigkeit.",
		NotesEN:   "National filing, grant and maintenance of UK patents; Opinion Service on infringement and validity.",
		Source:    "https://www.gov.uk/government/organisations/intellectual-property-office",
	},
	{
		ID:      "fr-tj-paris",
		NameDE:  "Tribunal judiciaire de Paris — Pôle propriété intellectuelle (3e chambre)",
		NameEN:  "Paris Judicial Court — Intellectual Property Division (3rd Chamber)",
		Type:    "NAT", Group: "National", Country: "FR", City: "Paris",
		Address:   "Parvis du Tribunal de Paris, 29–45 Avenue de la Porte de Clichy, 75017 Paris",
		Phone:     "+33 1 44 32 51 51",
		Website:   "https://www.tribunal-de-paris.justice.fr/75",
		Languages: []string{"FR"},
		Filing:    "RPVA / e-Barreau für Anwaltskommunikation.",
		NotesDE:   "Ausschließliche Zuständigkeit für Patentstreitigkeiten in Frankreich außerhalb des UPC.",
		NotesEN:   "Exclusive jurisdiction for patent litigation in France outside the UPC.",
		Source:    "https://www.tribunal-de-paris.justice.fr/75/nous-contacter",
	},
	{
		ID:      "fr-cour-appel-paris",
		NameDE:  "Cour d'appel de Paris — Pôle 5 chambre 1 (propriété intellectuelle)",
		NameEN:  "Paris Court of Appeal — Division 5 Chamber 1 (IP)",
		Type:    "NAT", Group: "National", Country: "FR", City: "Paris",
		Website:   "https://www.cours-appel.justice.fr/paris",
		Languages: []string{"FR"},
		NotesDE:   "Berufungsinstanz für Patentsachen aus dem Tribunal judiciaire de Paris.",
		NotesEN:   "Appeal instance for patent matters from Tribunal judiciaire de Paris.",
		Source:    "https://www.cours-appel.justice.fr/paris",
	},
	{
		ID:      "fr-inpi",
		NameDE:  "INPI — Institut national de la propriété industrielle",
		NameEN:  "INPI — French National Industrial Property Institute",
		Type:    "NAT", Group: "National", Country: "FR", City: "Courbevoie",
		Address:   "15 rue des Minimes, CS 50001, 92677 Courbevoie Cedex, France",
		Website:   "https://www.inpi.fr/",
		Languages: []string{"FR", "EN"},
		Filing:    "Portail INPI (e-procédures).",
		NotesDE:   "Nationales französisches Patent- und Markenamt.",
		NotesEN:   "French national patent and trade mark office.",
		Source:    "https://www.inpi.fr/",
	},
	{
		ID:      "it-tribunale-milano",
		NameDE:  "Tribunale di Milano — Sezioni Specializzate Impresa (14./15. Sektion)",
		NameEN:  "Court of Milan — Specialised Business Sections (14th/15th)",
		Type:    "NAT", Group: "National", Country: "IT", City: "Milano",
		Address:   "Via Freguglia 1 / Corso di Porta Vittoria 6–8, 20122 Milano (Zugang über Via Manara)",
		Website:   "https://www.tribunale.milano.it/",
		Languages: []string{"IT"},
		NotesDE:   "Spezialisierte Unternehmenskammern (Sezioni Specializzate Impresa) mit Patentzuständigkeit für Norditalien außerhalb des UPC.",
		NotesEN:   "Specialised business sections with patent jurisdiction for Northern Italy outside the UPC.",
		Source:    "https://tribunale-milano.giustizia.it/it/sez_14_civile.page",
	},
	{
		ID:      "it-tribunale-torino",
		NameDE:  "Tribunale di Torino — Sezione Specializzata Impresa",
		NameEN:  "Court of Turin — Specialised Business Section",
		Type:    "NAT", Group: "National", Country: "IT", City: "Torino",
		Website:   "https://www.tribunale.torino.it/",
		Languages: []string{"IT"},
		NotesDE:   "Regionale Zuständigkeit für Patentstreitigkeiten im Nordwesten Italiens außerhalb des UPC.",
		NotesEN:   "Regional jurisdiction for patent matters in north-western Italy outside the UPC.",
		Source:    "https://www.tribunale.torino.it/",
	},
}

// --- Feedback ---

type CourtsFeedback struct {
	FeedbackType string `json:"feedback_type"`
	Message      string `json:"message"`
	CourtID      string `json:"court_id,omitempty"`
}

type CourtsResponse struct {
	Courts []Court     `json:"courts"`
	Types  []CourtType `json:"types"`
}

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

func handleCourtsAPI(w http.ResponseWriter, r *http.Request) {
	// Strip the internal `source` field — it is for maintainers, not for end users.
	public := make([]Court, len(courts))
	for i, c := range courts {
		c.Source = ""
		public[i] = c
	}
	writeJSON(w, http.StatusOK, CourtsResponse{Courts: public, Types: CourtTypes})
}

func handleCourtsFeedback(w http.ResponseWriter, r *http.Request) {
	var feedback CourtsFeedback
	if err := json.NewDecoder(r.Body).Decode(&feedback); err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Ungültige Anfrage."})
		return
	}

	feedback.FeedbackType = strings.TrimSpace(feedback.FeedbackType)
	feedback.Message = strings.TrimSpace(feedback.Message)
	feedback.CourtID = strings.TrimSpace(feedback.CourtID)

	if feedback.Message == "" || feedback.FeedbackType == "" {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Nachricht und Art sind erforderlich."})
		return
	}

	accessToken := ""
	email := ""
	if cookie, err := r.Cookie(auth.SessionCookieName); err == nil {
		accessToken = cookie.Value
		email = extractEmailFromJWT(cookie.Value)
	}

	payload := map[string]string{
		"feedback_type": feedback.FeedbackType,
		"message":       feedback.Message,
		"court_id":      feedback.CourtID,
		"submitted_by":  email,
	}

	jsonBody, err := json.Marshal(payload)
	if err != nil {
		log.Printf("gerichte feedback marshal error: %v", err)
		writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "Interner Fehler."})
		return
	}

	endpoint := fmt.Sprintf("%s/rest/v1/court_feedback", authClient.URL)
	req2, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonBody))
	if err != nil {
		log.Printf("gerichte feedback request error: %v", err)
		writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "Interner Fehler."})
		return
	}
	req2.Header.Set("Content-Type", "application/json")
	req2.Header.Set("apikey", authClient.AnonKey)
	if accessToken != "" {
		req2.Header.Set("Authorization", "Bearer "+accessToken)
	} else {
		req2.Header.Set("Authorization", "Bearer "+authClient.AnonKey)
	}
	req2.Header.Set("Prefer", "return=minimal")

	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Do(req2)
	if err != nil {
		log.Printf("gerichte feedback supabase error: %v", err)
		writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "Fehler beim Speichern."})
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 300 {
		body, _ := io.ReadAll(resp.Body)
		log.Printf("gerichte feedback supabase status %d: %s", resp.StatusCode, string(body))
		writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "Fehler beim Speichern."})
		return
	}

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