from typing import List

from aiopg.sa.connection import SAConnection
import sqlalchemy as sa

from src import enitites
from src.enitites import DocumentType, EventType


metadata = sa.MetaData()


budget_position_fact_2021_08_18 = sa.Table(
    'budget_position_fact_2021_08_18',
    metadata,
    sa.Column('id', sa.BigInteger, primary_key=True, autoincrement=True),
    sa.Column('dataswamp_id', sa.BigInteger, unique=True),
    sa.Column('source_id', sa.BigInteger, unique=True),
    sa.Column('bp_code', sa.BigInteger, nullable=False),
    sa.Column('login', sa.String, nullable=True),
    sa.Column('status', sa.String, nullable=True),
    sa.Column('department_id', sa.BigInteger, nullable=True),
    sa.Column('valuestream_id', sa.BigInteger, nullable=True),
    sa.Column('event_type', sa.String, nullable=False),
    sa.Column('event_time', sa.DateTime, nullable=False),
    sa.Column('ticket1', sa.String, nullable=True),
    sa.Column('ticket2', sa.String, nullable=True),
    sa.Column('document_type', sa.Enum(DocumentType), nullable=False),
    sa.Column('document_id', sa.String, nullable=True),
    sa.Column('workflow_id', sa.String, nullable=True),
    sa.Column('hc', sa.BigInteger, nullable=True),
)


class DwhBpChangesRepository(enitites.DwhBpChangesRepositoryInterface):
    def __init__(self, connection: SAConnection):
        self._connection = connection

    def _change_to_db_value(self, change: enitites.BpChange) -> dict:
        return {
            'dataswamp_id': change.dataswamp_id,
            'source_id': change.source_id,
            'bp_code': change.bp_code,
            'login': change.login,
            'status': change.status,
            'department_id': change.department_id,
            'valuestream_id': change.valuestream_id,
            'event_type': str(change.event_type),
            'event_time': change.event_time,
            'ticket1': change.ticket1,
            'ticket2': change.ticket2,
            'document_type': change.document_type,
            'document_id': change.document_id,
            'workflow_id': change.workflow_id,
            'hc': change.hc,
        }

    async def get_last_processed_id(self) -> int:
        request = budget_position_fact_2021_08_18.select()
        request = request.order_by(sa.desc(budget_position_fact_2021_08_18.c.dataswamp_id)).limit(1)
        rows = await self._connection.execute(request)

        async for row in rows:
            return row[budget_position_fact_2021_08_18.c.dataswamp_id]

        return -1

    async def add_changes(self, changes: List[enitites.BpChange]):
        values = [
            self._change_to_db_value(change)
            for change in changes
        ]
        if values:
            await self._connection.execute(budget_position_fact_2021_08_18.insert().values(values))
