package incidents

import (
	"time"

	"github.com/google/uuid"
)

// ============================================================================
// Constants / Enums
// ============================================================================

// IncidentCategory represents the category of a security/data breach incident
type IncidentCategory string

const (
	IncidentCategoryDataBreach          IncidentCategory = "data_breach"
	IncidentCategoryUnauthorizedAccess  IncidentCategory = "unauthorized_access"
	IncidentCategoryDataLoss            IncidentCategory = "data_loss"
	IncidentCategorySystemCompromise    IncidentCategory = "system_compromise"
	IncidentCategoryPhishing            IncidentCategory = "phishing"
	IncidentCategoryRansomware          IncidentCategory = "ransomware"
	IncidentCategoryInsiderThreat       IncidentCategory = "insider_threat"
	IncidentCategoryPhysicalBreach      IncidentCategory = "physical_breach"
	IncidentCategoryOther               IncidentCategory = "other"
)

// IncidentStatus represents the status of an incident through its lifecycle
type IncidentStatus string

const (
	IncidentStatusDetected             IncidentStatus = "detected"
	IncidentStatusAssessment           IncidentStatus = "assessment"
	IncidentStatusContainment          IncidentStatus = "containment"
	IncidentStatusNotificationRequired IncidentStatus = "notification_required"
	IncidentStatusNotificationSent     IncidentStatus = "notification_sent"
	IncidentStatusRemediation          IncidentStatus = "remediation"
	IncidentStatusClosed               IncidentStatus = "closed"
)

// IncidentSeverity represents the severity level of an incident
type IncidentSeverity string

const (
	IncidentSeverityCritical IncidentSeverity = "critical"
	IncidentSeverityHigh     IncidentSeverity = "high"
	IncidentSeverityMedium   IncidentSeverity = "medium"
	IncidentSeverityLow      IncidentSeverity = "low"
)

// MeasureType represents the type of corrective measure
type MeasureType string

const (
	MeasureTypeImmediate MeasureType = "immediate"
	MeasureTypeLongTerm  MeasureType = "long_term"
)

// MeasureStatus represents the status of a corrective measure
type MeasureStatus string

const (
	MeasureStatusPlanned    MeasureStatus = "planned"
	MeasureStatusInProgress MeasureStatus = "in_progress"
	MeasureStatusCompleted  MeasureStatus = "completed"
)

// NotificationStatus represents the status of a notification (authority or data subject)
type NotificationStatus string

const (
	NotificationStatusNotRequired NotificationStatus = "not_required"
	NotificationStatusPending     NotificationStatus = "pending"
	NotificationStatusSent        NotificationStatus = "sent"
	NotificationStatusConfirmed   NotificationStatus = "confirmed"
)

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

// Incident represents a security or data breach incident per DSGVO Art. 33/34
type Incident struct {
	ID       uuid.UUID `json:"id"`
	TenantID uuid.UUID `json:"tenant_id"`

	// Incident info
	Title       string           `json:"title"`
	Description string           `json:"description,omitempty"`
	Category    IncidentCategory `json:"category"`
	Status      IncidentStatus   `json:"status"`
	Severity    IncidentSeverity `json:"severity"`

	// Detection & reporting
	DetectedAt time.Time `json:"detected_at"`
	ReportedBy uuid.UUID `json:"reported_by"`

	// Affected scope
	AffectedDataCategories    []string `json:"affected_data_categories"`     // JSONB
	AffectedDataSubjectCount  int      `json:"affected_data_subject_count"`
	AffectedSystems           []string `json:"affected_systems"`             // JSONB

	// Assessments & notifications (JSONB embedded objects)
	RiskAssessment            *RiskAssessment            `json:"risk_assessment,omitempty"`
	AuthorityNotification     *AuthorityNotification     `json:"authority_notification,omitempty"`
	DataSubjectNotification   *DataSubjectNotification   `json:"data_subject_notification,omitempty"`

	// Resolution
	RootCause      string `json:"root_cause,omitempty"`
	LessonsLearned string `json:"lessons_learned,omitempty"`

	// Timeline (JSONB array)
	Timeline []TimelineEntry `json:"timeline"`

	// Audit
	CreatedAt time.Time  `json:"created_at"`
	UpdatedAt time.Time  `json:"updated_at"`
	ClosedAt  *time.Time `json:"closed_at,omitempty"`
}

