package iace

import (
	"encoding/json"
	"time"

	"github.com/google/uuid"
)

// ============================================================================
// Main Entities
// ============================================================================

// Project represents an IACE compliance project for a machine or system
type Project struct {
	ID                   uuid.UUID       `json:"id"`
	TenantID             uuid.UUID       `json:"tenant_id"`
	ParentProjectID      *uuid.UUID      `json:"parent_project_id,omitempty"`
	MachineName          string          `json:"machine_name"`
	MachineType          string          `json:"machine_type"`
	Manufacturer         string          `json:"manufacturer"`
	// CustomerName is the end customer (Anlagenbetreiber). Optional —
	// projects without a customer are still valid, but customer-standard
	// reuse only fires across projects sharing the same non-empty value
	// (case-insensitive match, see customerKey()).
	CustomerName         string          `json:"customer_name,omitempty"`
	Description          string          `json:"description,omitempty"`
	NarrativeText        string          `json:"narrative_text,omitempty"`
	Status               ProjectStatus   `json:"status"`
	CEMarkingTarget      string          `json:"ce_marking_target,omitempty"`
	CompletenessScore    float64         `json:"completeness_score"`
	RiskSummary          map[string]int  `json:"risk_summary,omitempty"`
	TriggeredRegulations json.RawMessage `json:"triggered_regulations,omitempty"`
	Metadata             json.RawMessage `json:"metadata,omitempty"`
	CreatedAt            time.Time       `json:"created_at"`
	UpdatedAt            time.Time       `json:"updated_at"`
	ArchivedAt           *time.Time      `json:"archived_at,omitempty"`
}

// Component presence states for expert review of auto-detected components.
const (
	PresencePresent = "vorhanden"
	PresenceAbsent  = "nicht_vorhanden"
	PresenceDeleted = "geloescht"
)

// Component represents a system component within a project
type Component struct {
	ID               uuid.UUID       `json:"id"`
	ProjectID        uuid.UUID       `json:"project_id"`
	ParentID         *uuid.UUID      `json:"parent_id,omitempty"`
	Name             string          `json:"name"`
	ComponentType    ComponentType   `json:"component_type"`
	Version          string          `json:"version,omitempty"`
	Description      string          `json:"description,omitempty"`
	IsSafetyRelevant bool            `json:"is_safety_relevant"`
	IsNetworked      bool            `json:"is_networked"`
	// CEMarked: bought component that carries its own CE / Declaration of
	// Conformity (finished robot, actuator, drive, safety PLC). SAFE semantics:
	// does NOT suppress hazards — only drives provenance/evidence hints and the
	// "validate the integrated safety function (PL/SIL)" obligation when also
	// safety-relevant.
	CEMarked         bool            `json:"ce_marked"`
	// PresenceStatus: vorhanden | nicht_vorhanden | geloescht. Only `vorhanden`
	// components feed pattern matching. `nicht_vorhanden` = engine's best-effort
	// negation verdict awaiting expert review; `geloescht` = expert removed it
	// (kept as a soft-deleted audit row).
	PresenceStatus   string          `json:"presence_status"`
	Metadata         json.RawMessage `json:"metadata,omitempty"`
	SortOrder        int             `json:"sort_order"`
	CreatedAt        time.Time       `json:"created_at"`
	UpdatedAt        time.Time       `json:"updated_at"`
}

// RegulatoryClassification represents the classification result for a regulation
type RegulatoryClassification struct {
	ID                   uuid.UUID       `json:"id"`
	ProjectID            uuid.UUID       `json:"project_id"`
	Regulation           RegulationType  `json:"regulation"`
	ClassificationResult string          `json:"classification_result"`
	RiskLevel            RiskLevel       `json:"risk_level"`
	Confidence           float64         `json:"confidence"`
	Reasoning            string          `json:"reasoning,omitempty"`
	RAGSources           json.RawMessage `json:"rag_sources,omitempty"`
	Requirements         json.RawMessage `json:"requirements,omitempty"`
	CreatedAt            time.Time       `json:"created_at"`
	UpdatedAt            time.Time       `json:"updated_at"`
}

