package dsgvo

import (
	"context"
	"encoding/json"
	"time"

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

// Store handles DSGVO data persistence
type Store struct {
	pool *pgxpool.Pool
}

// NewStore creates a new DSGVO store
func NewStore(pool *pgxpool.Pool) *Store {
	return &Store{pool: pool}
}

// ============================================================================
// VVT - Verarbeitungsverzeichnis
// ============================================================================

// CreateProcessingActivity creates a new processing activity
func (s *Store) CreateProcessingActivity(ctx context.Context, pa *ProcessingActivity) error {
	pa.ID = uuid.New()
	pa.CreatedAt = time.Now().UTC()
	pa.UpdatedAt = pa.CreatedAt

	metadata, _ := json.Marshal(pa.Metadata)
	dataCategories, _ := json.Marshal(pa.DataCategories)
	dataSubjectCategories, _ := json.Marshal(pa.DataSubjectCategories)
	recipients, _ := json.Marshal(pa.Recipients)
	tomReference, _ := json.Marshal(pa.TOMReference)
	systems, _ := json.Marshal(pa.Systems)

	_, err := s.pool.Exec(ctx, `
		INSERT INTO dsgvo_processing_activities (
			id, tenant_id, namespace_id, name, description, purpose, legal_basis, legal_basis_details,
			data_categories, data_subject_categories, recipients, third_country_transfer, transfer_safeguards,
			retention_period, retention_policy_id, tom_reference, dsfa_required, dsfa_id,
			responsible_person, responsible_department, systems, status, metadata,
			created_at, updated_at, created_by, last_reviewed_at, next_review_at
		) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
	`, pa.ID, pa.TenantID, pa.NamespaceID, pa.Name, pa.Description, pa.Purpose, pa.LegalBasis, pa.LegalBasisDetails,
		dataCategories, dataSubjectCategories, recipients, pa.ThirdCountryTransfer, pa.TransferSafeguards,
		pa.RetentionPeriod, pa.RetentionPolicyID, tomReference, pa.DSFARequired, pa.DSFAID,
		pa.ResponsiblePerson, pa.ResponsibleDepartment, systems, pa.Status, metadata,
		pa.CreatedAt, pa.UpdatedAt, pa.CreatedBy, pa.LastReviewedAt, pa.NextReviewAt)

	return err
}

// GetProcessingActivity retrieves a processing activity by ID
func (s *Store) GetProcessingActivity(ctx context.Context, id uuid.UUID) (*ProcessingActivity, error) {
	var pa ProcessingActivity
	var metadata, dataCategories, dataSubjectCategories, recipients, tomReference, systems []byte

	err := s.pool.QueryRow(ctx, `
		SELECT id, tenant_id, namespace_id, name, description, purpose, legal_basis, legal_basis_details,
			data_categories, data_subject_categories, recipients, third_country_transfer, transfer_safeguards,
			retention_period, retention_policy_id, tom_reference, dsfa_required, dsfa_id,
			responsible_person, responsible_department, systems, status, metadata,
			created_at, updated_at, created_by, last_reviewed_at, next_review_at
		FROM dsgvo_processing_activities WHERE id = $1
	`, id).Scan(&pa.ID, &pa.TenantID, &pa.NamespaceID, &pa.Name, &pa.Description, &pa.Purpose, &pa.LegalBasis, &pa.LegalBasisDetails,
		&dataCategories, &dataSubjectCategories, &recipients, &pa.ThirdCountryTransfer, &pa.TransferSafeguards,
		&pa.RetentionPeriod, &pa.RetentionPolicyID, &tomReference, &pa.DSFARequired, &pa.DSFAID,
		&pa.ResponsiblePerson, &pa.ResponsibleDepartment, &systems, &pa.Status, &metadata,
		&pa.CreatedAt, &pa.UpdatedAt, &pa.CreatedBy, &pa.LastReviewedAt, &pa.NextReviewAt)

	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}

	json.Unmarshal(metadata, &pa.Metadata)
	json.Unmarshal(dataCategories, &pa.DataCategories)
	json.Unmarshal(dataSubjectCategories, &pa.DataSubjectCategories)
	json.Unmarshal(recipients, &pa.Recipients)
	json.Unmarshal(tomReference, &pa.TOMReference)
	json.Unmarshal(systems, &pa.Systems)

	return &pa, nil
}

