"""add poa models

Revision ID: 907a4961c5a5
Revises: a7c1e9b24d6f
Create Date: 2026-02-09 15:42:11.506780

"""
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 = '907a4961c5a5'
down_revision: Union[str, Sequence[str], None] = 'a7c1e9b24d6f'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('poa_plan',
    sa.Column('case_number', sa.String(length=64), nullable=False),
    sa.Column('member_name', sa.String(length=160), nullable=False),
    sa.Column('mission_title', sa.String(length=200), nullable=True),
    sa.Column('status', sa.Enum('DRAFT', 'ACTIVE', 'ARCHIVED', name='poaplanstatus', native_enum=False), nullable=False),
    sa.Column('starts_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('ends_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_by_contact_id', sa.Integer(), nullable=True),
    sa.Column('updated_by_contact_id', sa.Integer(), nullable=True),
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
    sa.CheckConstraint('char_length(trim(case_number)) > 0', name=op.f('poa_plan_poa_plan_case_number_not_blank_check')),
    sa.CheckConstraint('char_length(trim(member_name)) > 0', name=op.f('poa_plan_poa_plan_member_name_not_blank_check')),
    sa.CheckConstraint('ends_at IS NULL OR starts_at IS NULL OR ends_at > starts_at', name=op.f('poa_plan_poa_plan_time_window_valid_check')),
    sa.ForeignKeyConstraint(['created_by_contact_id'], ['contact.id'], name=op.f('poa_plan_created_by_contact_id_fkey'), ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['updated_by_contact_id'], ['contact.id'], name=op.f('poa_plan_updated_by_contact_id_fkey'), ondelete='SET NULL'),
    sa.PrimaryKeyConstraint('id', name=op.f('poa_plan_pkey'))
    )
    op.create_index('ix_poa_plan_status_updated', 'poa_plan', ['status', 'updated_at'], unique=False)
    op.create_index(op.f('poa_plan_case_number_idx'), 'poa_plan', ['case_number'], unique=False)
    op.create_index(op.f('poa_plan_created_by_contact_id_idx'), 'poa_plan', ['created_by_contact_id'], unique=False)
    op.create_index(op.f('poa_plan_id_idx'), 'poa_plan', ['id'], unique=False)
    op.create_index(op.f('poa_plan_member_name_idx'), 'poa_plan', ['member_name'], unique=False)
    op.create_index(op.f('poa_plan_status_idx'), 'poa_plan', ['status'], unique=False)
    op.create_index(op.f('poa_plan_updated_by_contact_id_idx'), 'poa_plan', ['updated_by_contact_id'], unique=False)
    op.create_table('poa_event',
    sa.Column('plan_id', sa.Integer(), nullable=False),
    sa.Column('event_type', sa.Enum('FLIGHT', 'LAYOVER', 'GROUND_TRANSPORT', 'HOTEL', 'BEDSIDE', 'MEDICATION', 'PRE_FLIGHT_CHECK', 'POST_FLIGHT_CHECK', 'OTHER', name='poaeventtype', native_enum=False), nullable=False),
    sa.Column('title', sa.String(length=200), nullable=False),
    sa.Column('start_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('start_tz', sa.String(length=80), nullable=False),
    sa.Column('end_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('end_tz', sa.String(length=80), nullable=False),
    sa.Column('is_completed', sa.Boolean(), nullable=False),
    sa.Column('notes', sa.Text(), nullable=True),
    sa.Column('location', sa.String(length=240), nullable=True),
    sa.Column('contact_id', sa.Integer(), nullable=True),
    sa.Column('details_json', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
    sa.Column('stack_row', sa.Integer(), nullable=False),
    sa.Column('sort_order', sa.Integer(), nullable=False),
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
    sa.CheckConstraint('char_length(trim(title)) > 0', name=op.f('poa_event_poa_event_title_not_blank_check')),
    sa.CheckConstraint('end_at > start_at', name=op.f('poa_event_poa_event_time_valid_check')),
    sa.CheckConstraint('stack_row >= 0', name=op.f('poa_event_poa_event_stack_row_non_negative_check')),
    sa.ForeignKeyConstraint(['contact_id'], ['contact.id'], name=op.f('poa_event_contact_id_fkey'), ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['plan_id'], ['poa_plan.id'], name=op.f('poa_event_plan_id_fkey'), ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id', name=op.f('poa_event_pkey'))
    )
    op.create_index('ix_poa_event_plan_sort', 'poa_event', ['plan_id', 'sort_order', 'start_at'], unique=False)
    op.create_index('ix_poa_event_plan_time', 'poa_event', ['plan_id', 'start_at', 'end_at'], unique=False)
    op.create_index(op.f('poa_event_contact_id_idx'), 'poa_event', ['contact_id'], unique=False)
    op.create_index(op.f('poa_event_event_type_idx'), 'poa_event', ['event_type'], unique=False)
    op.create_index(op.f('poa_event_id_idx'), 'poa_event', ['id'], unique=False)
    op.create_index(op.f('poa_event_plan_id_idx'), 'poa_event', ['plan_id'], unique=False)
    op.create_table('poa_plan_timezone',
    sa.Column('plan_id', sa.Integer(), nullable=False),
    sa.Column('iana_zone', sa.String(length=80), nullable=False),
    sa.Column('display_order', sa.Integer(), nullable=False),
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
    sa.CheckConstraint('display_order >= 0', name=op.f('poa_plan_timezone_poa_plan_timezone_order_non_negative_check')),
    sa.ForeignKeyConstraint(['plan_id'], ['poa_plan.id'], name=op.f('poa_plan_timezone_plan_id_fkey'), ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id', name=op.f('poa_plan_timezone_pkey')),
    sa.UniqueConstraint('plan_id', 'display_order', name='uq_poa_plan_timezone_order'),
    sa.UniqueConstraint('plan_id', 'iana_zone', name='uq_poa_plan_timezone_zone')
    )
    op.create_index('ix_poa_plan_timezone_plan_order', 'poa_plan_timezone', ['plan_id', 'display_order'], unique=False)
    op.create_index(op.f('poa_plan_timezone_id_idx'), 'poa_plan_timezone', ['id'], unique=False)
    op.create_index(op.f('poa_plan_timezone_plan_id_idx'), 'poa_plan_timezone', ['plan_id'], unique=False)
    op.create_table('poa_event_dependency',
    sa.Column('plan_id', sa.Integer(), nullable=False),
    sa.Column('from_event_id', sa.Integer(), nullable=False),
    sa.Column('to_event_id', sa.Integer(), nullable=False),
    sa.Column('dependency_type', sa.Enum('PRECEDES', 'REQUIRES_BUFFER', 'BLOCKS', name='poadependencytype', native_enum=False), nullable=False),
    sa.Column('min_buffer_minutes', sa.Integer(), nullable=True),
    sa.Column('created_by_contact_id', sa.Integer(), nullable=True),
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
    sa.CheckConstraint("dependency_type != 'requires_buffer' OR min_buffer_minutes IS NOT NULL", name=op.f('poa_event_dependency_poa_event_dependency_requires_buffer_value_check')),
    sa.CheckConstraint('from_event_id <> to_event_id', name=op.f('poa_event_dependency_poa_event_dependency_not_self_check')),
    sa.CheckConstraint('min_buffer_minutes IS NULL OR min_buffer_minutes >= 0', name=op.f('poa_event_dependency_poa_event_dependency_buffer_non_negative_check')),
    sa.ForeignKeyConstraint(['created_by_contact_id'], ['contact.id'], name=op.f('poa_event_dependency_created_by_contact_id_fkey'), ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['from_event_id'], ['poa_event.id'], name=op.f('poa_event_dependency_from_event_id_fkey'), ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['plan_id'], ['poa_plan.id'], name=op.f('poa_event_dependency_plan_id_fkey'), ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['to_event_id'], ['poa_event.id'], name=op.f('poa_event_dependency_to_event_id_fkey'), ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id', name=op.f('poa_event_dependency_pkey')),
    sa.UniqueConstraint('from_event_id', 'to_event_id', 'dependency_type', name='uq_poa_event_dependency')
    )
    op.create_index('ix_poa_event_dependency_plan', 'poa_event_dependency', ['plan_id'], unique=False)
    op.create_index('ix_poa_event_dependency_to_event', 'poa_event_dependency', ['to_event_id'], unique=False)
    op.create_index(op.f('poa_event_dependency_created_by_contact_id_idx'), 'poa_event_dependency', ['created_by_contact_id'], unique=False)
    op.create_index(op.f('poa_event_dependency_dependency_type_idx'), 'poa_event_dependency', ['dependency_type'], unique=False)
    op.create_index(op.f('poa_event_dependency_from_event_id_idx'), 'poa_event_dependency', ['from_event_id'], unique=False)
    op.create_index(op.f('poa_event_dependency_id_idx'), 'poa_event_dependency', ['id'], unique=False)
    op.create_index(op.f('poa_event_dependency_plan_id_idx'), 'poa_event_dependency', ['plan_id'], unique=False)
    op.create_index(op.f('poa_event_dependency_to_event_id_idx'), 'poa_event_dependency', ['to_event_id'], unique=False)
    # ### end Alembic commands ###


def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('poa_event_dependency_to_event_id_idx'), table_name='poa_event_dependency')
    op.drop_index(op.f('poa_event_dependency_plan_id_idx'), table_name='poa_event_dependency')
    op.drop_index(op.f('poa_event_dependency_id_idx'), table_name='poa_event_dependency')
    op.drop_index(op.f('poa_event_dependency_from_event_id_idx'), table_name='poa_event_dependency')
    op.drop_index(op.f('poa_event_dependency_dependency_type_idx'), table_name='poa_event_dependency')
    op.drop_index(op.f('poa_event_dependency_created_by_contact_id_idx'), table_name='poa_event_dependency')
    op.drop_index('ix_poa_event_dependency_to_event', table_name='poa_event_dependency')
    op.drop_index('ix_poa_event_dependency_plan', table_name='poa_event_dependency')
    op.drop_table('poa_event_dependency')
    op.drop_index(op.f('poa_plan_timezone_plan_id_idx'), table_name='poa_plan_timezone')
    op.drop_index(op.f('poa_plan_timezone_id_idx'), table_name='poa_plan_timezone')
    op.drop_index('ix_poa_plan_timezone_plan_order', table_name='poa_plan_timezone')
    op.drop_table('poa_plan_timezone')
    op.drop_index(op.f('poa_event_plan_id_idx'), table_name='poa_event')
    op.drop_index(op.f('poa_event_id_idx'), table_name='poa_event')
    op.drop_index(op.f('poa_event_event_type_idx'), table_name='poa_event')
    op.drop_index(op.f('poa_event_contact_id_idx'), table_name='poa_event')
    op.drop_index('ix_poa_event_plan_time', table_name='poa_event')
    op.drop_index('ix_poa_event_plan_sort', table_name='poa_event')
    op.drop_table('poa_event')
    op.drop_index(op.f('poa_plan_updated_by_contact_id_idx'), table_name='poa_plan')
    op.drop_index(op.f('poa_plan_status_idx'), table_name='poa_plan')
    op.drop_index(op.f('poa_plan_member_name_idx'), table_name='poa_plan')
    op.drop_index(op.f('poa_plan_id_idx'), table_name='poa_plan')
    op.drop_index(op.f('poa_plan_created_by_contact_id_idx'), table_name='poa_plan')
    op.drop_index(op.f('poa_plan_case_number_idx'), table_name='poa_plan')
    op.drop_index('ix_poa_plan_status_updated', table_name='poa_plan')
    op.drop_table('poa_plan')
    # ### end Alembic commands ###
