package handlers

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// RegulatoryHint represents a relevant passage from TRBS/TRGS/ASR/OSHA.
type RegulatoryHint struct {
	RegulationID    string  `json:"regulation_id"`
	RegulationShort string  `json:"regulation_short"`
	Category        string  `json:"category"`
	Text            string  `json:"text"`
	Pages           []int   `json:"pages,omitempty"`
	SourceURL       string  `json:"source_url,omitempty"`
	Score           float64 `json:"score"`
}

// categoryToSearchTerms maps hazard categories to German search terms
// that match TRBS/TRGS/ASR/OSHA content.
var categoryToSearchTerms = map[string]string{
	"mechanical_hazard":          "mechanische Gefaehrdung Quetschstelle Scherstelle Stossstelle",
	"electrical_hazard":          "elektrische Gefaehrdung Stromschlag Lichtbogen Kurzschluss",
	"thermal_hazard":             "thermische Gefaehrdung Verbrennung Erfrierung heisse Oberflaeche",
	"noise_hazard":               "Laerm Gehoerschutz Schalldruckpegel Laermexposition",
	"vibration_hazard":           "Vibration Hand-Arm Ganzkoerper Schwingungsbelastung",
	"radiation_hazard":           "Strahlung ionisierend nichtionisierend Laser UV",
	"chemical_hazard":            "Gefahrstoff chemische Gefaehrdung Exposition Grenzwert",
	"ergonomic_hazard":           "Ergonomie Zwangshaltung Lasthandhabung Koerperbelastung",
	"hydraulic_hazard":           "Hydraulik Druckbehaelter Druck Bersten Leckage",
	"pneumatic_hazard":           "Pneumatik Druckluft Druckbehaelter Belueftung",
	"software_hazard":            "Software Sicherheitsfunktion Fehlfunktion Programmierung",
	"safety_function_failure":    "Sicherheitsfunktion Ausfall SIL Performance Level",
	"fire_explosion_hazard":      "Brand Explosion explosionsfaehige Atmosphaere Zuendschutz",
	"falling_hazard":             "Absturz herabfallende Gegenstaende Sturzgefahr",
	"trip_slip_hazard":           "Stolpern Rutschen Ausrutschen Fussboden Verkehrsweg",
	"entrapment_hazard":          "Einzugsstelle Fangstelle rotierende Teile Wickelgefahr",
	"crush_hazard":               "Quetschgefahr Quetschstelle Einklemmen Andruckkraft",
	"cut_hazard":                 "Schneiden Schneidwerkzeug Schnittverletzung scharfe Kante",
	"stabbing_hazard":            "Stechen Stichverletzung spitze Teile Injektionsgefahr",
	"high_pressure_hazard":       "Hochdruck Fluessigkeitsstrahl Druckbehaelter Ueberdruck",
	"collision_hazard":           "Kollision Zusammenstoss Anfahren fahrerlose Transportsysteme",
	"lack_of_stability_hazard":   "Standsicherheit Umkippen Kippen Stabilitaet",
	"unexpected_start_hazard":    "unerwarteter Anlauf Wiederanlauf Energietrennung Lockout",
	"control_system_failure":     "Steuerungsausfall Steuerung Fehler Ausfall Sicherheitssteuerung",
	"ppe_hazard":                 "PSA persoenliche Schutzausruestung Schutzkleidung",
}

// EnrichHazardWithRegulations returns regulatory hints for a specific hazard.
// GET /projects/:id/hazards/:hid/regulatory-hints
func (h *IACEHandler) EnrichHazardWithRegulations(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	hazardID, err := uuid.Parse(c.Param("hid"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid hazard ID"})
		return
	}

	// Fetch hazard
	hazard, err := h.store.GetHazard(c.Request.Context(), hazardID)
	if err != nil || hazard == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "hazard not found"})
		return
	}
	if hazard.ProjectID != projectID {
		c.JSON(http.StatusNotFound, gin.H{"error": "hazard not in this project"})
		return
	}

	// Fetch project for machine context
	project, err := h.store.GetProject(c.Request.Context(), projectID)
	if err != nil || project == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "project not found"})
		return
	}

	// Build search query from hazard context
	query := buildHazardSearchQuery(hazard.Category, hazard.Name, hazard.Scenario, project.MachineName, project.MachineType)

	// Search bp_compliance_ce (TRBS/TRGS/ASR/OSHA)
	results, err := h.ragClient.SearchCollection(
		c.Request.Context(),
		"bp_compliance_ce",
		query,
		nil, // no regulation filter — search all
		7,
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "regulatory search failed: " + err.Error(),
		})
		return
	}

	hints := make([]RegulatoryHint, 0, len(results))
	for _, r := range results {
		if r.Score < 0.3 {
			continue // skip low-relevance results
		}
		hints = append(hints, RegulatoryHint{
			RegulationID:    r.RegulationCode,
			RegulationShort: r.RegulationShort,
			Category:        r.Category,
			Text:            truncateHintText(r.Text, 500),
			Pages:           r.Pages,
			SourceURL:       r.SourceURL,
			Score:           r.Score,
		})
	}

	c.JSON(http.StatusOK, gin.H{
		"hazard_id":   hazardID.String(),
		"hazard_name": hazard.Name,
		"category":    hazard.Category,
		"query":       query,
		"hints":       hints,
		"total":       len(hints),
	})
}