// ListProcessingActivities lists processing activities for a tenant
func (s *Store) ListProcessingActivities(ctx context.Context, tenantID uuid.UUID, namespaceID *uuid.UUID) ([]ProcessingActivity, error) {
	query := `
		SELECT id, tenant_id, namespace_id, name, description, purpose, legal_basis, legal_basis_details,
			data_categories, data_subject_categories, recipients, third_country_transfer, transfer_safeguards,
			retention_period, retention_policy_id, tom_reference, dsfa_required, dsfa_id,
			responsible_person, responsible_department, systems, status, metadata,
			created_at, updated_at, created_by, last_reviewed_at, next_review_at
		FROM dsgvo_processing_activities WHERE tenant_id = $1`

	args := []interface{}{tenantID}
	if namespaceID != nil {
		query += " AND namespace_id = $2"
		args = append(args, *namespaceID)
	}
	query += " ORDER BY name"

	rows, err := s.pool.Query(ctx, query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var activities []ProcessingActivity
	for rows.Next() {
		var pa ProcessingActivity
		var metadata, dataCategories, dataSubjectCategories, recipients, tomReference, systems []byte

		err := rows.Scan(&pa.ID, &pa.TenantID, &pa.NamespaceID, &pa.Name, &pa.Description, &pa.Purpose, &pa.LegalBasis, &pa.LegalBasisDetails,
			&dataCategories, &dataSubjectCategories, &recipients, &pa.ThirdCountryTransfer, &pa.TransferSafeguards,
			&pa.RetentionPeriod, &pa.RetentionPolicyID, &tomReference, &pa.DSFARequired, &pa.DSFAID,
			&pa.ResponsiblePerson, &pa.ResponsibleDepartment, &systems, &pa.Status, &metadata,
			&pa.CreatedAt, &pa.UpdatedAt, &pa.CreatedBy, &pa.LastReviewedAt, &pa.NextReviewAt)
		if err != nil {
			return nil, err
		}

		json.Unmarshal(metadata, &pa.Metadata)
		json.Unmarshal(dataCategories, &pa.DataCategories)
		json.Unmarshal(dataSubjectCategories, &pa.DataSubjectCategories)
		json.Unmarshal(recipients, &pa.Recipients)
		json.Unmarshal(tomReference, &pa.TOMReference)
		json.Unmarshal(systems, &pa.Systems)

		activities = append(activities, pa)
	}

	return activities, nil
}

// UpdateProcessingActivity updates a processing activity
func (s *Store) UpdateProcessingActivity(ctx context.Context, pa *ProcessingActivity) error {
	pa.UpdatedAt = time.Now().UTC()

	metadata, _ := json.Marshal(pa.Metadata)
	dataCategories, _ := json.Marshal(pa.DataCategories)
	dataSubjectCategories, _ := json.Marshal(pa.DataSubjectCategories)
	recipients, _ := json.Marshal(pa.Recipients)
	tomReference, _ := json.Marshal(pa.TOMReference)
	systems, _ := json.Marshal(pa.Systems)

	_, err := s.pool.Exec(ctx, `
		UPDATE dsgvo_processing_activities SET
			name = $2, description = $3, purpose = $4, legal_basis = $5, legal_basis_details = $6,
			data_categories = $7, data_subject_categories = $8, recipients = $9, third_country_transfer = $10,
			transfer_safeguards = $11, retention_period = $12, retention_policy_id = $13, tom_reference = $14,
			dsfa_required = $15, dsfa_id = $16, responsible_person = $17, responsible_department = $18,
			systems = $19, status = $20, metadata = $21, updated_at = $22, last_reviewed_at = $23, next_review_at = $24
		WHERE id = $1
	`, pa.ID, pa.Name, pa.Description, pa.Purpose, pa.LegalBasis, pa.LegalBasisDetails,
		dataCategories, dataSubjectCategories, recipients, pa.ThirdCountryTransfer,
		pa.TransferSafeguards, pa.RetentionPeriod, pa.RetentionPolicyID, tomReference,
		pa.DSFARequired, pa.DSFAID, pa.ResponsiblePerson, pa.ResponsibleDepartment,
		systems, pa.Status, metadata, pa.UpdatedAt, pa.LastReviewedAt, pa.NextReviewAt)

	return err
}

// DeleteProcessingActivity deletes a processing activity
func (s *Store) DeleteProcessingActivity(ctx context.Context, id uuid.UUID) error {
	_, err := s.pool.Exec(ctx, "DELETE FROM dsgvo_processing_activities WHERE id = $1", id)
	return err
}

// ============================================================================
// TOM - Technische und Organisatorische Maßnahmen
// ============================================================================

// CreateTOM creates a new TOM entry
func (s *Store) CreateTOM(ctx context.Context, tom *TOM) error {
	tom.ID = uuid.New()
	tom.CreatedAt = time.Now().UTC()
	tom.UpdatedAt = tom.CreatedAt

	metadata, _ := json.Marshal(tom.Metadata)
	relatedControls, _ := json.Marshal(tom.RelatedControls)

	_, err := s.pool.Exec(ctx, `
		INSERT INTO dsgvo_tom (
			id, tenant_id, namespace_id, category, subcategory, name, description, type,
			implementation_status, implemented_at, verified_at, verified_by, effectiveness_rating,
			documentation, responsible_person, responsible_department, review_frequency,
			last_review_at, next_review_at, related_controls, metadata, created_at, updated_at, created_by
		) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
	`, tom.ID, tom.TenantID, tom.NamespaceID, tom.Category, tom.Subcategory, tom.Name, tom.Description, tom.Type,
		tom.ImplementationStatus, tom.ImplementedAt, tom.VerifiedAt, tom.VerifiedBy, tom.EffectivenessRating,
		tom.Documentation, tom.ResponsiblePerson, tom.ResponsibleDepartment, tom.ReviewFrequency,
		tom.LastReviewAt, tom.NextReviewAt, relatedControls, metadata, tom.CreatedAt, tom.UpdatedAt, tom.CreatedBy)

	return err
}

// GetTOM retrieves a TOM by ID
func (s *Store) GetTOM(ctx context.Context, id uuid.UUID) (*TOM, error) {
	var tom TOM
	var metadata, relatedControls []byte

	err := s.pool.QueryRow(ctx, `
		SELECT id, tenant_id, namespace_id, category, subcategory, name, description, type,
			implementation_status, implemented_at, verified_at, verified_by, effectiveness_rating,
			documentation, responsible_person, responsible_department, review_frequency,
			last_review_at, next_review_at, related_controls, metadata, created_at, updated_at, created_by
		FROM dsgvo_tom WHERE id = $1
	`, id).Scan(&tom.ID, &tom.TenantID, &tom.NamespaceID, &tom.Category, &tom.Subcategory, &tom.Name, &tom.Description, &tom.Type,
		&tom.ImplementationStatus, &tom.ImplementedAt, &tom.VerifiedAt, &tom.VerifiedBy, &tom.EffectivenessRating,
		&tom.Documentation, &tom.ResponsiblePerson, &tom.ResponsibleDepartment, &tom.ReviewFrequency,
		&tom.LastReviewAt, &tom.NextReviewAt, &relatedControls, &metadata, &tom.CreatedAt, &tom.UpdatedAt, &tom.CreatedBy)

	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}

	json.Unmarshal(metadata, &tom.Metadata)
	json.Unmarshal(relatedControls, &tom.RelatedControls)

	return &tom, nil
}

