"""initial schema

Revision ID: 4a560483c5e4
Revises: 
Create Date: 2026-09-10 22:10:45.371635
"""
from alembic import op
import sqlalchemy as sa


revision = '4a560483c5e4'
down_revision = None
branch_labels = None
depends_on = None


def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('application_settings',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('key', sa.String(length=150), nullable=False),
    sa.Column('value', sa.JSON(), nullable=False),
    sa.Column('description', sa.String(length=300), nullable=True),
    sa.Column('category', sa.String(length=60), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_application_settings_created_at'), 'application_settings', ['created_at'], unique=False)
    op.create_index(op.f('ix_application_settings_key'), 'application_settings', ['key'], unique=True)
    op.create_table('users',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('email', sa.String(length=320), nullable=False),
    sa.Column('password_hash', sa.String(length=255), nullable=False),
    sa.Column('full_name', sa.String(length=200), nullable=True),
    sa.Column('is_admin', sa.Boolean(), nullable=False),
    sa.Column('is_active', sa.Boolean(), nullable=False),
    sa.Column('last_login_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_users_created_at'), 'users', ['created_at'], unique=False)
    op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=True)
    op.create_table('audit_logs',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=True),
    sa.Column('action', sa.String(length=120), nullable=False),
    sa.Column('entity', sa.String(length=60), nullable=True),
    sa.Column('entity_id', sa.Integer(), nullable=True),
    sa.Column('detail', sa.JSON(), nullable=True),
    sa.Column('ip_address', sa.String(length=64), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='SET NULL'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_audit_logs_action'), 'audit_logs', ['action'], unique=False)
    op.create_index(op.f('ix_audit_logs_created_at'), 'audit_logs', ['created_at'], unique=False)
    op.create_index(op.f('ix_audit_logs_user_id'), 'audit_logs', ['user_id'], unique=False)
    op.create_table('company_phone_numbers',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('label', sa.String(length=150), nullable=True),
    sa.Column('phone', sa.String(length=60), nullable=False),
    sa.Column('is_active', sa.Boolean(), nullable=False),
    sa.Column('use_count', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_company_phone_numbers_created_at'), 'company_phone_numbers', ['created_at'], unique=False)
    op.create_index(op.f('ix_company_phone_numbers_user_id'), 'company_phone_numbers', ['user_id'], unique=False)
    op.create_table('html_templates',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=250), nullable=False),
    sa.Column('subject_hint', sa.String(length=500), nullable=True),
    sa.Column('body_html', sa.Text(), nullable=False),
    sa.Column('body_text', sa.Text(), nullable=True),
    sa.Column('source', sa.String(length=20), nullable=True),
    sa.Column('is_active', sa.Boolean(), nullable=False),
    sa.Column('sequence_order', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_html_templates_created_at'), 'html_templates', ['created_at'], unique=False)
    op.create_index(op.f('ix_html_templates_user_id'), 'html_templates', ['user_id'], unique=False)
    op.create_table('oauth_client_configs',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=200), nullable=False),
    sa.Column('client_id', sa.String(length=300), nullable=False),
    sa.Column('client_secret_enc', sa.String(length=600), nullable=False),
    sa.Column('redirect_uri', sa.String(length=500), nullable=True),
    sa.Column('project_id', sa.String(length=200), nullable=True),
    sa.Column('is_active', sa.Boolean(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_oauth_client_configs_created_at'), 'oauth_client_configs', ['created_at'], unique=False)
    op.create_table('recipient_lists',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=200), nullable=False),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('source', sa.String(length=30), nullable=True),
    sa.Column('row_count', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_recipient_lists_created_at'), 'recipient_lists', ['created_at'], unique=False)
    op.create_index(op.f('ix_recipient_lists_user_id'), 'recipient_lists', ['user_id'], unique=False)
    op.create_table('subject_lines',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('subject', sa.String(length=500), nullable=False),
    sa.Column('tags', sa.JSON(), nullable=True),
    sa.Column('use_count', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_subject_lines_created_at'), 'subject_lines', ['created_at'], unique=False)
    op.create_index(op.f('ix_subject_lines_user_id'), 'subject_lines', ['user_id'], unique=False)
    op.create_table('attachments',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=300), nullable=False),
    sa.Column('filename', sa.String(length=300), nullable=False),
    sa.Column('stored_path', sa.String(length=500), nullable=False),
    sa.Column('mime_type', sa.String(length=120), nullable=True),
    sa.Column('size_bytes', sa.Integer(), nullable=True),
    sa.Column('kind', sa.String(length=30), nullable=True),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('is_html_attachment', sa.Boolean(), nullable=True),
    sa.Column('html_attachment_body', sa.Text(), nullable=True),
    sa.Column('html_source_template_id', sa.Integer(), nullable=True),
    sa.Column('file_sha256', sa.String(length=64), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['html_source_template_id'], ['html_templates.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_attachments_created_at'), 'attachments', ['created_at'], unique=False)
    op.create_index(op.f('ix_attachments_user_id'), 'attachments', ['user_id'], unique=False)
    op.create_table('gmail_accounts',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('email', sa.String(length=320), nullable=False),
    sa.Column('display_name', sa.String(length=200), nullable=True),
    sa.Column('status', sa.String(length=30), nullable=True),
    sa.Column('sending_method', sa.String(length=20), nullable=True),
    sa.Column('auth_provider', sa.String(length=60), nullable=True),
    sa.Column('google_user_id', sa.String(length=120), nullable=True),
    sa.Column('daily_limit', sa.Integer(), nullable=True),
    sa.Column('campaign_limit', sa.Integer(), nullable=True),
    sa.Column('sends_today', sa.Integer(), nullable=True),
    sa.Column('last_send_date', sa.DateTime(timezone=True), nullable=True),
    sa.Column('cooldown_until', sa.DateTime(timezone=True), nullable=True),
    sa.Column('last_success_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('last_error', sa.Text(), nullable=True),
    sa.Column('error_count', sa.Integer(), nullable=True),
    sa.Column('token_expiry', sa.DateTime(timezone=True), nullable=True),
    sa.Column('oauth_config_id', sa.Integer(), nullable=True),
    sa.Column('is_active', sa.Boolean(), nullable=False),
    sa.Column('revoked_by_user', sa.Boolean(), nullable=True),
    sa.Column('revoked_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['oauth_config_id'], ['oauth_client_configs.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('user_id', 'email', name='uq_gmail_account_user_email')
    )
    op.create_index(op.f('ix_gmail_accounts_created_at'), 'gmail_accounts', ['created_at'], unique=False)
    op.create_index(op.f('ix_gmail_accounts_user_id'), 'gmail_accounts', ['user_id'], unique=False)
    op.create_index('ix_gmail_status', 'gmail_accounts', ['status'], unique=False)
    op.create_table('recipients',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('list_id', sa.Integer(), nullable=False),
    sa.Column('email', sa.String(length=320), nullable=False),
    sa.Column('first_name', sa.String(length=150), nullable=True),
    sa.Column('last_name', sa.String(length=150), nullable=True),
    sa.Column('company_name', sa.String(length=250), nullable=True),
    sa.Column('company_phone', sa.String(length=60), nullable=True),
    sa.Column('customer_email', sa.String(length=320), nullable=True),
    sa.Column('custom_fields', sa.JSON(), nullable=True),
    sa.Column('status', sa.String(length=30), nullable=True),
    sa.Column('validation_error', sa.Text(), nullable=True),
    sa.Column('is_valid', sa.Boolean(), nullable=False),
    sa.Column('unsub_token', sa.String(length=64), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['list_id'], ['recipient_lists.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('unsub_token')
    )
    op.create_index('ix_recipient_list_email', 'recipients', ['list_id', 'email'], unique=False)
    op.create_index(op.f('ix_recipients_created_at'), 'recipients', ['created_at'], unique=False)
    op.create_index(op.f('ix_recipients_email'), 'recipients', ['email'], unique=False)
    op.create_index(op.f('ix_recipients_list_id'), 'recipients', ['list_id'], unique=False)
    op.create_table('campaigns',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=250), nullable=False),
    sa.Column('status', sa.String(length=30), nullable=True),
    sa.Column('recipient_list_id', sa.Integer(), nullable=True),
    sa.Column('subject_set_ids', sa.JSON(), nullable=True),
    sa.Column('template_ids', sa.JSON(), nullable=True),
    sa.Column('message_type', sa.String(length=40), nullable=True),
    sa.Column('attach_pdf', sa.Boolean(), nullable=True),
    sa.Column('attach_pdf_template_id', sa.Integer(), nullable=True),
    sa.Column('attachment_id', sa.Integer(), nullable=True),
    sa.Column('attach_mode', sa.String(length=40), nullable=True),
    sa.Column('variable_config', sa.JSON(), nullable=True),
    sa.Column('account_ids', sa.JSON(), nullable=True),
    sa.Column('rotation_strategy', sa.String(length=30), nullable=True),
    sa.Column('rotation_weights', sa.JSON(), nullable=True),
    sa.Column('subject_rotation', sa.String(length=30), nullable=True),
    sa.Column('template_sequence_mode', sa.String(length=30), nullable=True),
    sa.Column('phone_selection', sa.String(length=30), nullable=True),
    sa.Column('max_per_account', sa.Integer(), nullable=True),
    sa.Column('send_interval_seconds', sa.Float(), nullable=True),
    sa.Column('rate_per_minute', sa.Integer(), nullable=True),
    sa.Column('max_retries', sa.Integer(), nullable=True),
    sa.Column('retry_delay_seconds', sa.Integer(), nullable=True),
    sa.Column('total_recipients', sa.Integer(), nullable=True),
    sa.Column('sent_count', sa.Integer(), nullable=True),
    sa.Column('failed_count', sa.Integer(), nullable=True),
    sa.Column('skipped_count', sa.Integer(), nullable=True),
    sa.Column('suppressed_count', sa.Integer(), nullable=True),
    sa.Column('bounced_count', sa.Integer(), nullable=True),
    sa.Column('queued_count', sa.Integer(), nullable=True),
    sa.Column('started_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('finished_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('preview_sample_size', sa.Integer(), nullable=True),
    sa.Column('unsubscribe_enabled', sa.Boolean(), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['attach_pdf_template_id'], ['html_templates.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['attachment_id'], ['attachments.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['recipient_list_id'], ['recipient_lists.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_campaigns_created_at'), 'campaigns', ['created_at'], unique=False)
    op.create_index(op.f('ix_campaigns_user_id'), 'campaigns', ['user_id'], unique=False)
    op.create_table('oauth_tokens',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('account_id', sa.Integer(), nullable=False),
    sa.Column('access_token_enc', sa.String(length=1200), nullable=False),
    sa.Column('refresh_token_enc', sa.String(length=1200), nullable=True),
    sa.Column('token_type', sa.String(length=50), nullable=True),
    sa.Column('scope', sa.Text(), nullable=True),
    sa.Column('expires_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('granted_scopes', sa.Text(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['account_id'], ['gmail_accounts.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_oauth_tokens_account_id'), 'oauth_tokens', ['account_id'], unique=False)
    op.create_index(op.f('ix_oauth_tokens_created_at'), 'oauth_tokens', ['created_at'], unique=False)
    op.create_table('campaign_recipients',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('campaign_id', sa.Integer(), nullable=False),
    sa.Column('recipient_id', sa.Integer(), nullable=False),
    sa.Column('email', sa.String(length=320), nullable=False),
    sa.Column('status', sa.String(length=30), nullable=True),
    sa.Column('generated_invoice_number', sa.String(length=100), nullable=True),
    sa.Column('generated_amount', sa.Float(), nullable=True),
    sa.Column('generated_shipping', sa.Float(), nullable=True),
    sa.Column('generated_subject_id', sa.Integer(), nullable=True),
    sa.Column('generated_template_id', sa.Integer(), nullable=True),
    sa.Column('generated_phone', sa.String(length=60), nullable=True),
    sa.Column('assigned_account_id', sa.Integer(), nullable=True),
    sa.Column('attempt_count', sa.Integer(), nullable=True),
    sa.Column('last_error', sa.Text(), nullable=True),
    sa.Column('msg_id', sa.String(length=200), nullable=True),
    sa.Column('thread_id', sa.String(length=200), nullable=True),
    sa.Column('sent_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('seq', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['assigned_account_id'], ['gmail_accounts.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['campaign_id'], ['campaigns.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['generated_subject_id'], ['subject_lines.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['generated_template_id'], ['html_templates.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['recipient_id'], ['recipients.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('campaign_id', 'recipient_id', name='uq_campaign_recipient')
    )
    op.create_index('ix_campaign_recipient_status', 'campaign_recipients', ['campaign_id', 'status'], unique=False)
    op.create_index(op.f('ix_campaign_recipients_campaign_id'), 'campaign_recipients', ['campaign_id'], unique=False)
    op.create_index(op.f('ix_campaign_recipients_created_at'), 'campaign_recipients', ['created_at'], unique=False)
    op.create_index(op.f('ix_campaign_recipients_email'), 'campaign_recipients', ['email'], unique=False)
    op.create_table('suppression_list',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('email', sa.String(length=320), nullable=False),
    sa.Column('reason', sa.String(length=50), nullable=True),
    sa.Column('source', sa.String(length=200), nullable=True),
    sa.Column('campaign_id', sa.Integer(), nullable=True),
    sa.Column('user_id', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['campaign_id'], ['campaigns.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_suppression_list_created_at'), 'suppression_list', ['created_at'], unique=False)
    op.create_index(op.f('ix_suppression_list_email'), 'suppression_list', ['email'], unique=True)
    op.create_table('email_events',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('campaign_id', sa.Integer(), nullable=True),
    sa.Column('campaign_recipient_id', sa.Integer(), nullable=True),
    sa.Column('gmail_account_id', sa.Integer(), nullable=True),
    sa.Column('event_type', sa.String(length=40), nullable=False),
    sa.Column('detail', sa.Text(), nullable=True),
    sa.Column('message_id', sa.String(length=200), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['campaign_id'], ['campaigns.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['campaign_recipient_id'], ['campaign_recipients.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['gmail_account_id'], ['gmail_accounts.id'], ondelete='SET NULL'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index('ix_email_events_campaign', 'email_events', ['campaign_id', 'event_type'], unique=False)
    op.create_index(op.f('ix_email_events_campaign_id'), 'email_events', ['campaign_id'], unique=False)
    op.create_index(op.f('ix_email_events_campaign_recipient_id'), 'email_events', ['campaign_recipient_id'], unique=False)
    op.create_index(op.f('ix_email_events_created_at'), 'email_events', ['created_at'], unique=False)
    op.create_table('send_jobs',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('campaign_id', sa.Integer(), nullable=False),
    sa.Column('campaign_recipient_id', sa.Integer(), nullable=False),
    sa.Column('status', sa.String(length=30), nullable=True),
    sa.Column('attempts', sa.Integer(), nullable=True),
    sa.Column('max_attempts', sa.Integer(), nullable=True),
    sa.Column('retry_after', sa.DateTime(timezone=True), nullable=True),
    sa.Column('last_error', sa.Text(), nullable=True),
    sa.Column('locked_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('priority', sa.Integer(), nullable=True),
    sa.Column('scheduled_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['campaign_id'], ['campaigns.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['campaign_recipient_id'], ['campaign_recipients.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_send_jobs_campaign_id'), 'send_jobs', ['campaign_id'], unique=False)
    op.create_index(op.f('ix_send_jobs_campaign_recipient_id'), 'send_jobs', ['campaign_recipient_id'], unique=False)
    op.create_index(op.f('ix_send_jobs_created_at'), 'send_jobs', ['created_at'], unique=False)
    op.create_index(op.f('ix_send_jobs_scheduled_at'), 'send_jobs', ['scheduled_at'], unique=False)
    op.create_table('send_attempts',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('send_job_id', sa.Integer(), nullable=False),
    sa.Column('campaign_id', sa.Integer(), nullable=False),
    sa.Column('gmail_account_id', sa.Integer(), nullable=True),
    sa.Column('recipient_email', sa.String(length=320), nullable=False),
    sa.Column('subject', sa.String(length=500), nullable=True),
    sa.Column('template_name', sa.String(length=250), nullable=True),
    sa.Column('attachment_names', sa.JSON(), nullable=True),
    sa.Column('method', sa.String(length=20), nullable=True),
    sa.Column('outcome', sa.String(length=30), nullable=False),
    sa.Column('provider_response', sa.Text(), nullable=True),
    sa.Column('message_id', sa.String(length=200), nullable=True),
    sa.Column('thread_id', sa.String(length=200), nullable=True),
    sa.Column('retry_no', sa.Integer(), nullable=True),
    sa.Column('failure_reason', sa.Text(), nullable=True),
    sa.Column('error_class', sa.String(length=60), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
    sa.ForeignKeyConstraint(['campaign_id'], ['campaigns.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['gmail_account_id'], ['gmail_accounts.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['send_job_id'], ['send_jobs.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_send_attempts_campaign_id'), 'send_attempts', ['campaign_id'], unique=False)
    op.create_index(op.f('ix_send_attempts_created_at'), 'send_attempts', ['created_at'], unique=False)
    op.create_index(op.f('ix_send_attempts_send_job_id'), 'send_attempts', ['send_job_id'], unique=False)
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_send_attempts_send_job_id'), table_name='send_attempts')
    op.drop_index(op.f('ix_send_attempts_created_at'), table_name='send_attempts')
    op.drop_index(op.f('ix_send_attempts_campaign_id'), table_name='send_attempts')
    op.drop_table('send_attempts')
    op.drop_index(op.f('ix_send_jobs_scheduled_at'), table_name='send_jobs')
    op.drop_index(op.f('ix_send_jobs_created_at'), table_name='send_jobs')
    op.drop_index(op.f('ix_send_jobs_campaign_recipient_id'), table_name='send_jobs')
    op.drop_index(op.f('ix_send_jobs_campaign_id'), table_name='send_jobs')
    op.drop_table('send_jobs')
    op.drop_index(op.f('ix_email_events_created_at'), table_name='email_events')
    op.drop_index(op.f('ix_email_events_campaign_recipient_id'), table_name='email_events')
    op.drop_index(op.f('ix_email_events_campaign_id'), table_name='email_events')
    op.drop_index('ix_email_events_campaign', table_name='email_events')
    op.drop_table('email_events')
    op.drop_index(op.f('ix_suppression_list_email'), table_name='suppression_list')
    op.drop_index(op.f('ix_suppression_list_created_at'), table_name='suppression_list')
    op.drop_table('suppression_list')
    op.drop_index(op.f('ix_campaign_recipients_email'), table_name='campaign_recipients')
    op.drop_index(op.f('ix_campaign_recipients_created_at'), table_name='campaign_recipients')
    op.drop_index(op.f('ix_campaign_recipients_campaign_id'), table_name='campaign_recipients')
    op.drop_index('ix_campaign_recipient_status', table_name='campaign_recipients')
    op.drop_table('campaign_recipients')
    op.drop_index(op.f('ix_oauth_tokens_created_at'), table_name='oauth_tokens')
    op.drop_index(op.f('ix_oauth_tokens_account_id'), table_name='oauth_tokens')
    op.drop_table('oauth_tokens')
    op.drop_index(op.f('ix_campaigns_user_id'), table_name='campaigns')
    op.drop_index(op.f('ix_campaigns_created_at'), table_name='campaigns')
    op.drop_table('campaigns')
    op.drop_index(op.f('ix_recipients_list_id'), table_name='recipients')
    op.drop_index(op.f('ix_recipients_email'), table_name='recipients')
    op.drop_index(op.f('ix_recipients_created_at'), table_name='recipients')
    op.drop_index('ix_recipient_list_email', table_name='recipients')
    op.drop_table('recipients')
    op.drop_index('ix_gmail_status', table_name='gmail_accounts')
    op.drop_index(op.f('ix_gmail_accounts_user_id'), table_name='gmail_accounts')
    op.drop_index(op.f('ix_gmail_accounts_created_at'), table_name='gmail_accounts')
    op.drop_table('gmail_accounts')
    op.drop_index(op.f('ix_attachments_user_id'), table_name='attachments')
    op.drop_index(op.f('ix_attachments_created_at'), table_name='attachments')
    op.drop_table('attachments')
    op.drop_index(op.f('ix_subject_lines_user_id'), table_name='subject_lines')
    op.drop_index(op.f('ix_subject_lines_created_at'), table_name='subject_lines')
    op.drop_table('subject_lines')
    op.drop_index(op.f('ix_recipient_lists_user_id'), table_name='recipient_lists')
    op.drop_index(op.f('ix_recipient_lists_created_at'), table_name='recipient_lists')
    op.drop_table('recipient_lists')
    op.drop_index(op.f('ix_oauth_client_configs_created_at'), table_name='oauth_client_configs')
    op.drop_table('oauth_client_configs')
    op.drop_index(op.f('ix_html_templates_user_id'), table_name='html_templates')
    op.drop_index(op.f('ix_html_templates_created_at'), table_name='html_templates')
    op.drop_table('html_templates')
    op.drop_index(op.f('ix_company_phone_numbers_user_id'), table_name='company_phone_numbers')
    op.drop_index(op.f('ix_company_phone_numbers_created_at'), table_name='company_phone_numbers')
    op.drop_table('company_phone_numbers')
    op.drop_index(op.f('ix_audit_logs_user_id'), table_name='audit_logs')
    op.drop_index(op.f('ix_audit_logs_created_at'), table_name='audit_logs')
    op.drop_index(op.f('ix_audit_logs_action'), table_name='audit_logs')
    op.drop_table('audit_logs')
    op.drop_index(op.f('ix_users_email'), table_name='users')
    op.drop_index(op.f('ix_users_created_at'), table_name='users')
    op.drop_table('users')
    op.drop_index(op.f('ix_application_settings_key'), table_name='application_settings')
    op.drop_index(op.f('ix_application_settings_created_at'), table_name='application_settings')
    op.drop_table('application_settings')
    # ### end Alembic commands ###
