"""card_project_split

Revision: 0069
Revision ID: 423db8281cbe
Revises: 491bd448c7c8
Create Date: 2016-08-17 18:40:53.259336

"""

# revision identifiers, used by Alembic.
revision = '423db8281cbe'
down_revision = '491bd448c7c8'
branch_labels = None
depends_on = None

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


cards = sa.Table(
    'cards',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('parent_id', sa.Integer),
    sa.Column('members_cache_id', sa.String),
    sa.Column('created_at', sa.DateTime),
    sa.Column('updated_at', sa.DateTime),
    sa.Column('owner_id', sa.Integer),
    sa.Column('created_by_id', sa.Integer),
    sa.Column('public_permission', sa.Integer),
    sa.Column('is_template', sa.Boolean),
    sa.Column('is_archived', sa.Boolean),
    sa.Column('base_card_model_id', sa.Integer),
    sa.Column('ref_counter', sa.Integer),
    sa.Column('org_members_can_observe', sa.Boolean),
    sa.Column('org_members_can_autojoin', sa.Boolean),
    sa.Column('default_org_member_permission', sa.Integer),
    sa.Column('import_status', sa.String),
    sa.Column('push_id', sa.String),
    sa.Column('meta', postgresql.JSONB())
)


def upgrade():
    conn = op.get_bind()

    op.drop_constraint('card_models_card_template_id_fkey', 'card_models', type_='foreignkey')
    op.drop_constraint('cards_default_card_group_type_id_fkey', 'cards', type_='foreignkey')
    op.drop_constraint('cards_owner_id_fkey', 'cards', type_='foreignkey')
    op.drop_constraint('cards_base_card_model_id', 'cards', type_='foreignkey')

    op.drop_constraint('card_models_created_in_id_fkey', 'card_models', type_='foreignkey')
    op.drop_constraint('card_log_types_card_id_fkey', 'card_log_types', type_='foreignkey')
    op.drop_constraint('views_card_id_fkey', 'views', type_='foreignkey')
    op.drop_constraint('card_behaviors_card_id_fkey', 'card_behaviors', type_='foreignkey')

    op.add_column('card_models', sa.Column('created_in_card_id', sa.Integer(), nullable=True))
    op.execute("UPDATE card_models SET created_in_card_id = created_in_id")
    op.execute("UPDATE card_models SET created_in_id = NULL")

    projects = op.create_table('projects',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('members_cache_id', sa.String(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=True),
        sa.Column('updated_at', sa.DateTime(), nullable=True),
        sa.Column('owner_id', sa.Integer(), nullable=True),
        sa.Column('created_by_id', sa.Integer(), nullable=True),
        sa.Column('public_permission', sa.Integer(), nullable=True),
        sa.Column('is_template', sa.Boolean(), nullable=True),
        sa.Column('is_archived', sa.Boolean(), nullable=True),
        sa.Column('base_card_model_id', sa.Integer(), nullable=True),
        sa.Column('ref_counter', sa.Integer(), nullable=True),
        sa.Column('org_members_can_observe', sa.Boolean(), nullable=True),
        sa.Column('org_members_can_autojoin', sa.Boolean(), nullable=True),
        sa.Column('default_org_member_permission', sa.Integer(), nullable=True),
        sa.Column('import_status', sa.String(), nullable=True),
        sa.Column('push_id', sa.String(), nullable=True),
        sa.Column('top_level_card_id', sa.Integer(), nullable=True),
        sa.Column('meta', postgresql.JSONB(), nullable=True),
        sa.ForeignKeyConstraint(['base_card_model_id'], ['card_models.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['created_by_id'], ['users.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['owner_id'], ['organizations.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['top_level_card_id'], ['cards.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_projects_meta'), 'projects', ['meta'], unique=False)
    op.create_index(op.f('ix_projects_owner_id'), 'projects', ['owner_id'], unique=False)
    op.create_index(op.f('ix_projects_is_template'), 'projects', ['is_template'], unique=False)
    op.create_index(op.f('ix_projects_is_archived'), 'projects', ['is_archived'], unique=False)

    op.create_table('project_enabled_group_types',
        sa.Column('group_type_id', sa.Integer(), nullable=True),
        sa.Column('project_id', sa.Integer(), nullable=True),
        sa.ForeignKeyConstraint(['group_type_id'], ['card_group_types.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['project_id'], ['projects.id'], ondelete='CASCADE')
    )
    op.create_index(op.f('ix_project_enabled_group_types_group_type_id'), 'project_enabled_group_types', ['group_type_id'], unique=False)
    op.create_index(op.f('ix_project_enabled_group_types_project_id'), 'project_enabled_group_types', ['project_id'], unique=False)

    op.create_table('project_enabled_models',
        sa.Column('model_id', sa.Integer(), nullable=True),
        sa.Column('project_id', sa.Integer(), nullable=True),
        sa.ForeignKeyConstraint(['model_id'], ['card_models.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['project_id'], ['projects.id'], ondelete='CASCADE')
    )
    op.create_index(op.f('ix_project_enabled_models_model_id'), 'project_enabled_models', ['model_id'], unique=False)
    op.create_index(op.f('ix_project_enabled_models_project_id'), 'project_enabled_models', ['project_id'], unique=False)

    op.create_table('project_members',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('project_id', sa.Integer(), nullable=True),
        sa.Column('user_id', sa.Integer(), nullable=True),
        sa.Column('email', sa.String(), nullable=True),
        sa.Column('created_by_id', sa.Integer(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=True),
        sa.Column('updated_at', sa.DateTime(), nullable=True),
        sa.Column('permission', sa.Integer(), nullable=True),
        sa.ForeignKeyConstraint(['created_by_id'], ['users.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['project_id'], ['projects.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_project_members_email'), 'project_members', ['email'], unique=False)
    op.create_index(op.f('ix_project_members_project_id'), 'project_members', ['project_id'], unique=False)
    op.create_index(op.f('ix_project_members_user_id'), 'project_members', ['user_id'], unique=False)
    op.create_index(op.f('ix_project_members_permission'), 'project_members', ['permission'], unique=False)

    op.add_column('card_behaviors', sa.Column('project_id', sa.Integer(), nullable=True))
    op.create_index(op.f('ix_card_behaviors_project_id'), 'card_behaviors', ['project_id'], unique=False)
    op.create_foreign_key(None, 'card_behaviors', 'projects', ['project_id'], ['id'], ondelete='CASCADE')

    op.add_column('views', sa.Column('project_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'views', 'projects', ['project_id'], ['id'], ondelete='CASCADE')
    op.create_index(op.f('ix_views_project_id'), 'views', ['project_id'], unique=False)

    op.add_column('card_log_types', sa.Column('project_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'card_log_types', 'projects', ['project_id'], ['id'], ondelete='CASCADE')
    op.create_index(op.f('ix_card_log_types_project_id'), 'card_log_types', ['project_id'], unique=False)

    op.create_foreign_key(None, 'card_models', 'projects', ['created_in_id'], ['id'], ondelete='SET NULL')
    op.create_index(op.f('ix_card_models_created_in_id'), 'card_models', ['created_in_id'], unique=False)

    op.add_column('cards', sa.Column('project_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'cards', 'projects', ['project_id'], ['id'], ondelete='CASCADE')
    op.create_index(op.f('ix_cards_project_id'), 'cards', ['project_id'], unique=False)

    q = select([cards]).where(cards.c.parent_id==None)
    for card in conn.execute(q):
        r = conn.execute(projects.insert().values(
            members_cache_id=card.members_cache_id,
            created_at=card.created_at,
            updated_at=card.updated_at,
            owner_id=card.owner_id,
            created_by_id=card.created_by_id,
            public_permission=card.public_permission,
            is_template=card.is_template,
            is_archived=card.is_archived,
            base_card_model_id=card.base_card_model_id,
            ref_counter=card.ref_counter,
            org_members_can_observe=card.org_members_can_observe,
            org_members_can_autojoin=card.org_members_can_autojoin,
            default_org_member_permission=card.default_org_member_permission,
            import_status=card.import_status,
            push_id=card.push_id,
            top_level_card_id=card.id,
            meta=card.meta
        ))
        project_id = r.inserted_primary_key[0]
        op.execute("UPDATE cards SET project_id = %s WHERE id = %s OR %s = ANY(parents_ids)" % (project_id, card.id, card.id))

    op.execute("""INSERT INTO project_enabled_group_types (project_id, group_type_id)
        SELECT DISTINCT c.project_id, cegt.group_type_id FROM card_enabled_group_types cegt JOIN cards c ON c.id = cegt.card_id""")

    op.execute("""INSERT INTO project_enabled_models (project_id, model_id)
        SELECT DISTINCT c.project_id, cem.model_id FROM card_enabled_models cem JOIN cards c ON c.id = cem.card_id""")

    op.execute("""INSERT INTO project_members (project_id, user_id, email, created_by_id, created_at, updated_at, permission)
        SELECT c.project_id, cm.user_id, cm.email, cm.created_by_id, cm.created_at, cm.updated_at, cmp.permission
        FROM card_members cm JOIN card_member_permissions cmp ON (cmp.card_id = cm.card_id AND cmp.member_id = cm.id)
        JOIN cards c ON c.id = cm.card_id WHERE c.parent_id is null""")

    op.execute("""UPDATE card_behaviors SET project_id = cards.project_id FROM cards
        WHERE cards.id = card_behaviors.card_id AND cards.parent_id IS NULL""")

    op.add_column('views', sa.Column('card_ref', sa.Integer(), nullable=True))
    op.execute("""UPDATE views SET project_id = cards.project_id, card_ref = CASE cards.ref WHEN 0 THEN NULL ELSE cards.ref END FROM cards
        WHERE cards.id = views.card_id""")

    op.execute("""UPDATE card_log_types SET project_id = cards.project_id FROM cards
        WHERE cards.id = card_log_types.card_id""")

    op.execute("""UPDATE card_models SET created_in_id = cards.project_id FROM cards
        WHERE cards.id = card_models.created_in_card_id""")

    op.execute("DROP VIEW IF EXISTS metrics_projects_count_per_user")
    op.execute("DROP VIEW IF EXISTS projects_view")
    op.execute("DROP VIEW IF EXISTS metrics_members_count_per_org_projects")
    op.execute("DROP VIEW IF EXISTS soon_expiring_trials_view")
    op.execute("DROP VIEW IF EXISTS unpaid_view")
    op.execute("DROP VIEW IF EXISTS metrics_projects_count_per_org")

    op.drop_column('card_models', 'created_in_card_id')
    op.drop_index('ix_card_log_types_card_id', table_name='card_log_types')
    op.drop_column('card_log_types', 'card_id')
    op.drop_index('ix_views_card_id', table_name='views')
    op.drop_column('views', 'card_id')
    op.drop_index('ix_card_behaviors_card_id', table_name='card_behaviors')
    op.drop_column('card_behaviors', 'card_id')

    op.drop_column('cards', 'mongo_id')
    op.drop_column('cards', 'list_position')
    op.drop_column('cards', 'org_members_can_autojoin')
    op.drop_column('cards', 'org_members_can_observe')
    op.drop_column('cards', 'ref_counter')
    op.drop_column('cards', 'done_at')
    op.drop_column('cards', 'reopened')
    op.drop_column('cards', 'default_org_member_permission')
    op.drop_column('cards', 'import_status')
    op.drop_column('cards', 'default_card_group_type_id')
    op.drop_column('cards', 'is_list_archived')
    op.drop_column('cards', 'list_id')
    op.drop_column('cards', 'base_card_model_id')
    op.drop_column('cards', 'done')
    op.drop_column('cards', 'children_attributes_ctx')
    op.drop_column('cards', 'push_id')
    op.drop_column('cards', 'milestone_id')
    op.drop_column('cards', 'public_permission')
    op.drop_column('cards', 'owner_id')

    op.drop_table('card_member_permissions')
    op.drop_table('card_members')
    op.drop_table('card_enabled_models')
    op.drop_table('card_enabled_group_types')

    op.execute("""DELETE FROM card_group_types WHERE attribute_id IS NOT NULL and attribute_id NOT IN (select id from attributes)""")
    op.create_foreign_key(None, 'card_group_types', 'attributes', ['attribute_id'], ['id'], ondelete='CASCADE')
    op.create_foreign_key(None, 'card_log_types', 'users', ['created_by_id'], ['id'], ondelete='SET NULL')


def downgrade():
    pass