import logging
from starlette.applications import Starlette

from src.enitites import RegistryChangeEvent, BpChange, DocumentType, EventType
from src.gateways import DwhBpChangesRepository, DataswampRegistryRepository
from src.db_engine import create_engine, create_dataswamp_engine

logger = logging.getLogger(__name__)


def registry_change_to_dwh(ev: RegistryChangeEvent):
    document_type = (
        DocumentType.proposal
        if ev.proposal_id
        else DocumentType.vacancy
    )

    document_id = (
        ev.proposal_id
        if document_type == DocumentType.proposal
        else str(ev.vacancy_id)
    )

    workflow_code_to_event_type_mapping = {
        '1.1': EventType.open_vacancy,
        '1.1.1': EventType.transfer_vacancy,
        '1.2': EventType.credit_vacancy,
        '1.3': EventType.vacancy_cancellation,
        '2.1': EventType.open_vacancy,
        '5.1': EventType.offer,
        '5.1.1': EventType.position_assignment,
        '5.2': EventType.offer_declined,
        '5.3': EventType.internal_offer,
        '7.2': EventType.transfer_headcount,
        '7.3': EventType.transfer_to_new_budget_position,
        '8.0': EventType.credit_closure_with_active_vacancy,
        '8.1': EventType.credit_closure,
    }

    event_type = workflow_code_to_event_type_mapping.get(ev.workflow_code, EventType.unknown)

    if ev.workflow_code == '7.1':
        if ev.department_id is not None:
            event_type = EventType.transfer_to_other_department
        else:
            event_type = EventType.other_employee_changes

    return BpChange(
        dataswamp_id=ev.id,
        source_id=ev.source_id,
        bp_code=ev.budget_position_code or 0,
        login=ev.login,
        status=None,
        department_id=ev.department_id,
        valuestream_id=None,
        event_type=event_type,
        event_time=ev.resolved_at,
        ticket1=ev.ticket,
        ticket2=ev.optional_ticket,
        document_type=document_type,
        document_id=document_id,
        workflow_id=ev.workflow_id,
        hc=ev.headcount,
    )


async def pull_registry_changes():
    async with create_dataswamp_engine() as dataswamp_engine:
        async with dataswamp_engine.acquire() as dataswamp_connection:
            async with create_engine() as dwh_engine:
                async with dwh_engine.acquire() as dwh_connection:
                    dataswamp_repo = DataswampRegistryRepository(dataswamp_connection)
                    dwh_repo = DwhBpChangesRepository(dwh_connection)
                    last_processed_id = await dwh_repo.get_last_processed_id()
                    logger.info('Last processed id: %s', last_processed_id)
                    registry_changes = await dataswamp_repo.all_changes(last_processed_id)
                    bp_changes = [
                        registry_change_to_dwh(registry_change)
                        for registry_change in registry_changes
                    ]
                    logger.info('Processing %s changes', len(bp_changes))
                    await dwh_repo.add_changes(bp_changes)


class PullRegistryData:
    async def run(self, app: Starlette) -> bool:
        await pull_registry_changes()
        return False
