"""add_comprehensive_gdpr_tables

Revision ID: 7a899ef55e3b
Revises: dbafe747c931
Create Date: 2025-12-01 04:10:25.699589

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql


# revision identifiers, used by Alembic.
revision = '7a899ef55e3b'
down_revision = 'dbafe747c931'
branch_labels = None
depends_on = None


def upgrade() -> None:
    # Consent table
    op.create_table(
        'consents',
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.Column('user_id', sa.Integer(), nullable=False),
        sa.Column('consent_type', sa.Enum('marketing', 'analytics', 'necessary', 'preferences', 'third_party_sharing', 'profiling', 'automated_decision_making', name='consenttype'), nullable=False),
        sa.Column('status', sa.Enum('granted', 'withdrawn', 'pending', 'expired', name='consentstatus'), nullable=False),
        sa.Column('granted_at', sa.DateTime(), nullable=True),
        sa.Column('withdrawn_at', sa.DateTime(), nullable=True),
        sa.Column('expires_at', sa.DateTime(), nullable=True),
        sa.Column('legal_basis', sa.String(length=100), nullable=True),
        sa.Column('consent_method', sa.String(length=50), nullable=True),
        sa.Column('consent_version', sa.String(length=20), nullable=True),
        sa.Column('ip_address', sa.String(length=45), nullable=True),
        sa.Column('user_agent', sa.String(length=255), nullable=True),
        sa.Column('source', sa.String(length=100), nullable=True),
        sa.Column('extra_metadata', sa.JSON(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=False),
        sa.Column('updated_at', sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_consents_id'), 'consents', ['id'], unique=False)
    op.create_index(op.f('ix_consents_user_id'), 'consents', ['user_id'], unique=False)
    op.create_index(op.f('ix_consents_consent_type'), 'consents', ['consent_type'], unique=False)
    op.create_index(op.f('ix_consents_status'), 'consents', ['status'], unique=False)
    op.create_index(op.f('ix_consents_created_at'), 'consents', ['created_at'], unique=False)
    
    # Data processing records table
    op.create_table(
        'data_processing_records',
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.Column('processing_category', sa.Enum('collection', 'storage', 'usage', 'sharing', 'deletion', 'anonymization', 'transfer', name='processingcategory'), nullable=False),
        sa.Column('legal_basis', sa.Enum('consent', 'contract', 'legal_obligation', 'vital_interests', 'public_task', 'legitimate_interests', name='legalbasis'), nullable=False),
        sa.Column('purpose', sa.Text(), nullable=False),
        sa.Column('data_categories', sa.JSON(), nullable=True),
        sa.Column('data_subjects', sa.JSON(), nullable=True),
        sa.Column('recipients', sa.JSON(), nullable=True),
        sa.Column('third_parties', sa.JSON(), nullable=True),
        sa.Column('transfers_to_third_countries', sa.Boolean(), nullable=False),
        sa.Column('transfer_countries', sa.JSON(), nullable=True),
        sa.Column('safeguards', sa.Text(), nullable=True),
        sa.Column('retention_period', sa.String(length=100), nullable=True),
        sa.Column('retention_criteria', sa.Text(), nullable=True),
        sa.Column('security_measures', sa.Text(), nullable=True),
        sa.Column('user_id', sa.Integer(), nullable=True),
        sa.Column('related_booking_id', sa.Integer(), nullable=True),
        sa.Column('related_payment_id', sa.Integer(), nullable=True),
        sa.Column('processed_by', sa.Integer(), nullable=True),
        sa.Column('processing_timestamp', sa.DateTime(), nullable=False),
        sa.Column('extra_metadata', sa.JSON(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(['processed_by'], ['users.id'], ),
        sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_data_processing_records_id'), 'data_processing_records', ['id'], unique=False)
    op.create_index(op.f('ix_data_processing_records_processing_category'), 'data_processing_records', ['processing_category'], unique=False)
    op.create_index(op.f('ix_data_processing_records_legal_basis'), 'data_processing_records', ['legal_basis'], unique=False)
    op.create_index(op.f('ix_data_processing_records_user_id'), 'data_processing_records', ['user_id'], unique=False)
    op.create_index(op.f('ix_data_processing_records_processing_timestamp'), 'data_processing_records', ['processing_timestamp'], unique=False)
    op.create_index(op.f('ix_data_processing_records_created_at'), 'data_processing_records', ['created_at'], unique=False)
    
    # Data breaches table
    op.create_table(
        'data_breaches',
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.Column('breach_type', sa.Enum('confidentiality', 'integrity', 'availability', name='breachtype'), nullable=False),
        sa.Column('status', sa.Enum('detected', 'investigating', 'contained', 'reported_to_authority', 'notified_data_subjects', 'resolved', name='breachstatus'), nullable=False),
        sa.Column('description', sa.Text(), nullable=False),
        sa.Column('affected_data_categories', sa.JSON(), nullable=True),
        sa.Column('affected_data_subjects', sa.JSON(), nullable=True),
        sa.Column('detected_at', sa.DateTime(), nullable=False),
        sa.Column('occurred_at', sa.DateTime(), nullable=True),
        sa.Column('contained_at', sa.DateTime(), nullable=True),
        sa.Column('reported_to_authority_at', sa.DateTime(), nullable=True),
        sa.Column('authority_reference', sa.String(length=255), nullable=True),
        sa.Column('notified_data_subjects_at', sa.DateTime(), nullable=True),
        sa.Column('notification_method', sa.String(length=100), nullable=True),
        sa.Column('likely_consequences', sa.Text(), nullable=True),
        sa.Column('measures_proposed', sa.Text(), nullable=True),
        sa.Column('risk_level', sa.String(length=20), nullable=True),
        sa.Column('reported_by', sa.Integer(), nullable=False),
        sa.Column('investigated_by', sa.Integer(), nullable=True),
        sa.Column('extra_metadata', sa.JSON(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=False),
        sa.Column('updated_at', sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(['investigated_by'], ['users.id'], ),
        sa.ForeignKeyConstraint(['reported_by'], ['users.id'], ),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_data_breaches_id'), 'data_breaches', ['id'], unique=False)
    op.create_index(op.f('ix_data_breaches_breach_type'), 'data_breaches', ['breach_type'], unique=False)
    op.create_index(op.f('ix_data_breaches_status'), 'data_breaches', ['status'], unique=False)
    op.create_index(op.f('ix_data_breaches_detected_at'), 'data_breaches', ['detected_at'], unique=False)
    
    # Retention rules table
    op.create_table(
        'retention_rules',
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.Column('data_category', sa.String(length=100), nullable=False),
        sa.Column('retention_period_days', sa.Integer(), nullable=False),
        sa.Column('retention_period_months', sa.Integer(), nullable=True),
        sa.Column('retention_period_years', sa.Integer(), nullable=True),
        sa.Column('legal_basis', sa.Text(), nullable=True),
        sa.Column('legal_requirement', sa.Text(), nullable=True),
        sa.Column('action_after_retention', sa.String(length=50), nullable=False),
        sa.Column('conditions', sa.JSON(), nullable=True),
        sa.Column('is_active', sa.Boolean(), nullable=False),
        sa.Column('description', sa.Text(), nullable=True),
        sa.Column('created_by', sa.Integer(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=False),
        sa.Column('updated_at', sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('data_category')
    )
    op.create_index(op.f('ix_retention_rules_id'), 'retention_rules', ['id'], unique=False)
    op.create_index(op.f('ix_retention_rules_data_category'), 'retention_rules', ['data_category'], unique=True)
    op.create_index(op.f('ix_retention_rules_is_active'), 'retention_rules', ['is_active'], unique=False)
    
    # Data retention logs table
    op.create_table(
        'data_retention_logs',
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.Column('retention_rule_id', sa.Integer(), nullable=False),
        sa.Column('data_category', sa.String(length=100), nullable=False),
        sa.Column('action_taken', sa.String(length=50), nullable=False),
        sa.Column('records_affected', sa.Integer(), nullable=False),
        sa.Column('affected_ids', sa.JSON(), nullable=True),
        sa.Column('executed_by', sa.Integer(), nullable=True),
        sa.Column('executed_at', sa.DateTime(), nullable=False),
        sa.Column('success', sa.Boolean(), nullable=False),
        sa.Column('error_message', sa.Text(), nullable=True),
        sa.Column('extra_metadata', sa.JSON(), nullable=True),
        sa.ForeignKeyConstraint(['executed_by'], ['users.id'], ),
        sa.ForeignKeyConstraint(['retention_rule_id'], ['retention_rules.id'], ),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_data_retention_logs_id'), 'data_retention_logs', ['id'], unique=False)
    op.create_index(op.f('ix_data_retention_logs_retention_rule_id'), 'data_retention_logs', ['retention_rule_id'], unique=False)
    op.create_index(op.f('ix_data_retention_logs_data_category'), 'data_retention_logs', ['data_category'], unique=False)
    op.create_index(op.f('ix_data_retention_logs_executed_at'), 'data_retention_logs', ['executed_at'], unique=False)


def downgrade() -> None:
    # Drop foreign keys first, then indexes, then tables
    op.drop_table('data_retention_logs')
    
    op.drop_table('retention_rules')
    op.drop_table('data_breaches')
    op.drop_table('data_processing_records')
    op.drop_table('consents')
