"""
Initial schema for Distribution Service

Revision ID: 001
Revises:
Create Date: 2024-12-01 13:00:00.000000

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


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


def upgrade():
    # Create enum types
    op.execute("CREATE TYPE deliveryroutestatus AS ENUM ('planned', 'in_progress', 'completed', 'cancelled')")
    op.execute("CREATE TYPE shipmentstatus AS ENUM ('pending', 'packed', 'in_transit', 'delivered', 'failed')")
    op.execute("CREATE TYPE deliveryschedulefrequency AS ENUM ('daily', 'weekly', 'biweekly', 'monthly')")

    # Create delivery_routes table
    op.create_table('delivery_routes',
        sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('route_number', sa.String(length=50), nullable=False),
        sa.Column('route_date', sa.DateTime(timezone=True), nullable=False),
        sa.Column('vehicle_id', sa.String(length=100), nullable=True),
        sa.Column('driver_id', postgresql.UUID(as_uuid=True), nullable=True),
        sa.Column('total_distance_km', sa.Float(), nullable=True),
        sa.Column('estimated_duration_minutes', sa.Integer(), nullable=True),
        sa.Column('route_sequence', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
        sa.Column('notes', sa.Text(), nullable=True),
        sa.Column('status', postgresql.ENUM('planned', 'in_progress', 'completed', 'cancelled', name='deliveryroutestatus', create_type=False), nullable=False, server_default='planned'),
        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('created_by', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('updated_by', postgresql.UUID(as_uuid=True), nullable=False),
        # VRP Optimization Metrics
        sa.Column('vrp_optimization_savings', sa.JSON(), nullable=True),
        sa.Column('vrp_algorithm_version', sa.String(length=50), nullable=True),
        sa.Column('vrp_optimization_timestamp', sa.DateTime(timezone=True), nullable=True),
        sa.Column('vrp_constraints_satisfied', sa.Boolean(), nullable=True),
        sa.Column('vrp_objective_value', sa.Float(), nullable=True),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('route_number')
    )

    # Create indexes for delivery_routes
    op.create_index('ix_delivery_routes_tenant_id', 'delivery_routes', ['tenant_id'])
    op.create_index('ix_delivery_routes_route_date', 'delivery_routes', ['route_date'])
    op.create_index('ix_delivery_routes_route_number', 'delivery_routes', ['route_number'])
    op.create_index('ix_delivery_routes_status', 'delivery_routes', ['status'])
    op.create_index('ix_delivery_routes_driver_id', 'delivery_routes', ['driver_id'])
    op.create_index('ix_delivery_routes_tenant_date', 'delivery_routes', ['tenant_id', 'route_date'])
    op.create_index('ix_delivery_routes_date_tenant_status', 'delivery_routes', ['route_date', 'tenant_id', 'status'])
    # VRP Optimization Index
    op.create_index('ix_delivery_routes_vrp_optimization', 'delivery_routes', ['vrp_optimization_timestamp'], unique=False)


    # Create shipments table
    op.create_table('shipments',
        sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('parent_tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('child_tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('purchase_order_id', postgresql.UUID(as_uuid=True), nullable=True),
        sa.Column('delivery_route_id', postgresql.UUID(as_uuid=True), nullable=True),
        sa.Column('shipment_number', sa.String(length=50), nullable=False),
        sa.Column('shipment_date', sa.DateTime(timezone=True), nullable=False),
        sa.Column('current_location_lat', sa.Float(), nullable=True),
        sa.Column('current_location_lng', sa.Float(), nullable=True),
        sa.Column('last_tracked_at', sa.DateTime(timezone=True), nullable=True),
        sa.Column('status', postgresql.ENUM('pending', 'packed', 'in_transit', 'delivered', 'failed', name='shipmentstatus', create_type=False), nullable=False, server_default='pending'),
        sa.Column('actual_delivery_time', sa.DateTime(timezone=True), nullable=True),
        sa.Column('signature', sa.Text(), nullable=True),
        sa.Column('photo_url', sa.String(length=500), nullable=True),
        sa.Column('received_by_name', sa.String(length=200), nullable=True),
        sa.Column('delivery_notes', sa.Text(), nullable=True),
        sa.Column('total_weight_kg', sa.Float(), nullable=True),
        sa.Column('total_volume_m3', sa.Float(), nullable=True),
        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('created_by', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('updated_by', postgresql.UUID(as_uuid=True), nullable=False),
        sa.ForeignKeyConstraint(['delivery_route_id'], ['delivery_routes.id'], ondelete='SET NULL'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('shipment_number')
    )

    # Create indexes for shipments
    op.create_index('ix_shipments_tenant_id', 'shipments', ['tenant_id'])
    op.create_index('ix_shipments_parent_tenant_id', 'shipments', ['parent_tenant_id'])
    op.create_index('ix_shipments_child_tenant_id', 'shipments', ['child_tenant_id'])
    op.create_index('ix_shipments_purchase_order_id', 'shipments', ['purchase_order_id'])
    op.create_index('ix_shipments_delivery_route_id', 'shipments', ['delivery_route_id'])
    op.create_index('ix_shipments_shipment_number', 'shipments', ['shipment_number'])
    op.create_index('ix_shipments_shipment_date', 'shipments', ['shipment_date'])
    op.create_index('ix_shipments_status', 'shipments', ['status'])
    op.create_index('ix_shipments_tenant_status', 'shipments', ['tenant_id', 'status'])
    op.create_index('ix_shipments_parent_child', 'shipments', ['parent_tenant_id', 'child_tenant_id'])
    op.create_index('ix_shipments_date_tenant', 'shipments', ['shipment_date', 'tenant_id'])


    # Create delivery_schedules table
    op.create_table('delivery_schedules',
        sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('name', sa.String(length=200), nullable=False),
        sa.Column('delivery_days', sa.String(length=200), nullable=False),
        sa.Column('delivery_time', sa.String(length=20), nullable=False),
        sa.Column('frequency', postgresql.ENUM('daily', 'weekly', 'biweekly', 'monthly', name='deliveryschedulefrequency', create_type=False), nullable=False, server_default='weekly'),
        sa.Column('auto_generate_orders', sa.Boolean(), nullable=False, server_default='false'),
        sa.Column('lead_time_days', sa.Integer(), nullable=False, server_default='1'),
        sa.Column('target_parent_tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('target_child_tenant_ids', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
        sa.Column('is_active', sa.Boolean(), nullable=False, server_default='true'),
        sa.Column('notes', sa.Text(), nullable=True),
        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('created_by', postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column('updated_by', postgresql.UUID(as_uuid=True), nullable=False),
        sa.PrimaryKeyConstraint('id')
    )

    # Create indexes for delivery_schedules
    op.create_index('ix_delivery_schedules_tenant_id', 'delivery_schedules', ['tenant_id'])
    op.create_index('ix_delivery_schedules_target_parent_tenant_id', 'delivery_schedules', ['target_parent_tenant_id'])
    op.create_index('ix_delivery_schedules_is_active', 'delivery_schedules', ['is_active'])
    op.create_index('ix_delivery_schedules_tenant_active', 'delivery_schedules', ['tenant_id', 'is_active'])
    op.create_index('ix_delivery_schedules_parent_tenant', 'delivery_schedules', ['target_parent_tenant_id'])


def downgrade():
    # Drop indexes for delivery_schedules
    op.drop_index('ix_delivery_schedules_parent_tenant', table_name='delivery_schedules')
    op.drop_index('ix_delivery_schedules_tenant_active', table_name='delivery_schedules')
    op.drop_index('ix_delivery_schedules_is_active', table_name='delivery_schedules')
    op.drop_index('ix_delivery_schedules_target_parent_tenant_id', table_name='delivery_schedules')
    op.drop_index('ix_delivery_schedules_tenant_id', table_name='delivery_schedules')

    # Drop delivery_schedules table
    op.drop_table('delivery_schedules')

    # Drop indexes for shipments
    op.drop_index('ix_shipments_date_tenant', table_name='shipments')
    op.drop_index('ix_shipments_parent_child', table_name='shipments')
    op.drop_index('ix_shipments_tenant_status', table_name='shipments')
    op.drop_index('ix_shipments_status', table_name='shipments')
    op.drop_index('ix_shipments_shipment_date', table_name='shipments')
    op.drop_index('ix_shipments_shipment_number', table_name='shipments')
    op.drop_index('ix_shipments_delivery_route_id', table_name='shipments')
    op.drop_index('ix_shipments_purchase_order_id', table_name='shipments')
    op.drop_index('ix_shipments_child_tenant_id', table_name='shipments')
    op.drop_index('ix_shipments_parent_tenant_id', table_name='shipments')
    op.drop_index('ix_shipments_tenant_id', table_name='shipments')

    # Drop shipments table
    op.drop_table('shipments')

    # Drop indexes for delivery_routes
    op.drop_index('ix_delivery_routes_vrp_optimization', table_name='delivery_routes')
    op.drop_index('ix_delivery_routes_date_tenant_status', table_name='delivery_routes')
    op.drop_index('ix_delivery_routes_tenant_date', table_name='delivery_routes')
    op.drop_index('ix_delivery_routes_driver_id', table_name='delivery_routes')
    op.drop_index('ix_delivery_routes_status', table_name='delivery_routes')
    op.drop_index('ix_delivery_routes_route_number', table_name='delivery_routes')
    op.drop_index('ix_delivery_routes_route_date', table_name='delivery_routes')
    op.drop_index('ix_delivery_routes_tenant_id', table_name='delivery_routes')

    # Drop delivery_routes table
    op.drop_table('delivery_routes')

    # Drop enum types
    op.execute("DROP TYPE IF EXISTS deliveryschedulefrequency")
    op.execute("DROP TYPE IF EXISTS shipmentstatus")
    op.execute("DROP TYPE IF EXISTS deliveryroutestatus")
