"""アルトマークデータ処理"""

from datetime import datetime

from src.aws.s3 import UltmarcBucket
from src.batch.common.batch_context import BatchContext
from src.batch.ultmarc.datfile import DatFile
from src.batch.ultmarc.utmp_tables.ultmarc_table_mapper_factory import \
    UltmarcTableMapperFactory
from src.db.database import Database
from src.error.exceptions import BatchOperationException
from src.logging.get_logger import get_logger
from src.system_var import constants

logger = get_logger('アルトマークデータ処理')
ultmarc_bucket = UltmarcBucket()
batch_context = BatchContext.get_instance()


def exec_import():
    """アルトマーク取り込み処理"""
    try:
        logger.info('アルトマーク取込処理: 開始')
        # datファイルをS3から取得する
        dat_file_list = ultmarc_bucket.list_dat_file()

        # ファイルがない場合は処理せず、正常終了とする
        if len(dat_file_list) == 0:
            logger.info('取込ファイルがないため、アルトマーク取込処理をスキップします')
            # アルトマークデータ受信予定曜日である月曜日は、保守ユーザーに通知する
            if datetime.strptime(batch_context.syor_date, '%Y/%m/%d').weekday() == constants.WEEKDAY_MONDAY:
                logger.info('[NOTICE]アルトマークデータの受信がありませんでした')
            return

        # ファイルが複数ある場合はエラーとする
        if len(dat_file_list) > 1:
            raise BatchOperationException(f'複数の取込ファイルがあるため、異常終了 ファイル一覧:{dat_file_list}')

        # ファイルの件数は必ず1件になる
        dat_file_info = dat_file_list[0]
        # 0Byteの場合、
        if dat_file_info['size'] == 0:
            logger.info(f'0Byteファイルのため、処理をスキップします。ファイル名={dat_file_info["filename"]}')
            return

        dat_file_name = dat_file_info['filename']
        logger.info(f"{dat_file_name}を取り込みます")
        # datファイルをダウンロード
        local_file_path = ultmarc_bucket.download_dat_file(dat_file_name)
        dat_file = DatFile.from_path(local_file_path)
        # アルトマーク取り込み実行
        _import_to_ultmarc_table(dat_file)
        # 処理後ファイルをバックアップ
        ultmarc_bucket.backup_dat_file(dat_file_name, batch_context.syor_date)
        logger.info(f'取り込み処理が完了したため、datファイルをバックアップ。ファイル名={dat_file_name}')
        # アルトマーク取込済をマーク
        batch_context.is_ultmarc_imported = True
        logger.info('アルトマーク取込処理: 終了')
    except Exception as e:
        raise BatchOperationException(e)


def exec_export():
    """V実消化用施設・薬局薬店データ作成処理"""
    if not batch_context.is_ultmarc_imported:
        logger.info('アルトマーク取込が行われていないため、V実消化用施設・薬局薬店データ作成処理をスキップします。')
        return


def _import_to_ultmarc_table(dat_file: DatFile):
    db = Database.get_instance()
    try:
        # DB接続
        db.connect()
        # ファイル単位でトランザクションを行う
        db.begin()
        mapper_factory = UltmarcTableMapperFactory()
        # datファイルを1行ずつ処理し、各テーブルへ登録
        for line in dat_file:
            try:
                # 書き込み先のテーブルを特定
                mapper_class = mapper_factory.create(
                    line.layout_class,
                    line.records,
                    db
                )
                mapper_class.make_query()
                mapper_class.execute_queries()
                dat_file.count_up_success()
            except Exception as e:
                logger.info(e)
                record = line.records
                log_message = ','.join([f'"{r}"' for r in record])
                logger.info(f'ERROR_LINE: {log_message}')
                dat_file.count_up_error()
        # 処理結果をログに出力する
        logger.info(f'ultmarc import process RESULT')
        logger.info(f'SUCCESS_COUNT={dat_file.success_count}')
        logger.info(f'ERROR_COUNT={dat_file.error_count}')
        logger.info(f'ALL_COUNT={dat_file.total_count}')

        # 1件でもエラーがあれば、通知用にログに出力する
        if dat_file.error_count > 0:
            logger.warning('取り込みに失敗した行があります。詳細は`ERROR_LINE:`の行を確認してください。')
    finally:
        # 終了時に必ずコミットする
        db.commit()
        db.disconnect()
    return
