from src.batch.batch_functions import logging_sql
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 environment

logger = get_logger('卸販売洗替')


def exec():
    db = Database.get_instance(autocommit=True)
    try:
        db.connect()
        logger.debug('処理開始')
        # 卸販売実績テーブル（洗替後）過去５年以前のデータ削除
        _call_sales_lau_delete(db)
        # 卸販売実績テーブル（洗替後）作成
        _call_sales_lau_upsert(db)
        # １：卸組織洗替
        _call_whs_org_laundering(db)
        # ３：HCO施設コードの洗替
        _update_sales_lau_from_vop_hco_merge_v(db)
        # ４：メルク施設コードの洗替
        _update_mst_inst_laundering(db)
        logger.debug('処理終了')
    except Exception as e:
        raise BatchOperationException(e)
    finally:
        db.disconnect()


def _call_sales_lau_delete(db: Database):
    # 卸販売実績テーブル（洗替後）過去５年以前のデータ削除
    logger.info('sales_lau_delete(プロシージャ―) 開始')
    db.execute(f"""
                CALL src05.sales_lau_delete(
                    '{environment.SALES_LAUNDERING_TARGET_TABLE_NAME}',
                    {environment.SALES_LAUNDERING_TARGET_YEAR_OFFSET}
                )
        """)
    logger.info('sales_lau_delete(プロシージャ―) 終了')
    return


def _call_sales_lau_upsert(db: Database):
    # 卸販売実績テーブル（洗替後）作成
    logger.info('sales_lau_upsert(プロシージャ―) 開始')
    db.execute(f"""
                CALL src05.sales_lau_upsert(
                    '{environment.SALES_LAUNDERING_TARGET_TABLE_NAME}',
                    (src05.get_syor_date() - interval {environment.SALES_LAUNDERING_EXTRACT_DATE_PERIOD} day),
                    src05.get_syor_date()
                )
        """)
    logger.info('sales_lau_upsert(プロシージャ―) 終了')
    return


def _call_whs_org_laundering(db: Database):
    # 卸組織洗替
    logger.info('whs_org_laundering(プロシージャ―) 開始')
    db.execute(f"""
                CALL src05.whs_org_laundering(
                    '{environment.SALES_LAUNDERING_TARGET_TABLE_NAME}'
                )
        """)
    logger.info('whs_org_laundering(プロシージャ―) 終了')
    return


def _update_sales_lau_from_vop_hco_merge_v(db: Database):
    # HCO施設コードの洗替
    if _count_v_inst_merge_t(db) == 0:
        logger.info('V施設統合マスタ(洗替処理一時テーブル)にデータは存在しません')
        return

    _call_v_inst_merge_laundering(db)
    return


def _count_v_inst_merge_t(db: Database) -> int:
    # V施設統合マスタ(洗替処理一時テーブル)のデータ件数の取得
    try:
        sql = """
            SELECT
                COUNT(v_inst_cd) AS cnt
            FROM
                internal05.v_inst_merge_t
        """
        result = db.execute_select(sql)
        logging_sql(logger, sql)
        logger.info('V施設統合マスタ(洗替処理一時テーブル)のデータ件数の取得 成功')
    except Exception as e:
        logger.debug('V施設統合マスタ(洗替処理一時テーブル)のデータ件数の取得 失敗')
        raise e

    return result[0]['cnt']


def _call_v_inst_merge_laundering(db: Database):
    # HCO施設コードの洗替(プロシージャ―の呼び出し)
    logger.info('v_inst_merge_laundering(プロシージャ―) 開始')
    db.execute(f"""
                CALL src05.v_inst_merge_laundering(
                    '{environment.SALES_LAUNDERING_TARGET_TABLE_NAME}'
                )
        """)
    logger.info('v_inst_merge_laundering(プロシージャ―) 終了')
    return


def _update_mst_inst_laundering(db: Database):
    # メルク施設コードの洗替
    _call_hco_to_mdb_laundering(db)
    _update_sales_lau_from_dcf_inst_merge(db)


def _call_hco_to_mdb_laundering(db: Database):
    # A:医療機関のデータはMDB変換表からHCO⇒DCFへ変換
    logger.info('hco_to_mdb_laundering(プロシージャ―) 開始')
    db.execute(f"""
                CALL src05.hco_to_mdb_laundering(
                    '{environment.SALES_LAUNDERING_TARGET_TABLE_NAME}'
                )
        """)
    logger.info('hco_to_mdb_laundering(プロシージャ―) 終了')
    return


def _update_sales_lau_from_dcf_inst_merge(db: Database):
    # B:DCF施設統合マスタがある場合は、コードを変換し、住所等をSETする
    if _count_inst_merge_t(db) == 0:
        logger.info('アルトマーク施設統合マスタ(洗替処理一時テーブル)にデータは存在しません')
        return
    _call_inst_merge_laundering(db)
    return


def _count_inst_merge_t(db: Database) -> int:
    # アルトマーク施設統合マスタ(洗替処理一時テーブル)のデータ件数の取得
    try:
        sql = """
            SELECT
                COUNT(dcf_dsf_inst_cd) AS cnt
            FROM
                internal05.inst_merge_t
        """
        result = db.execute_select(sql)
        logging_sql(logger, sql)
        logger.info('アルトマーク施設統合マスタ(洗替処理一時テーブル)のデータ件数の取得 成功')
    except Exception as e:
        logger.debug('アルトマーク施設統合マスタ(洗替処理一時テーブル)のデータ件数の取得 失敗')
        raise e

    return result[0]['cnt']


def _call_inst_merge_laundering(db: Database):
    # B:DCF施設統合マスタがある場合は、コードを変換し、住所等をSETする(プロシージャ―の呼び出し)
    logger.info('inst_merge_laundering(プロシージャ―) 開始')
    db.execute(f"""
                CALL src05.inst_merge_laundering(
                    '{environment.SALES_LAUNDERING_TARGET_TABLE_NAME}'
                )
        """)
    logger.info('inst_merge_laundering(プロシージャ―) 終了')
    return