// EnrichMitigationWithRegulations returns regulatory hints for a mitigation.
// GET /projects/:id/mitigations/:mid/regulatory-hints
func (h *IACEHandler) EnrichMitigationWithRegulations(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	mitigationID, err := uuid.Parse(c.Param("mid"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid mitigation ID"})
		return
	}

	// Fetch mitigation
	mitigation, err := h.store.GetMitigation(c.Request.Context(), mitigationID)
	if err != nil || mitigation == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "mitigation not found"})
		return
	}

	// Fetch the hazard to get category context
	hazard, err := h.store.GetHazard(c.Request.Context(), mitigation.HazardID)
	if err != nil || hazard == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "linked hazard not found"})
		return
	}
	if hazard.ProjectID != projectID {
		c.JSON(http.StatusNotFound, gin.H{"error": "mitigation not in this project"})
		return
	}

	// Build search query from mitigation + hazard context
	queryParts := []string{mitigation.Name}
	if mitigation.Description != "" {
		queryParts = append(queryParts, mitigation.Description)
	}
	queryParts = append(queryParts, "Schutzmassnahme")
	if terms, ok := categoryToSearchTerms[hazard.Category]; ok {
		queryParts = append(queryParts, terms)
	}
	query := strings.Join(queryParts, " ")
	if len(query) > 500 {
		query = query[:500]
	}

	results, err := h.ragClient.SearchCollection(
		c.Request.Context(),
		"bp_compliance_ce",
		query,
		nil,
		7,
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "regulatory search failed: " + err.Error(),
		})
		return
	}

	hints := make([]RegulatoryHint, 0, len(results))
	for _, r := range results {
		if r.Score < 0.3 {
			continue
		}
		hints = append(hints, RegulatoryHint{
			RegulationID:    r.RegulationCode,
			RegulationShort: r.RegulationShort,
			Category:        r.Category,
			Text:            truncateHintText(r.Text, 500),
			Pages:           r.Pages,
			SourceURL:       r.SourceURL,
			Score:           r.Score,
		})
	}

	c.JSON(http.StatusOK, gin.H{
		"mitigation_id":   mitigationID.String(),
		"mitigation_name": mitigation.Name,
		"reduction_type":  mitigation.ReductionType,
		"query":           query,
		"hints":           hints,
		"total":           len(hints),
	})
}

// buildHazardSearchQuery creates a contextual query for RAG search.
func buildHazardSearchQuery(category, name, scenario, machineName, machineType string) string {
	parts := make([]string, 0, 5)

	// Add category-specific German search terms
	if terms, ok := categoryToSearchTerms[category]; ok {
		parts = append(parts, terms)
	}

	// Add hazard name and scenario
	if name != "" {
		parts = append(parts, name)
	}
	if scenario != "" && len(scenario) < 200 {
		parts = append(parts, scenario)
	}

	// Add machine context
	if machineType != "" {
		parts = append(parts, machineType)
	}
	if machineName != "" && len(parts) < 4 {
		parts = append(parts, machineName)
	}

	query := strings.Join(parts, " ")
	if len(query) > 500 {
		query = query[:500]
	}
	return query
}

func truncateHintText(text string, maxLen int) string {
	if len(text) <= maxLen {
		return text
	}
	// Find last sentence boundary
	truncated := text[:maxLen]
	if lastDot := strings.LastIndex(truncated, ". "); lastDot > maxLen/2 {
		return truncated[:lastDot+1]
	}
	return truncated + "..."
}

// ============================================================================
// Batch: Enrich all hazards at once (for overview display)
// ============================================================================

// EnrichProjectHazardsBatch returns top regulatory hint per hazard category.
// GET /projects/:id/regulatory-hints
func (h *IACEHandler) EnrichProjectHazardsBatch(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	project, err := h.store.GetProject(c.Request.Context(), projectID)
	if err != nil || project == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "project not found"})
		return
	}

	// Get all hazards to extract unique categories
	hazards, err := h.store.ListHazards(c.Request.Context(), projectID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list hazards"})
		return
	}

	// Deduplicate categories
	seen := make(map[string]bool)
	var categories []string
	for _, hz := range hazards {
		if !seen[hz.Category] {
			seen[hz.Category] = true
			categories = append(categories, hz.Category)
		}
	}

	// One RAG search per unique category (typically 5-10 categories, not 160 hazards)
	type CategoryHints struct {
		Category string           `json:"category"`
		Hints    []RegulatoryHint `json:"hints"`
	}

	result := make([]CategoryHints, 0, len(categories))
	for _, cat := range categories {
		query := buildHazardSearchQuery(cat, "", "", project.MachineName, project.MachineType)
		results, err := h.ragClient.SearchCollection(
			c.Request.Context(),
			"bp_compliance_ce",
			query,
			nil,
			3,
		)
		if err != nil {
			continue
		}

		hints := make([]RegulatoryHint, 0, len(results))
		for _, r := range results {
			if r.Score < 0.3 {
				continue
			}
			hints = append(hints, RegulatoryHint{
				RegulationID:    r.RegulationCode,
				RegulationShort: r.RegulationShort,
				Category:        r.Category,
				Text:            truncateHintText(r.Text, 300),
				Pages:           r.Pages,
				SourceURL:       r.SourceURL,
				Score:           r.Score,
			})
		}
		if len(hints) > 0 {
			result = append(result, CategoryHints{Category: cat, Hints: hints})
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"project_id":       projectID.String(),
		"categories":       len(categories),
		"total_hazards":    len(hazards),
		"regulatory_hints": result,
		"sources":          fmt.Sprintf("TRBS/TRGS/ASR (%d BAuA) + OSHA Technical Manual", 126),
	})
}
