"""attribute_groups

Revision: 0064
Revision ID: 24191069ca2a
Revises: 2a74262efd7d
Create Date: 2016-06-14 11:48:39.567572

"""

# revision identifiers, used by Alembic.
revision = '24191069ca2a'
down_revision = '2a74262efd7d'
branch_labels = None
depends_on = None

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

card_models = sa.Table(
    'card_models',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('owner_id', sa.Integer),
    sa.Column('attribute_group_id', sa.Integer),
    sa.Column('created_at', sa.DateTime)
)
card_model_attributes = sa.Table(
    'card_model_attributes',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('card_model_id', sa.Integer),
    sa.Column('card_id', sa.Integer),
    sa.Column('group_id', sa.Integer)
)
cards = sa.Table(
    'cards',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('owner_id', sa.Integer),
    sa.Column('self_attribute_group_id', sa.Integer),
    sa.Column('created_at', sa.DateTime)
)

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

    attribute_groups = op.create_table('attribute_groups',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('owner_id', sa.Integer(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=True),
        sa.Column('updated_at', sa.DateTime(), nullable=True),
        sa.Column('shared_context', sa.PickleType(), nullable=True),
        sa.ForeignKeyConstraint(['owner_id'], ['organizations.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_attribute_groups_owner_id'), 'attribute_groups', ['owner_id'], unique=False)

    op.add_column('card_model_attributes', sa.Column('group_id', sa.Integer(), nullable=True))
    op.create_index(op.f('ix_attributes_group_id'), 'card_model_attributes', ['group_id'], unique=False)
    op.create_foreign_key(None, 'card_model_attributes', 'attribute_groups', ['group_id'], ['id'], ondelete='SET NULL')

    op.add_column('card_models', sa.Column('attribute_group_id', sa.Integer(), nullable=True))
    op.create_index(op.f('ix_card_models_attribute_group_id'), 'card_models', ['attribute_group_id'], unique=False)
    op.create_foreign_key(None, 'card_models', 'attribute_groups', ['attribute_group_id'], ['id'], ondelete='SET NULL')

    op.add_column('cards', sa.Column('self_attribute_group_id', sa.Integer(), nullable=True))
    op.create_index(op.f('ix_cards_self_attribute_group_id'), 'cards', ['self_attribute_group_id'], unique=False)
    op.create_foreign_key(None, 'cards', 'attribute_groups', ['self_attribute_group_id'], ['id'], ondelete='SET NULL')

    q = select([card_models.c.id, card_models.c.owner_id, card_models.c.created_at])
    for model in conn.execute(q):
        r = conn.execute(attribute_groups.insert().values(
            owner_id=model.owner_id,
            created_at=model.created_at
        ))
        conn.execute(card_models.update().where(card_models.c.id==model.id).values(
            attribute_group_id=r.inserted_primary_key[0]
        ))
        conn.execute(card_model_attributes.update().where(card_model_attributes.c.card_model_id==model.id).values(
            group_id=r.inserted_primary_key[0]
        ))

    subq = select([card_model_attributes.c.card_id]).where(card_model_attributes.c.card_id != None)\
            .group_by(card_model_attributes.c.card_id)
    q = select([cards.c.id, cards.c.owner_id, cards.c.created_at]).where(cards.c.id.in_(subq))
    for card in conn.execute(q):
        r = conn.execute(attribute_groups.insert().values(
            owner_id=card.owner_id,
            created_at=card.created_at
        ))
        conn.execute(cards.update().where(cards.c.id==card.id).values(
            self_attribute_group_id=r.inserted_primary_key[0]
        ))
        conn.execute(card_model_attributes.update().where(card_model_attributes.c.card_id==card.id).values(
            group_id=r.inserted_primary_key[0]
        ))

    op.drop_index('ix_card_attributes_card_model_attribute_id', table_name='card_attributes')
    op.drop_constraint('card_attribute_card_model_attribute_id', 'card_attributes', type_='foreignkey')
    op.add_column('card_attributes', sa.Column('attribute_id', sa.Integer(), nullable=True))
    op.execute("UPDATE card_attributes SET attribute_id = card_model_attribute_id")

    op.drop_constraint('card_model_attributes_card_id_fkey', 'card_model_attributes', type_='foreignkey')
    op.drop_constraint('card_model_attributes_card_model_id_fkey', 'card_model_attributes', type_='foreignkey')
    op.rename_table("card_model_attributes", "attributes")

    op.create_index(op.f('ix_card_attributes_attribute_id'), 'card_attributes', ['attribute_id'], unique=False)
    op.create_foreign_key(None, 'card_attributes', 'attributes', ['attribute_id'], ['id'], ondelete='CASCADE')

    op.drop_column('card_attributes', 'card_model_attribute_id')
    op.drop_column('card_models', 'has_builtin_attributes')
    op.drop_index('ix_card_models_builtin', table_name='card_models')


def downgrade():
    pass