// RiskAssessment contains the risk assessment for an incident
type RiskAssessment struct {
	Likelihood int       `json:"likelihood"` // 1-5
	Impact     int       `json:"impact"`     // 1-5
	RiskLevel  string    `json:"risk_level"` // critical, high, medium, low (auto-calculated)
	AssessedAt time.Time `json:"assessed_at"`
	AssessedBy uuid.UUID `json:"assessed_by"`
	Notes      string    `json:"notes,omitempty"`
}

// AuthorityNotification tracks the supervisory authority notification per DSGVO Art. 33
type AuthorityNotification struct {
	Status          NotificationStatus `json:"status"`
	Deadline        time.Time          `json:"deadline"`         // 72h from detected_at per Art. 33
	SubmittedAt     *time.Time         `json:"submitted_at,omitempty"`
	AuthorityName   string             `json:"authority_name,omitempty"`
	ReferenceNumber string             `json:"reference_number,omitempty"`
	ContactPerson   string             `json:"contact_person,omitempty"`
	Notes           string             `json:"notes,omitempty"`
}

// DataSubjectNotification tracks the data subject notification per DSGVO Art. 34
type DataSubjectNotification struct {
	Required         bool               `json:"required"`
	Status           NotificationStatus `json:"status"`
	SentAt           *time.Time         `json:"sent_at,omitempty"`
	AffectedCount    int                `json:"affected_count"`
	NotificationText string             `json:"notification_text,omitempty"`
	Channel          string             `json:"channel,omitempty"` // email, letter, website
}

// TimelineEntry represents a single event in the incident timeline
type TimelineEntry struct {
	Timestamp time.Time `json:"timestamp"`
	Action    string    `json:"action"`
	UserID    uuid.UUID `json:"user_id"`
	Details   string    `json:"details,omitempty"`
}

// IncidentMeasure represents a corrective or preventive measure for an incident
type IncidentMeasure struct {
	ID          uuid.UUID   `json:"id"`
	IncidentID  uuid.UUID   `json:"incident_id"`
	Title       string      `json:"title"`
	Description string      `json:"description,omitempty"`
	MeasureType MeasureType `json:"measure_type"`
	Status      MeasureStatus `json:"status"`
	Responsible string      `json:"responsible,omitempty"`
	DueDate     *time.Time  `json:"due_date,omitempty"`
	CompletedAt *time.Time  `json:"completed_at,omitempty"`
	CreatedAt   time.Time   `json:"created_at"`
}

// IncidentStatistics contains aggregated incident statistics for a tenant
type IncidentStatistics struct {
	TotalIncidents       int            `json:"total_incidents"`
	OpenIncidents        int            `json:"open_incidents"`
	ByStatus             map[string]int `json:"by_status"`
	BySeverity           map[string]int `json:"by_severity"`
	ByCategory           map[string]int `json:"by_category"`
	NotificationsPending int            `json:"notifications_pending"`
	AvgResolutionHours   float64        `json:"avg_resolution_hours"`
}

// ============================================================================
// API Request/Response Types
// ============================================================================

// CreateIncidentRequest is the API request for creating an incident
type CreateIncidentRequest struct {
	Title                    string           `json:"title" binding:"required"`
	Description              string           `json:"description,omitempty"`
	Category                 IncidentCategory `json:"category" binding:"required"`
	Severity                 IncidentSeverity `json:"severity" binding:"required"`
	DetectedAt               *time.Time       `json:"detected_at,omitempty"` // defaults to now
	AffectedDataCategories   []string         `json:"affected_data_categories,omitempty"`
	AffectedDataSubjectCount int              `json:"affected_data_subject_count,omitempty"`
	AffectedSystems          []string         `json:"affected_systems,omitempty"`
}