// ListTOMs lists TOMs for a tenant
func (s *Store) ListTOMs(ctx context.Context, tenantID uuid.UUID, category string) ([]TOM, error) {
	query := `
		SELECT id, tenant_id, namespace_id, category, subcategory, name, description, type,
			implementation_status, implemented_at, verified_at, verified_by, effectiveness_rating,
			documentation, responsible_person, responsible_department, review_frequency,
			last_review_at, next_review_at, related_controls, metadata, created_at, updated_at, created_by
		FROM dsgvo_tom WHERE tenant_id = $1`

	args := []interface{}{tenantID}
	if category != "" {
		query += " AND category = $2"
		args = append(args, category)
	}
	query += " ORDER BY category, name"

	rows, err := s.pool.Query(ctx, query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var toms []TOM
	for rows.Next() {
		var tom TOM
		var metadata, relatedControls []byte

		err := rows.Scan(&tom.ID, &tom.TenantID, &tom.NamespaceID, &tom.Category, &tom.Subcategory, &tom.Name, &tom.Description, &tom.Type,
			&tom.ImplementationStatus, &tom.ImplementedAt, &tom.VerifiedAt, &tom.VerifiedBy, &tom.EffectivenessRating,
			&tom.Documentation, &tom.ResponsiblePerson, &tom.ResponsibleDepartment, &tom.ReviewFrequency,
			&tom.LastReviewAt, &tom.NextReviewAt, &relatedControls, &metadata, &tom.CreatedAt, &tom.UpdatedAt, &tom.CreatedBy)
		if err != nil {
			return nil, err
		}

		json.Unmarshal(metadata, &tom.Metadata)
		json.Unmarshal(relatedControls, &tom.RelatedControls)

		toms = append(toms, tom)
	}

	return toms, nil
}

// ============================================================================
// DSR - Data Subject Requests
// ============================================================================

// CreateDSR creates a new DSR
func (s *Store) CreateDSR(ctx context.Context, dsr *DSR) error {
	dsr.ID = uuid.New()
	dsr.CreatedAt = time.Now().UTC()
	dsr.UpdatedAt = dsr.CreatedAt

	// Default deadline: 1 month from receipt
	if dsr.DeadlineAt.IsZero() {
		dsr.DeadlineAt = dsr.ReceivedAt.AddDate(0, 1, 0)
	}

	metadata, _ := json.Marshal(dsr.Metadata)
	affectedSystems, _ := json.Marshal(dsr.AffectedSystems)

	_, err := s.pool.Exec(ctx, `
		INSERT INTO dsgvo_dsr (
			id, tenant_id, namespace_id, request_type, status, subject_name, subject_email,
			subject_identifier, request_description, request_channel, received_at, verified_at,
			verification_method, deadline_at, extended_deadline_at, extension_reason,
			completed_at, response_sent, response_sent_at, response_method, rejection_reason,
			notes, affected_systems, assigned_to, metadata, created_at, updated_at, created_by
		) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28)
	`, dsr.ID, dsr.TenantID, dsr.NamespaceID, dsr.RequestType, dsr.Status, dsr.SubjectName, dsr.SubjectEmail,
		dsr.SubjectIdentifier, dsr.RequestDescription, dsr.RequestChannel, dsr.ReceivedAt, dsr.VerifiedAt,
		dsr.VerificationMethod, dsr.DeadlineAt, dsr.ExtendedDeadlineAt, dsr.ExtensionReason,
		dsr.CompletedAt, dsr.ResponseSent, dsr.ResponseSentAt, dsr.ResponseMethod, dsr.RejectionReason,
		dsr.Notes, affectedSystems, dsr.AssignedTo, metadata, dsr.CreatedAt, dsr.UpdatedAt, dsr.CreatedBy)

	return err
}

// GetDSR retrieves a DSR by ID
func (s *Store) GetDSR(ctx context.Context, id uuid.UUID) (*DSR, error) {
	var dsr DSR
	var metadata, affectedSystems []byte

	err := s.pool.QueryRow(ctx, `
		SELECT id, tenant_id, namespace_id, request_type, status, subject_name, subject_email,
			subject_identifier, request_description, request_channel, received_at, verified_at,
			verification_method, deadline_at, extended_deadline_at, extension_reason,
			completed_at, response_sent, response_sent_at, response_method, rejection_reason,
			notes, affected_systems, assigned_to, metadata, created_at, updated_at, created_by
		FROM dsgvo_dsr WHERE id = $1
	`, id).Scan(&dsr.ID, &dsr.TenantID, &dsr.NamespaceID, &dsr.RequestType, &dsr.Status, &dsr.SubjectName, &dsr.SubjectEmail,
		&dsr.SubjectIdentifier, &dsr.RequestDescription, &dsr.RequestChannel, &dsr.ReceivedAt, &dsr.VerifiedAt,
		&dsr.VerificationMethod, &dsr.DeadlineAt, &dsr.ExtendedDeadlineAt, &dsr.ExtensionReason,
		&dsr.CompletedAt, &dsr.ResponseSent, &dsr.ResponseSentAt, &dsr.ResponseMethod, &dsr.RejectionReason,
		&dsr.Notes, &affectedSystems, &dsr.AssignedTo, &metadata, &dsr.CreatedAt, &dsr.UpdatedAt, &dsr.CreatedBy)

	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}

	json.Unmarshal(metadata, &dsr.Metadata)
	json.Unmarshal(affectedSystems, &dsr.AffectedSystems)

	return &dsr, nil
}