// HazardLibraryEntry represents a reusable hazard template from the library
type HazardLibraryEntry struct {
	ID                             uuid.UUID       `json:"id"`
	Category                       string          `json:"category"`
	SubCategory                    string          `json:"sub_category,omitempty"`
	Name                           string          `json:"name"`
	Description                    string          `json:"description,omitempty"`
	DefaultSeverity                int             `json:"default_severity"`
	DefaultProbability             int             `json:"default_probability"`
	DefaultExposure                int             `json:"default_exposure,omitempty"`
	DefaultAvoidance               int             `json:"default_avoidance,omitempty"`
	ApplicableComponentTypes       []string        `json:"applicable_component_types"`
	RegulationReferences           []string        `json:"regulation_references"`
	SuggestedMitigations           json.RawMessage `json:"suggested_mitigations,omitempty"`
	TypicalCauses                  []string        `json:"typical_causes,omitempty"`
	TypicalHarm                    string          `json:"typical_harm,omitempty"`
	RelevantLifecyclePhases        []string        `json:"relevant_lifecycle_phases,omitempty"`
	RecommendedMeasuresDesign      []string        `json:"recommended_measures_design,omitempty"`
	RecommendedMeasuresTechnical   []string        `json:"recommended_measures_technical,omitempty"`
	RecommendedMeasuresInformation []string        `json:"recommended_measures_information,omitempty"`
	SuggestedEvidence              []string        `json:"suggested_evidence,omitempty"`
	RelatedKeywords                []string        `json:"related_keywords,omitempty"`
	Tags                           []string        `json:"tags,omitempty"`
	IsBuiltin                      bool            `json:"is_builtin"`
	TenantID                       *uuid.UUID      `json:"tenant_id,omitempty"`
	CreatedAt                      time.Time       `json:"created_at"`
}

// Hazard represents a specific hazard identified within a project
type Hazard struct {
	ID              uuid.UUID    `json:"id"`
	ProjectID       uuid.UUID    `json:"project_id"`
	ComponentID     uuid.UUID    `json:"component_id"`
	LibraryHazardID *uuid.UUID   `json:"library_hazard_id,omitempty"`
	Name            string       `json:"name"`
	Description     string       `json:"description,omitempty"`
	Scenario        string       `json:"scenario,omitempty"`
	Category        string       `json:"category"`
	SubCategory     string       `json:"sub_category,omitempty"`
	Status          HazardStatus `json:"status"`
	MachineModule   string       `json:"machine_module,omitempty"`
	Function        string       `json:"function,omitempty"`
	LifecyclePhase  string       `json:"lifecycle_phase,omitempty"`
	HazardousZone   string       `json:"hazardous_zone,omitempty"`
	TriggerEvent    string       `json:"trigger_event,omitempty"`
	AffectedPerson  string       `json:"affected_person,omitempty"`
	PossibleHarm    string       `json:"possible_harm,omitempty"`
	// HazardType distinguishes ISO 12100 concepts:
	//   "hazard"              — the source of potential harm (e.g. mechanical movement)
	//   "hazardous_situation"  — person exposed to hazard (e.g. person in motion range)
	//   "harm"                — the injury outcome (e.g. crushing)
	// Derived field — not stored in DB. Computed by DeriveHazardType().
	HazardType      string       `json:"hazard_type,omitempty"`
	// OperationalStates lists which machine states triggered this hazard.
	// Derived field — encoded in Function column as "op_states:x,y,z", parsed on read.
	OperationalStates []string   `json:"operational_states,omitempty"`
	ReviewStatus    ReviewStatus `json:"review_status,omitempty"`
	CreatedAt       time.Time    `json:"created_at"`
	UpdatedAt       time.Time    `json:"updated_at"`
}

// RiskAssessment represents a quantitative risk assessment for a hazard
type RiskAssessment struct {
	ID                      uuid.UUID      `json:"id"`
	HazardID                uuid.UUID      `json:"hazard_id"`
	Version                 int            `json:"version"`
	AssessmentType          AssessmentType `json:"assessment_type"`
	Severity                int            `json:"severity"`
	Exposure                int            `json:"exposure"`
	Probability             int            `json:"probability"`
	Avoidance               int            `json:"avoidance,omitempty"` // 0=disabled, 1-5 (3=neutral)
	InherentRisk            float64        `json:"inherent_risk"`
	ControlMaturity         int            `json:"control_maturity"`
	ControlCoverage         float64        `json:"control_coverage"`
	TestEvidenceStrength    float64        `json:"test_evidence_strength"`
	CEff                    float64        `json:"c_eff"`
	ResidualRisk            float64        `json:"residual_risk"`
	RiskLevel               RiskLevel      `json:"risk_level"`
	IsAcceptable            bool           `json:"is_acceptable"`
	AcceptanceJustification string         `json:"acceptance_justification,omitempty"`
	AssessedBy              uuid.UUID      `json:"assessed_by"`
	CreatedAt               time.Time      `json:"created_at"`
}