// UpdateIncidentRequest is the API request for updating an incident
type UpdateIncidentRequest struct {
	Title                    string           `json:"title,omitempty"`
	Description              string           `json:"description,omitempty"`
	Category                 IncidentCategory `json:"category,omitempty"`
	Status                   IncidentStatus   `json:"status,omitempty"`
	Severity                 IncidentSeverity `json:"severity,omitempty"`
	AffectedDataCategories   []string         `json:"affected_data_categories,omitempty"`
	AffectedDataSubjectCount *int             `json:"affected_data_subject_count,omitempty"`
	AffectedSystems          []string         `json:"affected_systems,omitempty"`
}

// RiskAssessmentRequest is the API request for assessing risk
type RiskAssessmentRequest struct {
	Likelihood int    `json:"likelihood" binding:"required,min=1,max=5"`
	Impact     int    `json:"impact" binding:"required,min=1,max=5"`
	Notes      string `json:"notes,omitempty"`
}

// SubmitAuthorityNotificationRequest is the API request for submitting authority notification
type SubmitAuthorityNotificationRequest struct {
	AuthorityName   string `json:"authority_name" binding:"required"`
	ContactPerson   string `json:"contact_person,omitempty"`
	ReferenceNumber string `json:"reference_number,omitempty"`
	Notes           string `json:"notes,omitempty"`
}

// NotifyDataSubjectsRequest is the API request for notifying data subjects
type NotifyDataSubjectsRequest struct {
	NotificationText string `json:"notification_text" binding:"required"`
	Channel          string `json:"channel" binding:"required"` // email, letter, website
	AffectedCount    int    `json:"affected_count,omitempty"`
}

// AddMeasureRequest is the API request for adding a corrective measure
type AddMeasureRequest struct {
	Title       string      `json:"title" binding:"required"`
	Description string      `json:"description,omitempty"`
	MeasureType MeasureType `json:"measure_type" binding:"required"`
	Responsible string      `json:"responsible,omitempty"`
	DueDate     *time.Time  `json:"due_date,omitempty"`
}

// CloseIncidentRequest is the API request for closing an incident
type CloseIncidentRequest struct {
	RootCause      string `json:"root_cause" binding:"required"`
	LessonsLearned string `json:"lessons_learned,omitempty"`
}

// AddTimelineEntryRequest is the API request for adding a timeline entry
type AddTimelineEntryRequest struct {
	Action  string `json:"action" binding:"required"`
	Details string `json:"details,omitempty"`
}

// IncidentListResponse is the API response for listing incidents
type IncidentListResponse struct {
	Incidents []Incident `json:"incidents"`
	Total     int        `json:"total"`
}

// IncidentFilters defines filters for listing incidents
type IncidentFilters struct {
	Status   IncidentStatus
	Severity IncidentSeverity
	Category IncidentCategory
	Limit    int
	Offset   int
}

// ============================================================================
// Helper Functions
// ============================================================================

// CalculateRiskLevel calculates the risk level from likelihood and impact scores.
// Risk score = likelihood * impact. Thresholds:
//   - critical: score >= 20
//   - high:     score >= 12
//   - medium:   score >= 6
//   - low:      score < 6
func CalculateRiskLevel(likelihood, impact int) string {
	score := likelihood * impact
	switch {
	case score >= 20:
		return "critical"
	case score >= 12:
		return "high"
	case score >= 6:
		return "medium"
	default:
		return "low"
	}
}

// Calculate72hDeadline calculates the 72-hour notification deadline per DSGVO Art. 33.
// The supervisory authority must be notified within 72 hours of becoming aware of a breach.
func Calculate72hDeadline(detectedAt time.Time) time.Time {
	return detectedAt.Add(72 * time.Hour)
}

// IsNotificationRequired determines whether authority notification is required
// based on the assessed risk level. Notification is required for critical and high risk.
func IsNotificationRequired(riskLevel string) bool {
	return riskLevel == "critical" || riskLevel == "high"
}