// ListDSRs lists DSRs for a tenant with optional filters
func (s *Store) ListDSRs(ctx context.Context, tenantID uuid.UUID, status string, requestType string) ([]DSR, error) {
	query := `
		SELECT id, tenant_id, namespace_id, request_type, status, subject_name, subject_email,
			subject_identifier, request_description, request_channel, received_at, verified_at,
			verification_method, deadline_at, extended_deadline_at, extension_reason,
			completed_at, response_sent, response_sent_at, response_method, rejection_reason,
			notes, affected_systems, assigned_to, metadata, created_at, updated_at, created_by
		FROM dsgvo_dsr WHERE tenant_id = $1`

	args := []interface{}{tenantID}
	argIdx := 2

	if status != "" {
		query += " AND status = $" + string(rune('0'+argIdx))
		args = append(args, status)
		argIdx++
	}
	if requestType != "" {
		query += " AND request_type = $" + string(rune('0'+argIdx))
		args = append(args, requestType)
	}
	query += " ORDER BY deadline_at ASC"

	rows, err := s.pool.Query(ctx, query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var dsrs []DSR
	for rows.Next() {
		var dsr DSR
		var metadata, affectedSystems []byte

		err := rows.Scan(&dsr.ID, &dsr.TenantID, &dsr.NamespaceID, &dsr.RequestType, &dsr.Status, &dsr.SubjectName, &dsr.SubjectEmail,
			&dsr.SubjectIdentifier, &dsr.RequestDescription, &dsr.RequestChannel, &dsr.ReceivedAt, &dsr.VerifiedAt,
			&dsr.VerificationMethod, &dsr.DeadlineAt, &dsr.ExtendedDeadlineAt, &dsr.ExtensionReason,
			&dsr.CompletedAt, &dsr.ResponseSent, &dsr.ResponseSentAt, &dsr.ResponseMethod, &dsr.RejectionReason,
			&dsr.Notes, &affectedSystems, &dsr.AssignedTo, &metadata, &dsr.CreatedAt, &dsr.UpdatedAt, &dsr.CreatedBy)
		if err != nil {
			return nil, err
		}

		json.Unmarshal(metadata, &dsr.Metadata)
		json.Unmarshal(affectedSystems, &dsr.AffectedSystems)

		dsrs = append(dsrs, dsr)
	}

	return dsrs, nil
}

// UpdateDSR updates a DSR
func (s *Store) UpdateDSR(ctx context.Context, dsr *DSR) error {
	dsr.UpdatedAt = time.Now().UTC()

	metadata, _ := json.Marshal(dsr.Metadata)
	affectedSystems, _ := json.Marshal(dsr.AffectedSystems)

	_, err := s.pool.Exec(ctx, `
		UPDATE dsgvo_dsr SET
			status = $2, verified_at = $3, verification_method = $4, extended_deadline_at = $5,
			extension_reason = $6, completed_at = $7, response_sent = $8, response_sent_at = $9,
			response_method = $10, rejection_reason = $11, notes = $12, affected_systems = $13,
			assigned_to = $14, metadata = $15, updated_at = $16
		WHERE id = $1
	`, dsr.ID, dsr.Status, dsr.VerifiedAt, dsr.VerificationMethod, dsr.ExtendedDeadlineAt,
		dsr.ExtensionReason, dsr.CompletedAt, dsr.ResponseSent, dsr.ResponseSentAt,
		dsr.ResponseMethod, dsr.RejectionReason, dsr.Notes, affectedSystems,
		dsr.AssignedTo, metadata, dsr.UpdatedAt)

	return err
}

// ============================================================================
// Retention Policies
// ============================================================================

// CreateRetentionPolicy creates a new retention policy
func (s *Store) CreateRetentionPolicy(ctx context.Context, rp *RetentionPolicy) error {
	rp.ID = uuid.New()
	rp.CreatedAt = time.Now().UTC()
	rp.UpdatedAt = rp.CreatedAt

	metadata, _ := json.Marshal(rp.Metadata)
	applicableSystems, _ := json.Marshal(rp.ApplicableSystems)

	_, err := s.pool.Exec(ctx, `
		INSERT INTO dsgvo_retention_policies (
			id, tenant_id, namespace_id, name, description, data_category, retention_period_days,
			retention_period_text, legal_basis, legal_reference, deletion_method, deletion_procedure,
			exception_criteria, applicable_systems, responsible_person, responsible_department,
			status, last_review_at, next_review_at, metadata, created_at, updated_at, created_by
		) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23)
	`, rp.ID, rp.TenantID, rp.NamespaceID, rp.Name, rp.Description, rp.DataCategory, rp.RetentionPeriodDays,
		rp.RetentionPeriodText, rp.LegalBasis, rp.LegalReference, rp.DeletionMethod, rp.DeletionProcedure,
		rp.ExceptionCriteria, applicableSystems, rp.ResponsiblePerson, rp.ResponsibleDepartment,
		rp.Status, rp.LastReviewAt, rp.NextReviewAt, metadata, rp.CreatedAt, rp.UpdatedAt, rp.CreatedBy)

	return err
}

// ListRetentionPolicies lists retention policies for a tenant
func (s *Store) ListRetentionPolicies(ctx context.Context, tenantID uuid.UUID) ([]RetentionPolicy, error) {
	rows, err := s.pool.Query(ctx, `
		SELECT id, tenant_id, namespace_id, name, description, data_category, retention_period_days,
			retention_period_text, legal_basis, legal_reference, deletion_method, deletion_procedure,
			exception_criteria, applicable_systems, responsible_person, responsible_department,
			status, last_review_at, next_review_at, metadata, created_at, updated_at, created_by
		FROM dsgvo_retention_policies WHERE tenant_id = $1 ORDER BY name
	`, tenantID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var policies []RetentionPolicy
	for rows.Next() {
		var rp RetentionPolicy
		var metadata, applicableSystems []byte

		err := rows.Scan(&rp.ID, &rp.TenantID, &rp.NamespaceID, &rp.Name, &rp.Description, &rp.DataCategory, &rp.RetentionPeriodDays,
			&rp.RetentionPeriodText, &rp.LegalBasis, &rp.LegalReference, &rp.DeletionMethod, &rp.DeletionProcedure,
			&rp.ExceptionCriteria, &applicableSystems, &rp.ResponsiblePerson, &rp.ResponsibleDepartment,
			&rp.Status, &rp.LastReviewAt, &rp.NextReviewAt, &metadata, &rp.CreatedAt, &rp.UpdatedAt, &rp.CreatedBy)
		if err != nil {
			return nil, err
		}

		json.Unmarshal(metadata, &rp.Metadata)
		json.Unmarshal(applicableSystems, &rp.ApplicableSystems)

		policies = append(policies, rp)
	}

	return policies, nil
}

// ============================================================================
// DSFA - Datenschutz-Folgenabschätzung
// ============================================================================

// CreateDSFA creates a new DSFA
func (s *Store) CreateDSFA(ctx context.Context, dsfa *DSFA) error {
	dsfa.ID = uuid.New()
	dsfa.CreatedAt = time.Now().UTC()
	dsfa.UpdatedAt = dsfa.CreatedAt

	metadata, _ := json.Marshal(dsfa.Metadata)
	risks, _ := json.Marshal(dsfa.Risks)
	mitigations, _ := json.Marshal(dsfa.Mitigations)

	_, err := s.pool.Exec(ctx, `
		INSERT INTO dsgvo_dsfa (
			id, tenant_id, namespace_id, processing_activity_id, name, description,
			processing_description, necessity_assessment, proportionality_assessment,
			risks, mitigations, dpo_consulted, dpo_opinion, authority_consulted, authority_reference,
			status, overall_risk_level, conclusion, metadata, created_at, updated_at, created_by,
			approved_by, approved_at
		) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
	`, dsfa.ID, dsfa.TenantID, dsfa.NamespaceID, dsfa.ProcessingActivityID, dsfa.Name, dsfa.Description,
		dsfa.ProcessingDescription, dsfa.NecessityAssessment, dsfa.ProportionalityAssment,
		risks, mitigations, dsfa.DPOConsulted, dsfa.DPOOpinion, dsfa.AuthorityConsulted, dsfa.AuthorityReference,
		dsfa.Status, dsfa.OverallRiskLevel, dsfa.Conclusion, metadata, dsfa.CreatedAt, dsfa.UpdatedAt, dsfa.CreatedBy,
		dsfa.ApprovedBy, dsfa.ApprovedAt)

	return err
}

// GetDSFA retrieves a DSFA by ID
func (s *Store) GetDSFA(ctx context.Context, id uuid.UUID) (*DSFA, error) {
	var dsfa DSFA
	var metadata, risks, mitigations []byte

	err := s.pool.QueryRow(ctx, `
		SELECT id, tenant_id, namespace_id, processing_activity_id, name, description,
			processing_description, necessity_assessment, proportionality_assessment,
			risks, mitigations, dpo_consulted, dpo_opinion, authority_consulted, authority_reference,
			status, overall_risk_level, conclusion, metadata, created_at, updated_at, created_by,
			approved_by, approved_at
		FROM dsgvo_dsfa WHERE id = $1
	`, id).Scan(&dsfa.ID, &dsfa.TenantID, &dsfa.NamespaceID, &dsfa.ProcessingActivityID, &dsfa.Name, &dsfa.Description,
		&dsfa.ProcessingDescription, &dsfa.NecessityAssessment, &dsfa.ProportionalityAssment,
		&risks, &mitigations, &dsfa.DPOConsulted, &dsfa.DPOOpinion, &dsfa.AuthorityConsulted, &dsfa.AuthorityReference,
		&dsfa.Status, &dsfa.OverallRiskLevel, &dsfa.Conclusion, &metadata, &dsfa.CreatedAt, &dsfa.UpdatedAt, &dsfa.CreatedBy,
		&dsfa.ApprovedBy, &dsfa.ApprovedAt)

	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}

	json.Unmarshal(metadata, &dsfa.Metadata)
	json.Unmarshal(risks, &dsfa.Risks)
	json.Unmarshal(mitigations, &dsfa.Mitigations)

	return &dsfa, nil
}

// ListDSFAs lists DSFAs for a tenant
func (s *Store) ListDSFAs(ctx context.Context, tenantID uuid.UUID, status string) ([]DSFA, error) {
	query := `
		SELECT id, tenant_id, namespace_id, processing_activity_id, name, description,
			processing_description, necessity_assessment, proportionality_assessment,
			risks, mitigations, dpo_consulted, dpo_opinion, authority_consulted, authority_reference,
			status, overall_risk_level, conclusion, metadata, created_at, updated_at, created_by,
			approved_by, approved_at
		FROM dsgvo_dsfa WHERE tenant_id = $1`

	args := []interface{}{tenantID}
	if status != "" {
		query += " AND status = $2"
		args = append(args, status)
	}
	query += " ORDER BY created_at DESC"

	rows, err := s.pool.Query(ctx, query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var dsfas []DSFA
	for rows.Next() {
		var dsfa DSFA
		var metadata, risks, mitigations []byte

		err := rows.Scan(&dsfa.ID, &dsfa.TenantID, &dsfa.NamespaceID, &dsfa.ProcessingActivityID, &dsfa.Name, &dsfa.Description,
			&dsfa.ProcessingDescription, &dsfa.NecessityAssessment, &dsfa.ProportionalityAssment,
			&risks, &mitigations, &dsfa.DPOConsulted, &dsfa.DPOOpinion, &dsfa.AuthorityConsulted, &dsfa.AuthorityReference,
			&dsfa.Status, &dsfa.OverallRiskLevel, &dsfa.Conclusion, &metadata, &dsfa.CreatedAt, &dsfa.UpdatedAt, &dsfa.CreatedBy,
			&dsfa.ApprovedBy, &dsfa.ApprovedAt)
		if err != nil {
			return nil, err
		}

		json.Unmarshal(metadata, &dsfa.Metadata)
		json.Unmarshal(risks, &dsfa.Risks)
		json.Unmarshal(mitigations, &dsfa.Mitigations)

		dsfas = append(dsfas, dsfa)
	}

	return dsfas, nil
}

// UpdateDSFA updates a DSFA
func (s *Store) UpdateDSFA(ctx context.Context, dsfa *DSFA) error {
	dsfa.UpdatedAt = time.Now().UTC()

	metadata, _ := json.Marshal(dsfa.Metadata)
	risks, _ := json.Marshal(dsfa.Risks)
	mitigations, _ := json.Marshal(dsfa.Mitigations)

	_, err := s.pool.Exec(ctx, `
		UPDATE dsgvo_dsfa SET
			name = $2, description = $3, processing_description = $4,
			necessity_assessment = $5, proportionality_assessment = $6,
			risks = $7, mitigations = $8, dpo_consulted = $9, dpo_opinion = $10,
			authority_consulted = $11, authority_reference = $12, status = $13,
			overall_risk_level = $14, conclusion = $15, metadata = $16, updated_at = $17,
			approved_by = $18, approved_at = $19
		WHERE id = $1
	`, dsfa.ID, dsfa.Name, dsfa.Description, dsfa.ProcessingDescription,
		dsfa.NecessityAssessment, dsfa.ProportionalityAssment,
		risks, mitigations, dsfa.DPOConsulted, dsfa.DPOOpinion,
		dsfa.AuthorityConsulted, dsfa.AuthorityReference, dsfa.Status,
		dsfa.OverallRiskLevel, dsfa.Conclusion, metadata, dsfa.UpdatedAt,
		dsfa.ApprovedBy, dsfa.ApprovedAt)

	return err
}

// DeleteDSFA deletes a DSFA
func (s *Store) DeleteDSFA(ctx context.Context, id uuid.UUID) error {
	_, err := s.pool.Exec(ctx, "DELETE FROM dsgvo_dsfa WHERE id = $1", id)
	return err
}

// ============================================================================
// Statistics
// ============================================================================

// DSGVOStats contains DSGVO module statistics
type DSGVOStats struct {
	ProcessingActivities int `json:"processing_activities"`
	ActiveProcessings    int `json:"active_processings"`
	TOMsImplemented      int `json:"toms_implemented"`
	TOMsPlanned          int `json:"toms_planned"`
	OpenDSRs             int `json:"open_dsrs"`
	OverdueDSRs          int `json:"overdue_dsrs"`
	RetentionPolicies    int `json:"retention_policies"`
	DSFAsCompleted       int `json:"dsfas_completed"`
}

// GetStats returns DSGVO statistics for a tenant
func (s *Store) GetStats(ctx context.Context, tenantID uuid.UUID) (*DSGVOStats, error) {
	stats := &DSGVOStats{}

	// Processing Activities
	s.pool.QueryRow(ctx, "SELECT COUNT(*) FROM dsgvo_processing_activities WHERE tenant_id = $1", tenantID).Scan(&stats.ProcessingActivities)
	s.pool.QueryRow(ctx, "SELECT COUNT(*) FROM dsgvo_processing_activities WHERE tenant_id = $1 AND status = 'active'", tenantID).Scan(&stats.ActiveProcessings)

	// TOMs
	s.pool.QueryRow(ctx, "SELECT COUNT(*) FROM dsgvo_tom WHERE tenant_id = $1 AND implementation_status = 'implemented'", tenantID).Scan(&stats.TOMsImplemented)
	s.pool.QueryRow(ctx, "SELECT COUNT(*) FROM dsgvo_tom WHERE tenant_id = $1 AND implementation_status IN ('planned', 'in_progress')", tenantID).Scan(&stats.TOMsPlanned)

	// DSRs
	s.pool.QueryRow(ctx, "SELECT COUNT(*) FROM dsgvo_dsr WHERE tenant_id = $1 AND status NOT IN ('completed', 'rejected')", tenantID).Scan(&stats.OpenDSRs)
	s.pool.QueryRow(ctx, "SELECT COUNT(*) FROM dsgvo_dsr WHERE tenant_id = $1 AND status NOT IN ('completed', 'rejected') AND deadline_at < NOW()", tenantID).Scan(&stats.OverdueDSRs)

	// Retention Policies
	s.pool.QueryRow(ctx, "SELECT COUNT(*) FROM dsgvo_retention_policies WHERE tenant_id = $1 AND status = 'active'", tenantID).Scan(&stats.RetentionPolicies)

	// DSFAs
	s.pool.QueryRow(ctx, "SELECT COUNT(*) FROM dsgvo_dsfa WHERE tenant_id = $1 AND status = 'approved'", tenantID).Scan(&stats.DSFAsCompleted)

	return stats, nil
}