// Mitigation represents a risk reduction measure applied to a hazard
type Mitigation struct {
	ID                 uuid.UUID          `json:"id"`
	HazardID           uuid.UUID          `json:"hazard_id"`
	ReductionType      ReductionType      `json:"reduction_type"`
	Name               string             `json:"name"`
	Description        string             `json:"description,omitempty"`
	Status             MitigationStatus   `json:"status"`
	VerificationMethod VerificationMethod `json:"verification_method,omitempty"`
	VerificationResult string             `json:"verification_result,omitempty"`
	VerifiedAt         *time.Time         `json:"verified_at,omitempty"`
	VerifiedBy         uuid.UUID          `json:"verified_by,omitempty"`
	// IsRelevant marks the mitigation as applicable for this concrete project.
	// Engine-suggested mitigations start with IsRelevant = false; the expert
	// flips it to true (or deletes the mitigation) when walking through the
	// Massnahmen tab. Only relevant mitigations surface in verification.
	IsRelevant bool `json:"is_relevant"`
	// IsCustomerStandard means the customer site already has this mitigation
	// implemented as company-wide standard, so no evidence upload is needed.
	// Implies IsRelevant = true (DB CHECK constraint).
	IsCustomerStandard bool      `json:"is_customer_standard"`
	CreatedAt          time.Time `json:"created_at"`
	UpdatedAt          time.Time `json:"updated_at"`
}

// Evidence represents an uploaded file that serves as evidence for compliance
type Evidence struct {
	ID                 uuid.UUID  `json:"id"`
	ProjectID          uuid.UUID  `json:"project_id"`
	MitigationID       *uuid.UUID `json:"mitigation_id,omitempty"`
	VerificationPlanID *uuid.UUID `json:"verification_plan_id,omitempty"`
	FileName           string     `json:"file_name"`
	FilePath           string     `json:"file_path"`
	FileHash           string     `json:"file_hash"`
	FileSize           int64      `json:"file_size"`
	MimeType           string     `json:"mime_type"`
	Description        string     `json:"description,omitempty"`
	UploadedBy         uuid.UUID  `json:"uploaded_by"`
	CreatedAt          time.Time  `json:"created_at"`
}

// VerificationPlan represents a plan for verifying compliance measures
type VerificationPlan struct {
	ID                 uuid.UUID          `json:"id"`
	ProjectID          uuid.UUID          `json:"project_id"`
	HazardID           *uuid.UUID         `json:"hazard_id,omitempty"`
	MitigationID       *uuid.UUID         `json:"mitigation_id,omitempty"`
	Title              string             `json:"title"`
	Description        string             `json:"description,omitempty"`
	AcceptanceCriteria string             `json:"acceptance_criteria,omitempty"`
	Method             VerificationMethod `json:"method"`
	Status             string             `json:"status"`
	Result             string             `json:"result,omitempty"`
	CompletedAt        *time.Time         `json:"completed_at,omitempty"`
	CompletedBy        uuid.UUID          `json:"completed_by,omitempty"`
	CreatedAt          time.Time          `json:"created_at"`
	UpdatedAt          time.Time          `json:"updated_at"`
}

// TechFileSection represents a section of the technical documentation file
type TechFileSection struct {
	ID          uuid.UUID             `json:"id"`
	ProjectID   uuid.UUID             `json:"project_id"`
	SectionType string                `json:"section_type"`
	Title       string                `json:"title"`
	Content     string                `json:"content,omitempty"`
	Version     int                   `json:"version"`
	Status      TechFileSectionStatus `json:"status"`
	ApprovedBy  uuid.UUID             `json:"approved_by,omitempty"`
	ApprovedAt  *time.Time            `json:"approved_at,omitempty"`
	Metadata    json.RawMessage       `json:"metadata,omitempty"`
	CreatedAt   time.Time             `json:"created_at"`
	UpdatedAt   time.Time             `json:"updated_at"`
}

// MonitoringEvent represents a post-market monitoring event
type MonitoringEvent struct {
	ID               uuid.UUID           `json:"id"`
	ProjectID        uuid.UUID           `json:"project_id"`
	EventType        MonitoringEventType `json:"event_type"`
	Title            string              `json:"title"`
	Description      string              `json:"description,omitempty"`
	Severity         string              `json:"severity"`
	ImpactAssessment string              `json:"impact_assessment,omitempty"`
	Status           string              `json:"status"`
	ResolvedAt       *time.Time          `json:"resolved_at,omitempty"`
	ResolvedBy       uuid.UUID           `json:"resolved_by,omitempty"`
	Metadata         json.RawMessage     `json:"metadata,omitempty"`
	CreatedAt        time.Time           `json:"created_at"`
	UpdatedAt        time.Time           `json:"updated_at"`
}

// AuditTrailEntry represents an immutable audit log entry for compliance traceability
type AuditTrailEntry struct {
	ID         uuid.UUID       `json:"id"`
	ProjectID  uuid.UUID       `json:"project_id"`
	EntityType string          `json:"entity_type"`
	EntityID   uuid.UUID       `json:"entity_id"`
	Action     AuditAction     `json:"action"`
	UserID     uuid.UUID       `json:"user_id"`
	OldValues  json.RawMessage `json:"old_values,omitempty"`
	NewValues  json.RawMessage `json:"new_values,omitempty"`
	Hash       string          `json:"hash"`
	CreatedAt  time.Time       `json:"created_at"`
}
