from src.batch.ultmarc.utmp_tables.table_mapper.ultmarc_table_mapper import \
    UltmarcTableMapper
from src.batch.ultmarc.utmp_tables.tables.com_pharm import ComPharm


class ComPharmMapper(UltmarcTableMapper):
    """レイアウト区分102: COM_薬局 登録処理 """

    # レコード存在確認SQL
    RECORD_EXISTS_QUERY = """\
    SELECT
        COUNT(*) AS count_num
    FROM
        src05.com_pharm
    WHERE
        dcf_dsf_inst_cd = :dcfdsf_inst_cd
    """
    # データ登録用SQL
    INSERT_QUERY = """\
    INSERT INTO src05.com_pharm
    (
        dcf_dsf_inst_cd,
        inst_div_cd,
        addr_unknown_reason_cd,
        form_inst_name_kana,
        inst_name_kana,
        form_inst_name_kanji,
        inst_name_kanji,
        close_flg,
        estab_sche_flg,
        close_start_ym,
        estab_sche_ym,
        inst_repre_kana,
        inst_repre,
        phone_number_non_flg,
        unconf_flg,
        inst_phone_number,
        inst_addr_kana,
        inst_addr,
        postal_number,
        village_cd,
        prefc_cd,
        city_cd,
        addr_display_number,
        addr_cnt_kana,
        addr_cnt,
        manage_cd,
        delete_sche_reason_cd,
        dup_opp_cd,
        supervising_pharmacist,
        supervising_pharmacist_kana,
        franchise_hq_cd,
        inst_pharm_div,
        abolish_ymd,
        delete_flg,
        sys_regist_date,
        regist_prgm_id,
        sys_update_date,
        update_prgm_id
    )
    VALUES (
        :dcfdsf_inst_cd,
        :hpclass_code,
        :hp_addr_lost_code,
        :hp_name_kana,
        :hp_ryaku_name_kana,
        :hp_name,
        :hp_ryaku_name,
        :close_flg,
        :open_flag,
        :close_yearmonth,
        :open_yearmonth,
        :president_Kana,
        :president,
        :tel_nothing_flag,
        :unconf_flg,
        :tel_number,
        :addr_kana,
        :addr,
        :zip_code,
        :village_code,
        :prefc_cd,
        :city_cd,
        :addr_number,
        :addr_count_kana,
        :addr_count,
        :mgtclass_code,
        :del_cd,
        :dup_opp_cd,
        :pharmacist,
        :pharmacist_kana,
        :franchise_hq_cd,
        2,
        NULL,
        0,
        :execute_datetime,
        :program_name,
        :execute_datetime,
        :program_name
    )
    """
    # 更新用SQL
    UPDATE_QUERY = """\
    UPDATE src05.com_pharm
    SET
        {update_columns}
        sys_update_date = :execute_datetime,
        update_prgm_id = :program_name
    WHERE
        dcf_dsf_inst_cd = :dcfdsf_inst_cd
    """

    # 修正区分が「C(削除)」の場合の更新SQL
    # 廃業年月日 ← メンテナンス年月日
    LOGICAL_DELETE_QUERY = """\
    UPDATE
        src05.com_pharm
    SET
        abolish_ymd = :maintdate,
        sys_update_date = :execute_date_str_ymd,
        update_prgm_id = :program_name
    WHERE
        dcf_dsf_inst_cd = :dcfdsf_inst_cd
    """
    record: ComPharm

    def __init__(self, record: list[str], db) -> None:
        super().__init__(record, db, ComPharm)
        program_name = __name__.split('.')[-1]  # 当モジュール名(現行から変わっている)
        # モジュール名をクエリパラメータに設定
        self.query_parameter['program_name'] = program_name
        # 読み込んだレコード値もクエリパラメータに追加
        self.query_parameter = {**self.query_parameter, **self.record.to_sql_parameter()}

    def make_query(self):
        # 修正区分がC(削除)の場合、論理削除
        if self.record.maint_flag == 'C':
            self.queries.append(self.LOGICAL_DELETE_QUERY)
            return

        # 追加、更新の場合
        self.queries.append(self.__make_upsert_query())
        return

    def __make_upsert_query(self):
        # レコードの存在確認
        record_count = self.db.execute_select(self.RECORD_EXISTS_QUERY, self.query_parameter)
        # 存在しない場合はInsert
        if record_count[0]['count_num'] == 0:
            return self.INSERT_QUERY

        # 更新の場合
        update_columns = ','.join(self.__make_update_query())
        # 何も更新項目が無い場合はNoneとする（更新処理は行わない）
        if len(update_columns) == 0:
            return None
        else:
            # 末尾にカンマを付けてSET句を完成させる
            update_columns += ','
            update_query = self.UPDATE_QUERY.format(
                update_columns=update_columns
            )
            return update_query

    def __make_update_query(self):
        set_clauses = []  # 設定項目

        # 設定項目の判定
        # DCFDSF施設コード(主キーなので更新対象外)

        # 施設区分コード
        if self.record.hpclass_code != '':
            set_clauses.append('inst_div_cd = :hpclass_code')

        # 住所不明理由コード
        if self.record.hp_addr_lost_code != '':
            set_clauses.append('addr_unknown_reason_cd = :hp_addr_lost_code')
            self.query_parameter['hp_addr_lost_code'] = None if self.record.hp_addr_lost_code == '@' else self.record.hp_addr_lost_code

        # 正式施設名カナ
        if self.record.hp_name_kana != '':
            set_clauses.append('form_inst_name_kana = :hp_name_kana')

        # 施設名カナ
        if self.record.hp_ryaku_name_kana != '':
            set_clauses.append('inst_name_kana = :hp_ryaku_name_kana')

        # 正式施設名（漢字）
        if self.record.hp_name != '':
            set_clauses.append('form_inst_name_kanji = :hp_name')

        # 施設名（漢字）
        if self.record.hp_ryaku_name != '':
            set_clauses.append('inst_name_kanji = :hp_ryaku_name')

        # 休院フラグ、休院予定年月
        if len(self.record.close_flg + self.record.close_yearmonth) > 0:
            set_clauses.append('close_flg = :close_flg')
            set_clauses.append('close_start_ym = :close_yearmonth')
            if self.record.close_flg == '@':
                self.query_parameter['close_flg'] = None
                self.query_parameter['close_yearmonth'] = None

        # 開業予定フラグ、開業予定年月
        if len(self.record.open_flag + self.record.open_yearmonth) > 0:
            set_clauses.append('estab_sche_flg = :open_flag')
            set_clauses.append('estab_sche_ym = :open_yearmonth')
            if self.record.open_flag == '@':
                self.query_parameter['open_flag'] = None
                self.query_parameter['open_yearmonth'] = None

        # 施設代表者カナ
        if self.record.president_Kana != '':
            set_clauses.append('inst_repre_kana = :president_Kana')
            self.query_parameter['president_Kana'] = None if self.record.president_Kana == '@' else self.record.president_Kana

        # 施設代表者　※＠が大文字
        if self.record.president != '':
            set_clauses.append('inst_repre = :president')
            self.query_parameter['president'] = None if self.record.president == '＠' else self.record.president

        # 電話番号なしフラグ
        if self.record.tel_nothing_flag != '':
            set_clauses.append('phone_number_non_flg = :tel_nothing_flag')
            self.query_parameter['tel_nothing_flag'] = None if self.record.tel_nothing_flag == '@' else self.record.tel_nothing_flag

        # 未確認フラグ
        if self.record.unconf_flg != '':
            set_clauses.append('unconf_flg = :unconf_flg')
            self.query_parameter['unconf_flg'] = None if self.record.unconf_flg == '@' else self.record.unconf_flg

        # 施設電話番号
        if self.record.tel_number != '':
            set_clauses.append('inst_phone_number = :tel_number')
            self.query_parameter['tel_number'] = None if self.record.tel_number == '@' else self.record.tel_number

        # 施設住所カナ
        if self.record.addr_kana != '':
            set_clauses.append('inst_addr_kana = :addr_kana')

        # 施設住所
        if self.record.addr != '':
            set_clauses.append('inst_addr = :addr')

        # 郵便番号
        if self.record.zip_code != '':
            set_clauses.append('postal_number = :zip_code')

        # 町字コード(住所コード)
        if len(self.record.village_code) > 0:
            set_clauses.append('village_cd = :village_code')    # 住所コード
            set_clauses.append('prefc_cd = :prefc_cd')          # 都道府県コード
            set_clauses.append('city_cd = :city_cd')            # 市区町村コード

        # 住所表示番号
        if self.record.addr_number != '':
            set_clauses.append('addr_display_number = :addr_number')
            self.query_parameter['addr_number'] = None if self.record.addr_number == '@' else self.record.addr_number

        # 住所カウント(集合項目である県コードが入っていればカウントをセットする)
        if len(self.record.prefc_cd) > 0:
            set_clauses.append('addr_cnt = :addr_count')            # 住所カウント
            set_clauses.append('addr_cnt_kana = :addr_count_kana')  # 住所カウントカナ

        # 経営体コード
        if self.record.mgtclass_code != '':
            set_clauses.append('manage_cd = :mgtclass_code')
            self.query_parameter['mgtclass_code'] = None if self.record.mgtclass_code == '@' else self.record.mgtclass_code

        # 削除予定理由コード
        if self.record.del_cd != '':
            set_clauses.append('delete_sche_reason_cd = :del_cd')
            self.query_parameter['del_cd'] = None if self.record.del_cd == '@' else self.record.del_cd

        # 重複時相手先コード
        if self.record.dup_opp_cd != '':
            set_clauses.append('dup_opp_cd = :dup_opp_cd')
            self.query_parameter['dup_opp_cd'] = None if self.record.dup_opp_cd == '@' else self.record.dup_opp_cd

        # 管理薬剤師名(漢字)※＠が大文字
        if self.record.pharmacist != '':
            set_clauses.append('supervising_pharmacist = :pharmacist')
            self.query_parameter['pharmacist'] = None if self.record.pharmacist == '＠' else self.record.pharmacist

        # 管理薬剤師名(カナ)
        if self.record.pharmacist_kana != '':
            set_clauses.append('supervising_pharmacist_kana = :pharmacist_kana')
            self.query_parameter['pharmacist_kana'] = None if self.record.pharmacist_kana == '@' else self.record.pharmacist_kana

        # チェーン店本部コード
        if self.record.franchise_hq_id != '':
            set_clauses.append('franchise_hq_cd = :franchise_hq_cd')
            if self.record.franchise_hq_id == '@':
                self.query_parameter['franchise_hq_cd'] = None

        return set_clauses
