from .. import migration

import sqlalchemy
import json


@migration.migration_class(21)
class DBMigrateMergeExceptionHandling(migration.DBMigration):
    """Merge hide-exception and block-failed-request-output into a single exception-handling select option,
    and add failure-hint field.

    Conversion logic:
    - block-failed-request-output=true  ->  exception-handling: hide
    - hide-exception=true               ->  exception-handling: show-hint
    - hide-exception=false              ->  exception-handling: show-error
    """

    async def upgrade(self):
        """Upgrade"""
        result = await self.ap.persistence_mgr.execute_async(
            sqlalchemy.text('SELECT uuid, config FROM legacy_pipelines')
        )
        pipelines = result.fetchall()

        current_version = self.ap.ver_mgr.get_current_version()

        for pipeline_row in pipelines:
            uuid = pipeline_row[0]
            config = json.loads(pipeline_row[1]) if isinstance(pipeline_row[1], str) else pipeline_row[1]

            if 'output' not in config:
                config['output'] = {}
            if 'misc' not in config['output']:
                config['output']['misc'] = {}

            misc = config['output']['misc']

            # Determine new exception-handling value from legacy fields
            hide_exception = misc.get('hide-exception', True)
            block_failed = misc.get('block-failed-request-output', False)

            if block_failed:
                exception_handling = 'hide'
            elif hide_exception:
                exception_handling = 'show-hint'
            else:
                exception_handling = 'show-error'

            misc['exception-handling'] = exception_handling

            # Add failure-hint with default value
            misc['failure-hint'] = 'Request failed.'

            # Remove legacy fields
            misc.pop('hide-exception', None)

            if self.ap.persistence_mgr.db.name == 'postgresql':
                await self.ap.persistence_mgr.execute_async(
                    sqlalchemy.text(
                        'UPDATE legacy_pipelines SET config = :config::jsonb, for_version = :for_version WHERE uuid = :uuid'
                    ),
                    {'config': json.dumps(config), 'for_version': current_version, 'uuid': uuid},
                )
            else:
                await self.ap.persistence_mgr.execute_async(
                    sqlalchemy.text(
                        'UPDATE legacy_pipelines SET config = :config, for_version = :for_version WHERE uuid = :uuid'
                    ),
                    {'config': json.dumps(config), 'for_version': current_version, 'uuid': uuid},
                )

    async def downgrade(self):
        """Downgrade"""
        pass
