package iace

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/google/uuid"
	"github.com/jackc/pgx/v5"
)

// ============================================================================
// Hazard Library Operations
// ============================================================================

// ListHazardLibrary lists hazard library entries, optionally filtered by category and component type
func (s *Store) ListHazardLibrary(ctx context.Context, category string, componentType string) ([]HazardLibraryEntry, error) {
	query := `
		SELECT
			id, category, COALESCE(sub_category, ''), name, description,
			default_severity, default_probability,
			COALESCE(default_exposure, 3), COALESCE(default_avoidance, 3),
			applicable_component_types, regulation_references,
			suggested_mitigations,
			COALESCE(typical_causes, '[]'::jsonb),
			COALESCE(typical_harm, ''),
			COALESCE(relevant_lifecycle_phases, '[]'::jsonb),
			COALESCE(recommended_measures_design, '[]'::jsonb),
			COALESCE(recommended_measures_technical, '[]'::jsonb),
			COALESCE(recommended_measures_information, '[]'::jsonb),
			COALESCE(suggested_evidence, '[]'::jsonb),
			COALESCE(related_keywords, '[]'::jsonb),
			is_builtin, tenant_id,
			created_at
		FROM iace_hazard_library WHERE 1=1`

	args := []interface{}{}
	argIdx := 1

	if category != "" {
		query += fmt.Sprintf(" AND category = $%d", argIdx)
		args = append(args, category)
		argIdx++
	}
	if componentType != "" {
		query += fmt.Sprintf(" AND applicable_component_types @> $%d::jsonb", argIdx)
		componentTypeJSON, _ := json.Marshal([]string{componentType})
		args = append(args, string(componentTypeJSON))
		argIdx++
	}

	query += " ORDER BY category ASC, name ASC"

	rows, err := s.pool.Query(ctx, query, args...)
	if err != nil {
		return nil, fmt.Errorf("list hazard library: %w", err)
	}
	defer rows.Close()

	var entries []HazardLibraryEntry
	for rows.Next() {
		var e HazardLibraryEntry
		var applicableComponentTypes, regulationReferences, suggestedMitigations []byte
		var typicalCauses, relevantPhases, measuresDesign, measuresTechnical, measuresInfo, evidence, keywords []byte

		err := rows.Scan(
			&e.ID, &e.Category, &e.SubCategory, &e.Name, &e.Description,
			&e.DefaultSeverity, &e.DefaultProbability,
			&e.DefaultExposure, &e.DefaultAvoidance,
			&applicableComponentTypes, &regulationReferences,
			&suggestedMitigations,
			&typicalCauses, &e.TypicalHarm, &relevantPhases,
			&measuresDesign, &measuresTechnical, &measuresInfo,
			&evidence, &keywords,
			&e.IsBuiltin, &e.TenantID,
			&e.CreatedAt,
		)
		if err != nil {
			return nil, fmt.Errorf("list hazard library scan: %w", err)
		}

		json.Unmarshal(applicableComponentTypes, &e.ApplicableComponentTypes)
		json.Unmarshal(regulationReferences, &e.RegulationReferences)
		json.Unmarshal(suggestedMitigations, &e.SuggestedMitigations)
		json.Unmarshal(typicalCauses, &e.TypicalCauses)
		json.Unmarshal(relevantPhases, &e.RelevantLifecyclePhases)
		json.Unmarshal(measuresDesign, &e.RecommendedMeasuresDesign)
		json.Unmarshal(measuresTechnical, &e.RecommendedMeasuresTechnical)
		json.Unmarshal(measuresInfo, &e.RecommendedMeasuresInformation)
		json.Unmarshal(evidence, &e.SuggestedEvidence)
		json.Unmarshal(keywords, &e.RelatedKeywords)

		if e.ApplicableComponentTypes == nil {
			e.ApplicableComponentTypes = []string{}
		}
		if e.RegulationReferences == nil {
			e.RegulationReferences = []string{}
		}

		entries = append(entries, e)
	}

	return entries, nil
}

// GetHazardLibraryEntry retrieves a single hazard library entry by ID
func (s *Store) GetHazardLibraryEntry(ctx context.Context, id uuid.UUID) (*HazardLibraryEntry, error) {
	var e HazardLibraryEntry
	var applicableComponentTypes, regulationReferences, suggestedMitigations []byte
	var typicalCauses, relevantLifecyclePhases []byte
	var recommendedMeasuresDesign, recommendedMeasuresTechnical, recommendedMeasuresInformation []byte
	var suggestedEvidence, relatedKeywords []byte

	err := s.pool.QueryRow(ctx, `
		SELECT
			id, category, name, description,
			default_severity, default_probability,
			applicable_component_types, regulation_references,
			suggested_mitigations, is_builtin, tenant_id,
			created_at,
			COALESCE(sub_category, ''),
			COALESCE(default_exposure, 3),
			COALESCE(default_avoidance, 3),
			COALESCE(typical_causes, '[]'),
			COALESCE(typical_harm, ''),
			COALESCE(relevant_lifecycle_phases, '[]'),
			COALESCE(recommended_measures_design, '[]'),
			COALESCE(recommended_measures_technical, '[]'),
			COALESCE(recommended_measures_information, '[]'),
			COALESCE(suggested_evidence, '[]'),
			COALESCE(related_keywords, '[]')
		FROM iace_hazard_library WHERE id = $1
	`, id).Scan(
		&e.ID, &e.Category, &e.Name, &e.Description,
		&e.DefaultSeverity, &e.DefaultProbability,
		&applicableComponentTypes, &regulationReferences,
		&suggestedMitigations, &e.IsBuiltin, &e.TenantID,
		&e.CreatedAt,
		&e.SubCategory,
		&e.DefaultExposure, &e.DefaultAvoidance,
		&typicalCauses, &e.TypicalHarm,
		&relevantLifecyclePhases,
		&recommendedMeasuresDesign, &recommendedMeasuresTechnical, &recommendedMeasuresInformation,
		&suggestedEvidence, &relatedKeywords,
	)
	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, fmt.Errorf("get hazard library entry: %w", err)
	}

	json.Unmarshal(applicableComponentTypes, &e.ApplicableComponentTypes)
	json.Unmarshal(regulationReferences, &e.RegulationReferences)
	json.Unmarshal(suggestedMitigations, &e.SuggestedMitigations)
	json.Unmarshal(typicalCauses, &e.TypicalCauses)
	json.Unmarshal(relevantLifecyclePhases, &e.RelevantLifecyclePhases)
	json.Unmarshal(recommendedMeasuresDesign, &e.RecommendedMeasuresDesign)
	json.Unmarshal(recommendedMeasuresTechnical, &e.RecommendedMeasuresTechnical)
	json.Unmarshal(recommendedMeasuresInformation, &e.RecommendedMeasuresInformation)
	json.Unmarshal(suggestedEvidence, &e.SuggestedEvidence)
	json.Unmarshal(relatedKeywords, &e.RelatedKeywords)

	if e.ApplicableComponentTypes == nil {
		e.ApplicableComponentTypes = []string{}
	}
	if e.RegulationReferences == nil {
		e.RegulationReferences = []string{}
	}

	return &e, nil
}
