"""Initial schema

Revision ID: 001_initial
Revises:
Create Date: 2024-12-16

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = '001_initial'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    # Create agencies table
    op.create_table(
        'agencies',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
        sa.Column('name', sa.String(255), nullable=False, unique=True),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
    )

    # Create users table
    op.create_table(
        'users',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
        sa.Column('azure_ad_oid', sa.String(255), nullable=False, unique=True),
        sa.Column('email', sa.String(255), nullable=False),
        sa.Column('name', sa.String(255), nullable=False),
        sa.Column('role', sa.String(50), nullable=False, server_default='basic_user'),
        sa.Column('agency_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('agencies.id'), nullable=True),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
    )

    # Create campaigns table
    op.create_table(
        'campaigns',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
        sa.Column('name', sa.String(255), nullable=False),
        sa.Column('workfront_id', sa.String(100), nullable=True),
        sa.Column('client_lead', sa.String(255), nullable=True),
        sa.Column('agency_lead', sa.String(255), nullable=True),
        sa.Column('brand_guidelines', sa.String(50), nullable=True),
        sa.Column('status', sa.String(50), server_default='In Progress'),
        sa.Column('agency_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('agencies.id'), nullable=True),
        sa.Column('created_by', postgresql.UUID(as_uuid=True), sa.ForeignKey('users.id'), nullable=True),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
    )

    # Create proofs table
    op.create_table(
        'proofs',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
        sa.Column('campaign_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('campaigns.id', ondelete='CASCADE'), nullable=False),
        sa.Column('proof_name', sa.String(255), nullable=False),
        sa.Column('channel', sa.String(100), nullable=True),
        sa.Column('sub_channel', sa.String(100), nullable=True),
        sa.Column('proof_type', sa.String(100), nullable=True),
        sa.Column('workfront_id', sa.String(100), nullable=True),
        sa.Column('created_by', postgresql.UUID(as_uuid=True), sa.ForeignKey('users.id'), nullable=True),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
        sa.UniqueConstraint('campaign_id', 'proof_name', name='uq_campaign_proof_name'),
    )

    # Create proof_versions table
    op.create_table(
        'proof_versions',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
        sa.Column('proof_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('proofs.id', ondelete='CASCADE'), nullable=False),
        sa.Column('version', sa.Integer, nullable=False),
        sa.Column('file_storage_key', sa.String(500), nullable=True),
        sa.Column('thumbnail_url', sa.Text, nullable=True),
        sa.Column('agent_review', postgresql.JSONB, nullable=True),
        sa.Column('overall_status', sa.String(50), nullable=True),
        sa.Column('workfront_id', sa.String(100), nullable=True),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
        sa.UniqueConstraint('proof_id', 'version', name='uq_proof_version'),
    )

    # Create flagged_items table
    op.create_table(
        'flagged_items',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
        sa.Column('proof_version_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('proof_versions.id'), nullable=False),
        sa.Column('agent_flagged', sa.String(100), nullable=False),
        sa.Column('comments', sa.Text, nullable=True),
        sa.Column('submitter_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('users.id'), nullable=True),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
    )

    # Create resolved_items table
    op.create_table(
        'resolved_items',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
        sa.Column('proof_version_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('proof_versions.id'), nullable=False),
        sa.Column('agent', sa.String(100), nullable=False),
        sa.Column('issue', sa.Text, nullable=True),
        sa.Column('resolution', sa.Text, nullable=True),
        sa.Column('submitter_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('users.id'), nullable=True),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
    )

    # Create error_items table
    op.create_table(
        'error_items',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
        sa.Column('proof_version_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('proof_versions.id'), nullable=False),
        sa.Column('error_summary', sa.Text, nullable=True),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
    )

    # Create dropdown_options table for configurable options
    op.create_table(
        'dropdown_options',
        sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
        sa.Column('option_type', sa.String(50), nullable=False),
        sa.Column('parent_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('dropdown_options.id'), nullable=True),
        sa.Column('value', sa.String(255), nullable=False),
        sa.Column('display_order', sa.Integer, server_default='0'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
    )

    # Create indexes for common queries
    op.create_index('idx_campaigns_agency', 'campaigns', ['agency_id'])
    op.create_index('idx_proofs_campaign', 'proofs', ['campaign_id'])
    op.create_index('idx_proof_versions_proof', 'proof_versions', ['proof_id'])
    op.create_index('idx_proof_versions_status', 'proof_versions', ['overall_status'])
    op.create_index('idx_users_agency', 'users', ['agency_id'])
    op.create_index('idx_flagged_items_version', 'flagged_items', ['proof_version_id'])
    op.create_index('idx_resolved_items_version', 'resolved_items', ['proof_version_id'])


def downgrade() -> None:
    # Drop indexes
    op.drop_index('idx_resolved_items_version')
    op.drop_index('idx_flagged_items_version')
    op.drop_index('idx_users_agency')
    op.drop_index('idx_proof_versions_status')
    op.drop_index('idx_proof_versions_proof')
    op.drop_index('idx_proofs_campaign')
    op.drop_index('idx_campaigns_agency')

    # Drop tables in reverse order
    op.drop_table('dropdown_options')
    op.drop_table('error_items')
    op.drop_table('resolved_items')
    op.drop_table('flagged_items')
    op.drop_table('proof_versions')
    op.drop_table('proofs')
    op.drop_table('campaigns')
    op.drop_table('users')
    op.drop_table('agencies')
