"""add group booking tables

Revision ID: add_group_booking_001
Revises: add_guest_profile_crm
Create Date: 2024-01-15 00:00:00.000000

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

# revision identifiers, used by Alembic.
revision = 'add_group_booking_001'
down_revision = 'add_guest_profile_crm'
branch_labels = None
depends_on = None


def upgrade() -> None:
    # Create group_bookings table
    op.create_table(
        'group_bookings',
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.Column('group_booking_number', sa.String(length=50), nullable=False),
        sa.Column('coordinator_id', sa.Integer(), nullable=False),
        sa.Column('coordinator_name', sa.String(length=100), nullable=False),
        sa.Column('coordinator_email', sa.String(length=100), nullable=False),
        sa.Column('coordinator_phone', sa.String(length=20), nullable=True),
        sa.Column('group_name', sa.String(length=200), nullable=True),
        sa.Column('group_type', sa.String(length=50), nullable=True),
        sa.Column('total_rooms', sa.Integer(), nullable=False, server_default='0'),
        sa.Column('total_guests', sa.Integer(), nullable=False, server_default='0'),
        sa.Column('check_in_date', sa.DateTime(), nullable=False),
        sa.Column('check_out_date', sa.DateTime(), nullable=False),
        sa.Column('base_rate_per_room', sa.Numeric(precision=10, scale=2), nullable=False),
        sa.Column('group_discount_percentage', sa.Numeric(precision=5, scale=2), nullable=True, server_default='0'),
        sa.Column('group_discount_amount', sa.Numeric(precision=10, scale=2), nullable=True, server_default='0'),
        sa.Column('original_total_price', sa.Numeric(precision=10, scale=2), nullable=False),
        sa.Column('discount_amount', sa.Numeric(precision=10, scale=2), nullable=True, server_default='0'),
        sa.Column('total_price', sa.Numeric(precision=10, scale=2), nullable=False),
        sa.Column('payment_option', sa.Enum('coordinator_pays_all', 'individual_payments', 'split_payment', name='paymentoption'), nullable=False, server_default='coordinator_pays_all'),
        sa.Column('deposit_required', sa.Boolean(), nullable=False, server_default='0'),
        sa.Column('deposit_percentage', sa.Integer(), nullable=True),
        sa.Column('deposit_amount', sa.Numeric(precision=10, scale=2), nullable=True),
        sa.Column('amount_paid', sa.Numeric(precision=10, scale=2), nullable=False, server_default='0'),
        sa.Column('balance_due', sa.Numeric(precision=10, scale=2), nullable=False),
        sa.Column('status', sa.Enum('draft', 'pending', 'confirmed', 'partially_confirmed', 'checked_in', 'checked_out', 'cancelled', name='groupbookingstatus'), nullable=False, server_default='draft'),
        sa.Column('cancellation_policy', sa.Text(), nullable=True),
        sa.Column('cancellation_deadline', sa.DateTime(), nullable=True),
        sa.Column('cancellation_penalty_percentage', sa.Numeric(precision=5, scale=2), nullable=True, server_default='0'),
        sa.Column('special_requests', sa.Text(), nullable=True),
        sa.Column('notes', sa.Text(), nullable=True),
        sa.Column('contract_terms', sa.Text(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=False),
        sa.Column('updated_at', sa.DateTime(), nullable=False),
        sa.Column('confirmed_at', sa.DateTime(), nullable=True),
        sa.Column('cancelled_at', sa.DateTime(), nullable=True),
        sa.ForeignKeyConstraint(['coordinator_id'], ['users.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('group_booking_number')
    )
    op.create_index(op.f('ix_group_bookings_id'), 'group_bookings', ['id'], unique=False)
    op.create_index(op.f('ix_group_bookings_group_booking_number'), 'group_bookings', ['group_booking_number'], unique=True)
    op.create_index(op.f('ix_group_bookings_coordinator_id'), 'group_bookings', ['coordinator_id'], unique=False)
    op.create_index(op.f('ix_group_bookings_status'), 'group_bookings', ['status'], unique=False)
    op.create_index(op.f('ix_group_bookings_check_in_date'), 'group_bookings', ['check_in_date'], unique=False)
    op.create_index(op.f('ix_group_bookings_check_out_date'), 'group_bookings', ['check_out_date'], unique=False)

    # Create group_room_blocks table
    op.create_table(
        'group_room_blocks',
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.Column('group_booking_id', sa.Integer(), nullable=False),
        sa.Column('room_type_id', sa.Integer(), nullable=False),
        sa.Column('rooms_blocked', sa.Integer(), nullable=False, server_default='0'),
        sa.Column('rooms_confirmed', sa.Integer(), nullable=False, server_default='0'),
        sa.Column('rooms_available', sa.Integer(), nullable=False, server_default='0'),
        sa.Column('rate_per_room', sa.Numeric(precision=10, scale=2), nullable=False),
        sa.Column('total_block_price', sa.Numeric(precision=10, scale=2), nullable=False),
        sa.Column('is_active', sa.Boolean(), nullable=False, server_default='1'),
        sa.Column('block_released_at', sa.DateTime(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=False),
        sa.Column('updated_at', sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(['group_booking_id'], ['group_bookings.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['room_type_id'], ['room_types.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_group_room_blocks_id'), 'group_room_blocks', ['id'], unique=False)
    op.create_index(op.f('ix_group_room_blocks_group_booking_id'), 'group_room_blocks', ['group_booking_id'], unique=False)
    op.create_index(op.f('ix_group_room_blocks_room_type_id'), 'group_room_blocks', ['room_type_id'], unique=False)

    # Create group_booking_members table
    op.create_table(
        'group_booking_members',
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.Column('group_booking_id', sa.Integer(), nullable=False),
        sa.Column('full_name', sa.String(length=100), nullable=False),
        sa.Column('email', sa.String(length=100), nullable=True),
        sa.Column('phone', sa.String(length=20), nullable=True),
        sa.Column('user_id', sa.Integer(), nullable=True),
        sa.Column('room_block_id', sa.Integer(), nullable=True),
        sa.Column('assigned_room_id', sa.Integer(), nullable=True),
        sa.Column('individual_booking_id', sa.Integer(), nullable=True),
        sa.Column('special_requests', sa.Text(), nullable=True),
        sa.Column('preferences', sa.JSON(), nullable=True),
        sa.Column('individual_amount', sa.Numeric(precision=10, scale=2), nullable=True),
        sa.Column('individual_paid', sa.Numeric(precision=10, scale=2), nullable=True, server_default='0'),
        sa.Column('individual_balance', sa.Numeric(precision=10, scale=2), nullable=True, server_default='0'),
        sa.Column('is_checked_in', sa.Boolean(), nullable=False, server_default='0'),
        sa.Column('checked_in_at', sa.DateTime(), nullable=True),
        sa.Column('is_checked_out', sa.Boolean(), nullable=False, server_default='0'),
        sa.Column('checked_out_at', sa.DateTime(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=False),
        sa.Column('updated_at', sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(['group_booking_id'], ['group_bookings.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['room_block_id'], ['group_room_blocks.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['assigned_room_id'], ['rooms.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['individual_booking_id'], ['bookings.id'], ondelete='SET NULL'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_group_booking_members_id'), 'group_booking_members', ['id'], unique=False)
    op.create_index(op.f('ix_group_booking_members_group_booking_id'), 'group_booking_members', ['group_booking_id'], unique=False)
    op.create_index(op.f('ix_group_booking_members_user_id'), 'group_booking_members', ['user_id'], unique=False)

    # Create group_payments table
    op.create_table(
        'group_payments',
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.Column('group_booking_id', sa.Integer(), nullable=False),
        sa.Column('amount', sa.Numeric(precision=10, scale=2), nullable=False),
        sa.Column('payment_method', sa.String(length=50), nullable=False),
        sa.Column('payment_type', sa.String(length=50), nullable=False, server_default='deposit'),
        sa.Column('payment_status', sa.String(length=50), nullable=False, server_default='pending'),
        sa.Column('transaction_id', sa.String(length=100), nullable=True),
        sa.Column('payment_date', sa.DateTime(), nullable=True),
        sa.Column('notes', sa.Text(), nullable=True),
        sa.Column('paid_by_member_id', sa.Integer(), nullable=True),
        sa.Column('paid_by_user_id', sa.Integer(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=False),
        sa.Column('updated_at', sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(['group_booking_id'], ['group_bookings.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['paid_by_member_id'], ['group_booking_members.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['paid_by_user_id'], ['users.id'], ondelete='SET NULL'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_group_payments_id'), 'group_payments', ['id'], unique=False)
    op.create_index(op.f('ix_group_payments_group_booking_id'), 'group_payments', ['group_booking_id'], unique=False)
    op.create_index(op.f('ix_group_payments_payment_status'), 'group_payments', ['payment_status'], unique=False)

    # Add group_booking_id to bookings table
    op.add_column('bookings', sa.Column('group_booking_id', sa.Integer(), nullable=True))
    op.create_foreign_key('fk_bookings_group_booking', 'bookings', 'group_bookings', ['group_booking_id'], ['id'], ondelete='SET NULL')
    op.create_index(op.f('ix_bookings_group_booking_id'), 'bookings', ['group_booking_id'], unique=False)


def downgrade() -> None:
    # Drop foreign key and column from bookings table
    op.drop_index(op.f('ix_bookings_group_booking_id'), table_name='bookings')
    op.drop_constraint('fk_bookings_group_booking', 'bookings', type_='foreignkey')
    op.drop_column('bookings', 'group_booking_id')
    
    # Drop group_payments table
    op.drop_index(op.f('ix_group_payments_payment_status'), table_name='group_payments')
    op.drop_index(op.f('ix_group_payments_group_booking_id'), table_name='group_payments')
    op.drop_index(op.f('ix_group_payments_id'), table_name='group_payments')
    op.drop_table('group_payments')
    
    # Drop group_booking_members table
    op.drop_index(op.f('ix_group_booking_members_user_id'), table_name='group_booking_members')
    op.drop_index(op.f('ix_group_booking_members_group_booking_id'), table_name='group_booking_members')
    op.drop_index(op.f('ix_group_booking_members_id'), table_name='group_booking_members')
    op.drop_table('group_booking_members')
    
    # Drop group_room_blocks table
    op.drop_index(op.f('ix_group_room_blocks_room_type_id'), table_name='group_room_blocks')
    op.drop_index(op.f('ix_group_room_blocks_group_booking_id'), table_name='group_room_blocks')
    op.drop_index(op.f('ix_group_room_blocks_id'), table_name='group_room_blocks')
    op.drop_table('group_room_blocks')
    
    # Drop group_bookings table
    op.drop_index(op.f('ix_group_bookings_check_out_date'), table_name='group_bookings')
    op.drop_index(op.f('ix_group_bookings_check_in_date'), table_name='group_bookings')
    op.drop_index(op.f('ix_group_bookings_status'), table_name='group_bookings')
    op.drop_index(op.f('ix_group_bookings_coordinator_id'), table_name='group_bookings')
    op.drop_index(op.f('ix_group_bookings_group_booking_number'), table_name='group_bookings')
    op.drop_index(op.f('ix_group_bookings_id'), table_name='group_bookings')
    op.drop_table('group_bookings')
    
    # Drop enums
    op.execute("DROP TYPE IF EXISTS paymentoption")
    op.execute("DROP TYPE IF EXISTS groupbookingstatus")

