# disease_code_processor.py
"""
疾患コード変換処理

移植時のCSVデータから各疾患ケースごとにコードを変換し、
指定されたフィールド（GENSIKKAN1_L ～ GENSIKKAN5_CMNT）に格納する処理を実装


既存のＪＳＯＮを利用した変換ロジックをもとに
移植時のCSVを参照して各ケースごとにＣＳＶファイルの値を参照して、下記の順番で格納していく処理を実装してほしい。
disease_code_mapping_regular関数などを参考にして

<格納する順番>
GENSIKKAN1_L
GENSIKKAN1_H
GENSIKKAN1_CMNT

GENSIKKAN2_L
GENSIKKAN2_H
GENSIKKAN2_CMNT

GENSIKKAN3_L
GENSIKKAN3_H
GENSIKKAN3_CMNT

GENSIKKAN4_L
GENSIKKAN4_H
GENSIKKAN4_CMNT

GENSIKKAN5_L
GENSIKKAN5_H
GENSIKKAN5_CMNT


【ケース1】


### 胆汁鬱滞性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]


[CSVの値 →　変換する値]
C1	0101
BA	0101
C2	0102
PBC	0102
C3	0103
PSC	0103
C4	0104
Alagille	0104
C5	0105
C5'	0106
C8	0107
C6	0108
Caroli	0108
肝内結石	0109
先天性胆道拡張症	0110


上記以外のデータは「0111」に設定する。

<該当フィールド>
GENSIKKAN1_L ～ GENSIKKAN5_L



### 胆汁鬱滞性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]

[CSVの値 →　変換する値]
胆汁鬱滞性疾患	01
腫瘍性疾患	02
肝細胞性疾患(肝硬変)	03
急性肝不全	04
代謝性疾患	05
血管性疾患	06
その他の疾患	07
再移植	08
不明	09


<該当フィールド>
GENSIKKAN1_H ～ GENSIKKAN5_H


### 胆汁鬱滞性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]

値をそのままデータベースに格納する。ただし、胆汁鬱滞性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]の変換された値が「0111」の場合、
胆汁鬱滞性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]と胆汁鬱滞性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]
の文字列を連結させて登録する。


<該当フィールド>
GENSIKKAN1_CMNT ～ GENSIKKAN5_CMNT


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


【ケース2】


### 腫瘍性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]

[CSVの値 →　変換する値]
N1	0201
HCC	0201
N5	0202
CCC	0203
N2	0204
肝芽腫	0204
Hemangioma	0205
Epithelioid hemangioendothelioma	0206

上記以外のデータは「0207」に設定する。


<該当フィールド>
GENSIKKAN1_H ～ GENSIKKAN5_H

### 腫瘍性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]

[CSVの値 →　変換する値]
N 02

<該当フィールド>
GENSIKKAN1_H ～ GENSIKKAN5_H

### 腫瘍性疾患-転移性（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]

値をそのままデータベースに格納する。ただし、腫瘍性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]の変換された値が「0207」の場合、
腫瘍性疾患-転移性（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]と腫瘍性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]の文字列を連結させて登録する。

<該当フィールド>
GENSIKKAN1_CMNT ～ GENSIKKAN5_CMNT


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


【ケース3】
### 肝細胞性疾患（肝硬変）-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]


[CSVの値 →　変換する値]
0301	H1
0301	HBV
0302	H2
0302	HCV
0303	H4
0303	アルコール性
0304	H3
0304	AIH
0305	H8
0305	NASH
0306	Infantile hepatitis
0307	Neonatal hepatitis
0308	原因不明の肝硬変


上記以外の値は「0309」に変換する

	
<該当フィールド>
GENSIKKAN1_L ～ GENSIKKAN5_L


### 肝細胞性疾患（肝硬変）-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]

[CSVの値 →　変換する値]
H 03

<該当フィールド>
GENSIKKAN1_H ～ GENSIKKAN5_H


### 肝細胞性疾患（肝硬変）-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]


値をそのままデータベースに格納する。ただし、肝細胞性疾患（肝硬変）-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]の変換された値が「0309」の場合、
肝細胞性疾患（肝硬変）-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]と肝細胞性疾患（肝硬変）-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]の文字列を連結させて登録する。


<該当フィールド>
GENSIKKAN1_CMNT ～ GENSIKKAN5_CMNT

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


【ケース4】
### 急性肝不全-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]


[CSVの値 →　変換する値]
HAV	0401
F1	0401
HBV	0402
	0403
AIH	0404
F4	0405
F2	0406
薬剤性	0406
F3	0407
F6	0408
原因不明	0408

上記以外の値は「0409」に変換する

	
<該当フィールド>
GENSIKKAN1_L ～ GENSIKKAN5_L


### 急性肝不全-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]

[CSVの値 →　変換する値]
F 04

<該当フィールド>
GENSIKKAN1_H ～ GENSIKKAN5_H


### 急性肝不全-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]


値をそのままデータベースに格納する。ただし、急性肝不全-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]の変換された値が「0409」の場合、
急性肝不全-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]と急性肝不全-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]の文字列を連結させて登録する。


<該当フィールド>
GENSIKKAN1_CMNT ～ GENSIKKAN5_CMNT


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


【ケース5】
### 代謝性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]



[CSVの値 →　変換する値]
M1	0501
Willson	0501
M2	0502
FAP	0502
M3	0503
Citrullinemia	0503	
M4	0504
OTC deficiency	0504	
M6	0506
Glycogen Strage Disease	0506
M8	0507
Methylmalonic acidemia	0507
M5	0509
Tyrosinemia	0509
M7	0510
Primary hyperoxaluria	0510
	

上記以外の値は「0511」に変換する

	
<該当フィールド>
GENSIKKAN1_L ～ GENSIKKAN5_L


### 代謝性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]


[CSVの値 →　変換する値]
M 05

<該当フィールド>
GENSIKKAN1_H ～ GENSIKKAN5_H


### 代謝性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]


値をそのままデータベースに格納する。ただし、代謝性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]の変換された値が「0511」の場合、
代謝性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]と代謝性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]の文字列を連結させて登録する。


<該当フィールド>
GENSIKKAN1_CMNT ～ GENSIKKAN5_CMNT


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


【ケース6】
### 血管性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]



[CSVの値 →　変換する値]
M1	501
Willson	501
M2	502
FAP	502
M3	503
Citrullinemia	503
M4	504
OTC deficiency	504	
M6	506
Glycogen Strage Disease	506
M8	507
Methylmalonic acidemia	507
M5	509
Tyrosinemia	509
M7	510
Primary hyperoxaluria	510

	
上記以外の値は「0511」に変換する

	
<該当フィールド>
GENSIKKAN1_L ～ GENSIKKAN5_L


### 血管性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]


[CSVの値 →　変換する値]
V 06

<該当フィールド>
GENSIKKAN1_H ～ GENSIKKAN5_H


### 血管性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]


値をそのままデータベースに格納する。ただし、血管性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]の変換された値が「0511」の場合、
血管性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]と血管性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]の文字列を連結させて登録する。


<該当フィールド>
GENSIKKAN1_CMNT ～ GENSIKKAN5_CMNT


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

【ケース7】


### その他の疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]


[CSVの値 →　変換する値]
Congenital hepatic fibrosis	0701
Polycystic liver(&amp;kidney)	0702
慢性肝GVHD:骨髄移植後	0703
その他	0704


<該当フィールド>
GENSIKKAN1_L ～ GENSIKKAN5_L


### その他の疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]


[CSVの値 →　変換する値]
胆汁鬱滞性疾患	01
腫瘍性疾患	02
肝細胞性疾患(肝硬変)	03
急性肝不全	04
代謝性疾患	05
血管性疾患	06
その他の疾患	07
再移植	08
不明	09

<該当フィールド>
GENSIKKAN1_H ～ GENSIKKAN5_H


### その他の疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]

値をそのままデータベースに格納する。

<該当フィールド>
GENSIKKAN1_CMNT ～ GENSIKKAN5_CMNT

胆汁鬱滞性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]　※カンマ区切り
胆汁鬱滞性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]の値はCのみで、値があった、01を設定する
胆汁鬱滞性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]



腫瘍性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]　※カンマ区切り
腫瘍性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]の値はNのみで、値があった、02を設定する
腫瘍性疾患-転移性（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]
腫瘍性疾患-他の原発性（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]

肝細胞性疾患（肝硬変）-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]　※カンマ区切り
肝細胞性疾患（肝硬変）-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]の値はHのみで、値があった、03を設定する
肝細胞性疾患（肝硬変）-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]



急性肝不全-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]　※カンマ区切り
急性肝不全-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]の値はFのみで、値があった、04を設定する
急性肝不全-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]


代謝性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]※カンマ区切り
代謝性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]の値はMのみで、値があった、05を設定する
代謝性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]


血管性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]※カンマ区切り
血管性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]の値はVのみで、値があった、06を設定する
血管性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]

その他の疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]※カンマ区切り
その他の疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]の値のみで、値があった、07を設定する
その他の疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]


        elif conv_type == "old_disease_code_mapping_regular":
            # 通常の疾患コード（管理者以外）の処理
            # すでにresultに存在するGENSIKKAN{n}_Hフィールドを確認し、使用済みインデックスを取得            
            disease_mappings = [
                # パターン①: 胆汁鬱滞性疾患
                {
                    "group_code_field": "胆汁鬱滞性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "disease_code_field": "胆汁鬱滞性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "h_value": "01",
                    "l_mappings": {
                        "C1": "101", "BA": "101", "C2": "102", "PBC": "102", "C3": "103", 
                        "PSC": "103", "C4": "104", "Alagille": "104", "C5": "105", "C5'": "106", 
                        "C8": "107", "C6": "108", "Caroli": "108", "肝内結石": "109"
                    },
                    "default_l": "111"
                },
                # パターン②: 腫瘍性疾患
                {
                    "group_code_field": "腫瘍性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "disease_code_field": "腫瘍性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "h_value": "02",
                    "l_mappings": {
                        "N1": "0201", "HCC": "0201", "N5": "0202", "CCC": "0203", "N2": "0204",
                        "肝芽腫": "0204", "Hemangioma": "0205", "Epithelioid hemangioendothelioma": "0206",
                        "N4": "0208", "転移性": "0208"
                    },
                    "default_l": "0207"
                },
                # パターン③: 肝細胞性疾患
                {
                    "group_code_field": "肝細胞性疾患（肝硬変）-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "disease_code_field": "肝細胞性疾患（肝硬変）-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "h_value": "03",
                    "l_mappings": {
                        "H1": "0301", "HBV": "0301", "H2": "0302", "HCV": "0302", "H4": "0303",
                        "アルコール性": "0303", "H3": "0304", "AIH": "0304", "H8": "0305", "NASH": "0305",
                        "Infantile hepatitis": "0306", "Neonatal hepatitis": "0307", "原因不明の肝硬変": "0308",
                        "H9": "0309", "その他": "0309"
                    },
                    "default_l": "0309"
                },
                # パターン④: 急性肝不全
                {
                    "group_code_field": "急性肝不全-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "disease_code_field": "急性肝不全-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "h_value": "04",
                    "l_mappings": {
                        "HAV": "0401", "F1": "0401", "HBV": "0402", "AIH": "0404", "F4": "0405",
                        "F2": "0406", "薬剤性": "0406", "F3": "0407", "F6": "0408", "原因不明": "0408",
                        "F9": "0409", "その他": "0409"
                    },
                    "default_l": "0409"
                },
                # パターン⑤: 代謝性疾患
                {
                    "group_code_field": "代謝性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "disease_code_field": "代謝性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "h_value": "05",
                    "l_mappings": {
                        "M1": "501", "Willson": "501", "M2": "502", "FAP": "502", "M3": "503",
                        "Citrullinemia": "503", "M4": "504", "OTC deficiency": "504", "M6": "506",
                        "Glycogen Strage Disease": "506", "M8": "507", "Methylmalonic acidemia": "507",
                        "M5": "509", "Tyrosinemia": "509", "M7": "510", "Primary hyperoxaluria": "510"
                    },
                    "default_l": "511"
                },
                # パターン⑥: 血管性疾患
                {
                    "group_code_field": "血管性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "disease_code_field": "血管性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "h_value": "06",
                    "l_mappings": {
                        "V1": "0601", "Budd-Chian症候群": "0601", "V2": "0602", "先天性門脈欠損症": "0602"
                    },
                    "default_l": "0603"
                },
                {
                    "group_code_field": "肝細胞性疾患（肝硬変）-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "disease_code_field": "肝細胞性疾患（肝硬変）-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]",
                    "h_value": "03",
                    "l_mappings": {
                        "H1": "0301", "HBV": "0301",
                        "H2": "0302", "HCV": "0302",
                        "H4": "0303", "アルコール性": "0303",
                        "H3": "0304", "AIH": "0304",
                        "H8": "0305", "NASH": "0305",
                        "Infantile hepatitis": "0306",
                        "Neonatal hepatitis": "0307",
                        "原因不明の肝硬変": "0308",
                        "H9": "0309", "その他": "0309"
                    },
                    "default_l": "0309"
                }
            ]
            filed_count = 1
            # 各疾患タイプを1回だけ処理するよう反復処理
            for mapping in disease_mappings:
                group_code_field = mapping["group_code_field"]
                disease_code_field = mapping["disease_code_field"]
                group_code_value = all_row[group_code_field]
                disease_code_value = all_row[disease_code_field]
                ## 群コード/疾患コードが入っていたら、default値を設定
                if group_code_value and disease_code_value:
                    code_list = str(disease_code_value).split(",")  # カンマで分割
                    ## 群コードdefault値を設定                    
                    code_list = [c.strip() for c in code_list if c.strip()]  # 空白除去
                    for code in code_list:
                        if filed_count >= 6:
                            continue    
                        group_code_value = mapping["h_value"]
                        disease_code_value = mapping["l_mappings"].get(code, mapping["default_l"])
                        result.append((f"GENSIKKAN{filed_count}_H", group_code_value, group_code_field))
                        result.append((f"GENSIKKAN{filed_count}_L", disease_code_value, disease_code_field))
                        filed_count = filed_count + 1
                else:
                    ## 群コードが入っていなかったら次のカラムを参照する
                    continue



select 
GENSIKKAN1_L,
GENSIKKAN1_H,
GENSIKKAN1_CMNT,
GENSIKKAN2_L,
GENSIKKAN2_H,
GENSIKKAN2_CMNT,
GENSIKKAN3_L,
GENSIKKAN3_H,
GENSIKKAN3_CMNT,
GENSIKKAN4_L,
GENSIKKAN4_H,
GENSIKKAN4_CMNT,
GENSIKKAN5_L,
GENSIKKAN5_H,
GENSIKKAN5_CMNT
from T_ISHOKU_KIHON_LIVER_LIV where SEITAI_ISYOKU_ID = 40728


疾患コード変換処理

移植時のCSVデータから各疾患ケースごとにコードを変換し、
指定されたフィールド（GENSIKKAN1_L ～ GENSIKKAN5_CMNT）に格納する処理を実装
"""

# disease_code_processor_updated.py
"""
疾患コード変換処理（カンマ区切り対応版）

更新仕様:
- 疾患コードはカンマ区切りで分割して1件ずつ登録
- 群コードは固定の文字列（C, N, H, F, M, V, その他）が入っていたら対応する番号（01-07）を設定
"""
import pandas as pd
from typing import List, Tuple, Optional
import numpy as np

class DiseaseCodeProcessor:
    def __init__(self):
        """
        疾患コード変換処理の初期化
        """
        # ケース1: 胆汁鬱滞性疾患の変換マップ
        self.case1_disease_code_map = {
            'C1': '0101', 'BA': '0101',
            'C2': '0102', 'PBC': '0102',
            'C3': '0103', 'PSC': '0103',
            'C4': '0104', 'Alagille': '0104',
            'C5': '0105', "C5'": '0106',
            'C8': '0107', 'C6': '0108',
            'Caroli': '0108', '肝内結石': '0109',
            '先天性胆道拡張症': '0110'
        }
        
        # ケース2: 腫瘍性疾患の変換マップ
        self.case2_disease_code_map = {
            'N1': '0201', 'HCC': '0201',
            'N5': '0202', 'CCC': '0203',
            'N2': '0204', '肝芽腫': '0204',
            'Hemangioma': '0205',
            'Epithelioid hemangioendothelioma': '0206'
        }
        
        # ケース3: 肝細胞性疾患（肝硬変）の変換マップ
        self.case3_disease_code_map = {
            'H1': '0301', 'HBV': '0301',
            'H2': '0302', 'HCV': '0302',
            'H4': '0303', 'アルコール性': '0303',
            'H3': '0304', 'AIH': '0304',
            'H8': '0305', 'NASH': '0305',
            'Infantile hepatitis': '0306',
            'Neonatal hepatitis': '0307',
            '原因不明の肝硬変': '0308'
        }
        
        # ケース4: 急性肝不全の変換マップ
        self.case4_disease_code_map = {
            'HAV': '0401', 'F1': '0401',
            'HBV': '0402',
            'AIH': '0404', 'F4': '0405',
            'F2': '0406', '薬剤性': '0406',
            'F3': '0407', 'F6': '0408',
            '原因不明': '0408'
        }
        
        # ケース5: 代謝性疾患の変換マップ
        self.case5_disease_code_map = {
            'M1': '0501', 'Willson': '0501',
            'M2': '0502', 'FAP': '0502',
            'M3': '0503', 'Citrullinemia': '0503',
            'M4': '0504', 'OTC deficiency': '0504',
            'M6': '0506', 'Glycogen Strage Disease': '0506',
            'M8': '0507', 'Methylmalonic acidemia': '0507',
            'M5': '0509', 'Tyrosinemia': '0509',
            'M7': '0510', 'Primary hyperoxaluria': '0510'
        }
        
        # ケース6: 血管性疾患の変換マップ
        self.case6_disease_code_map = {
            'V1': '0601', 'Budd-Chian症候群': '0601',
            'V2': '0602', '先天性門脈欠損症': '0602'
        }
        
        # ケース7: その他の疾患の変換マップ
        self.case7_disease_code_map = {
            'Congenital hepatic fibrosis': '0701',
            'Polycystic liver(&amp;kidney)': '0702',
            '慢性肝GVHD:骨髄移植後': '0703',
            'その他': '0704'
        }
        
        # 群コード変換マップ（固定文字列 → 番号）
        self.group_code_map = {
            'C': '01',    # 胆汁鬱滞性疾患
            'N': '02',    # 腫瘍性疾患
            'H': '03',    # 肝細胞性疾患（肝硬変）
            'F': '04',    # 急性肝不全
            'M': '05',    # 代謝性疾患
            'V': '06',    # 血管性疾患
            'その他': '07'  # その他の疾患
        }

    def has_valid_value(self, value) -> bool:
        """
        値が有効かどうかをチェック
        
        Args:
            value: チェック対象の値
            
        Returns:
            bool: 有効な値の場合True
        """
        if value is None:
            return False
        
        str_value = str(value).strip()
        
        # 空文字列、NaN、None、null等を無効とする
        if not str_value or str_value.lower() in ['nan', 'none', 'null']:
            return False
            
        return True
    
    def split_comma_separated_values(self, value: str) -> List[str]:
        """
        カンマ区切りの値を分割
        
        Args:
            value: カンマ区切りの文字列
            
        Returns:
            List[str]: 分割された値のリスト
        """
        if not self.has_valid_value(value):
            return []
        
        # カンマで分割し、各値をトリム
        values = [v.strip() for v in str(value).split(',')]
        # 空文字列を除外
        return [v for v in values if v]
    
    def process_case1_cholestatic_disease(self, row: pd.Series) -> List[Tuple[str, str, str]]:
        """
        ケース1: 胆汁鬱滞性疾患の処理（カンマ区切り対応）
        
        Returns:
            List[Tuple[str, str, str]]: (疾患コード, 群コード, コメント)のリスト
        """
        results = []
        
        # 疾患コードの処理（カンマ区切り対応）
        disease_code_value = row.get('胆汁鬱滞性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        disease_codes = self.split_comma_separated_values(disease_code_value)
        
        if not disease_codes:
            return results  # 疾患コードがない場合は処理しない
        
        # 群コードの変換（CSVの値をチェック）
        group_code_value = row.get('胆汁鬱滞性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        group_code = '01'  # デフォルト値
        if self.has_valid_value(group_code_value):
            group_code = self.group_code_map.get(str(group_code_value).strip(), '01')
        
        # コメントの取得
        text_comment = row.get('胆汁鬱滞性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        text_comment = str(text_comment).strip() if self.has_valid_value(text_comment) else ''
        
        # 各疾患コードに対して処理
        for disease_code_orig in disease_codes:
            disease_code = self.case1_disease_code_map.get(disease_code_orig, '0111')
            
            # コメントの処理
            comment = ''
            if disease_code == '0111':
                # 疾患コードが「その他」の場合、元の値とテキストを連結
                comment = f"{disease_code_orig}：{text_comment}" if text_comment else disease_code_orig
            else:
                # 通常の場合はテキストをそのまま格納
                comment = text_comment
            
            results.append((disease_code, group_code, comment))
        
        return results
    
    def process_case2_tumor_disease(self, row: pd.Series) -> List[Tuple[str, str, str]]:
        """
        ケース2: 腫瘍性疾患の処理（カンマ区切り対応）
        
        Returns:
            List[Tuple[str, str, str]]: (疾患コード, 群コード, コメント)のリスト
        """
        results = []
        
        # 疾患コードの処理（カンマ区切り対応）
        disease_code_value = row.get('腫瘍性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        disease_codes = self.split_comma_separated_values(disease_code_value)
        
        if not disease_codes:
            return results  # 疾患コードがない場合は処理しない
        
        # 群コードの変換
        group_code_value = row.get('腫瘍性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        group_code = '02'  # デフォルト値
        if self.has_valid_value(group_code_value):
            group_code = self.group_code_map.get(str(group_code_value).strip(), '02')
        
        # コメントの取得（転移性と他の原発性の両方）
        metastatic_comment = row.get('腫瘍性疾患-転移性（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        metastatic_comment = str(metastatic_comment).strip() if self.has_valid_value(metastatic_comment) else ''
        
        other_primary_comment = row.get('腫瘍性疾患-他の原発性（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        other_primary_comment = str(other_primary_comment).strip() if self.has_valid_value(other_primary_comment) else ''
        
        # 各疾患コードに対して処理
        for disease_code_orig in disease_codes:
            disease_code = self.case2_disease_code_map.get(disease_code_orig, '0207')
            
            # コメントの処理
            comment = ''
            if disease_code == '0207':
                # 疾患コードが「その他」の場合、元の値とテキストを連結
                combined_comment = f"{metastatic_comment} {other_primary_comment}".strip()
                comment = f"{disease_code_orig}：{combined_comment}" if combined_comment else disease_code_orig
            else:
                # 通常の場合はテキストをそのまま格納
                combined_comment = f"{metastatic_comment} {other_primary_comment}".strip()
                comment = combined_comment
            
            results.append((disease_code, group_code, comment))
        
        return results
    
    def process_case3_hepatocellular_disease(self, row: pd.Series) -> List[Tuple[str, str, str]]:
        """
        ケース3: 肝細胞性疾患（肝硬変）の処理（カンマ区切り対応）
        
        Returns:
            List[Tuple[str, str, str]]: (疾患コード, 群コード, コメント)のリスト
        """
        results = []
        
        # 疾患コードの処理（カンマ区切り対応）
        disease_code_value = row.get('肝細胞性疾患（肝硬変）-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        disease_codes = self.split_comma_separated_values(disease_code_value)
        
        if not disease_codes:
            return results
        
        # 群コードの変換
        group_code_value = row.get('肝細胞性疾患（肝硬変）-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        group_code = '03'  # デフォルト値
        if self.has_valid_value(group_code_value):
            group_code = self.group_code_map.get(str(group_code_value).strip(), '03')
        
        # コメントの取得
        text_comment = row.get('肝細胞性疾患（肝硬変）-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        text_comment = str(text_comment).strip() if self.has_valid_value(text_comment) else ''
        
        # 各疾患コードに対して処理
        for disease_code_orig in disease_codes:
            disease_code = self.case3_disease_code_map.get(disease_code_orig, '0309')
            
            # コメントの処理
            comment = ''
            if disease_code == '0309':
                # 疾患コードが「その他」の場合、元の値とテキストを連結
                comment = f"{disease_code_orig}：{text_comment}" if text_comment else disease_code_orig
            else:
                # 通常の場合はテキストをそのまま格納
                comment = text_comment
            
            results.append((disease_code, group_code, comment))
        
        return results
    
    def process_case4_acute_liver_failure(self, row: pd.Series) -> List[Tuple[str, str, str]]:
        """
        ケース4: 急性肝不全の処理（カンマ区切り対応）
        
        Returns:
            List[Tuple[str, str, str]]: (疾患コード, 群コード, コメント)のリスト
        """
        results = []
        
        # 疾患コードの処理（カンマ区切り対応）
        disease_code_value = row.get('急性肝不全-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        disease_codes = self.split_comma_separated_values(disease_code_value)
        
        if not disease_codes:
            return results
        
        # 群コードの変換
        group_code_value = row.get('急性肝不全-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        group_code = '04'  # デフォルト値
        if self.has_valid_value(group_code_value):
            group_code = self.group_code_map.get(str(group_code_value).strip(), '04')
        
        # コメントの取得
        text_comment = row.get('急性肝不全-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        text_comment = str(text_comment).strip() if self.has_valid_value(text_comment) else ''
        
        # 各疾患コードに対して処理
        for disease_code_orig in disease_codes:
            disease_code = self.case4_disease_code_map.get(disease_code_orig, '0409')
            
            # コメントの処理
            comment = ''
            if disease_code == '0409':
                # 疾患コードが「その他」の場合、元の値とテキストを連結
                comment = f"{disease_code_orig}：{text_comment}" if text_comment else disease_code_orig
            else:
                # 通常の場合はテキストをそのまま格納
                comment = text_comment
            
            results.append((disease_code, group_code, comment))
        
        return results
    
    def process_case5_metabolic_disease(self, row: pd.Series) -> List[Tuple[str, str, str]]:
        """
        ケース5: 代謝性疾患の処理（カンマ区切り対応）
        
        Returns:
            List[Tuple[str, str, str]]: (疾患コード, 群コード, コメント)のリスト
        """
        results = []
        
        # 疾患コードの処理（カンマ区切り対応）
        disease_code_value = row.get('代謝性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        disease_codes = self.split_comma_separated_values(disease_code_value)
        
        if not disease_codes:
            return results
        
        # 群コードの変換
        group_code_value = row.get('代謝性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        group_code = '05'  # デフォルト値
        if self.has_valid_value(group_code_value):
            group_code = self.group_code_map.get(str(group_code_value).strip(), '05')
        
        # コメントの取得
        text_comment = row.get('代謝性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        text_comment = str(text_comment).strip() if self.has_valid_value(text_comment) else ''
        
        # 各疾患コードに対して処理
        for disease_code_orig in disease_codes:
            disease_code = self.case5_disease_code_map.get(disease_code_orig, '0511')
            
            # コメントの処理
            comment = ''
            if disease_code == '0511':
                # 疾患コードが「その他」の場合、元の値とテキストを連結
                comment = f"{disease_code_orig}：{text_comment}" if text_comment else disease_code_orig
            else:
                # 通常の場合はテキストをそのまま格納
                comment = text_comment
            
            results.append((disease_code, group_code, comment))
        
        return results
    
    def process_case6_vascular_disease(self, row: pd.Series) -> List[Tuple[str, str, str]]:
        """
        ケース6: 血管性疾患の処理（カンマ区切り対応）
        
        Returns:
            List[Tuple[str, str, str]]: (疾患コード, 群コード, コメント)のリスト
        """
        results = []
        
        # 疾患コードの処理（カンマ区切り対応）
        disease_code_value = row.get('血管性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        disease_codes = self.split_comma_separated_values(disease_code_value)
        
        if not disease_codes:
            return results
        
        # 群コードの変換
        group_code_value = row.get('血管性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        group_code = '06'  # デフォルト値
        if self.has_valid_value(group_code_value):
            group_code = self.group_code_map.get(str(group_code_value).strip(), '06')
        
        # コメントの取得
        text_comment = row.get('血管性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        text_comment = str(text_comment).strip() if self.has_valid_value(text_comment) else ''
        
        # 各疾患コードに対して処理
        for disease_code_orig in disease_codes:
            disease_code = self.case6_disease_code_map.get(disease_code_orig, '0603')
            
            # コメントの処理
            comment = ''
            if disease_code == '0603':
                # 疾患コードが「その他」の場合、元の値とテキストを連結
                comment = f"{disease_code_orig}：{text_comment}" if text_comment else disease_code_orig
            else:
                # 通常の場合はテキストをそのまま格納
                comment = text_comment
            
            results.append((disease_code, group_code, comment))
        
        return results
    
    def process_case7_other_disease(self, row: pd.Series) -> List[Tuple[str, str, str]]:
        """
        ケース7: その他の疾患の処理（カンマ区切り対応）
        
        Returns:
            List[Tuple[str, str, str]]: (疾患コード, 群コード, コメント)のリスト
        """
        results = []
        
        # 疾患コードの処理（カンマ区切り対応）
        disease_code_value = row.get('その他の疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        disease_codes = self.split_comma_separated_values(disease_code_value)
        
        if not disease_codes:
            return results
        
        # 群コードの変換
        group_code_value = row.get('その他の疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        group_code = '07'  # デフォルト値
        if self.has_valid_value(group_code_value):
            group_code = self.group_code_map.get(str(group_code_value).strip(), '07')
        
        # コメントの取得
        text_comment = row.get('その他の疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]', '')
        text_comment = str(text_comment).strip() if self.has_valid_value(text_comment) else ''
        
        # 各疾患コードに対して処理
        for disease_code_orig in disease_codes:
            disease_code = self.case7_disease_code_map.get(disease_code_orig, '0705')
            
            # コメントの処理
            comment = ''
            if disease_code == '0705':
                # 疾患コードが「その他」の場合、元の値とテキストを連結
                comment = f"{disease_code_orig}{text_comment}" if text_comment else disease_code_orig
            else:
                # 通常の場合はテキストをそのまま格納
                comment = text_comment
            
            results.append((disease_code, group_code, comment))
        
        return results
    
    def process_disease_codes(self, df: pd.DataFrame) -> pd.DataFrame:
        """
        全ての疾患コードを処理してGENSIKKAN1_L～GENSIKKAN5_CMNTに格納
        
        Args:
            df: 処理対象のDataFrame
            
        Returns:
            pd.DataFrame: 処理後のDataFrame
        """
        # 結果フィールドを初期化
        for i in range(1, 6):
            df[f'GENSIKKAN{i}_L'] = ''
            df[f'GENSIKKAN{i}_H'] = ''
            df[f'GENSIKKAN{i}_CMNT'] = ''
        
        # 各行を処理
        for idx, row in df.iterrows():
            slot_index = 1  # 格納位置のインデックス
            
            # 各ケースを順番に処理
            case_functions = [
                self.process_case1_cholestatic_disease,
                self.process_case2_tumor_disease,
                self.process_case3_hepatocellular_disease,
                self.process_case4_acute_liver_failure,
                self.process_case5_metabolic_disease,
                self.process_case6_vascular_disease,
                self.process_case7_other_disease
            ]
            
            for case_func in case_functions:
                case_results = case_func(row)
                
                for disease_code, group_code, comment in case_results:
                    if slot_index > 5:
                        break  # 5件まで
                    
                    # 結果を格納
                    if disease_code:
                        df.at[idx, f'GENSIKKAN{slot_index}_L'] = disease_code
                    
                    if group_code:
                        df.at[idx, f'GENSIKKAN{slot_index}_H'] = group_code
                    
                    if comment:
                        df.at[idx, f'GENSIKKAN{slot_index}_CMNT'] = comment
                    
                    slot_index += 1
                
                if slot_index > 5:
                    break  # 5件まで
        
        return df


def test_updated_processor():
    """
    カンマ区切り対応のテスト
    """
    processor = DiseaseCodeProcessorUpdated()
    
    # カンマ区切りのテストデータ
    test_data = {
        # 胆汁鬱滞性疾患（カンマ区切り）
        '胆汁鬱滞性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['C1,PBC,unknown_code', '', ''],
        '胆汁鬱滞性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['C', '', ''],
        '胆汁鬱滞性疾患-その他（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]': ['胆汁コメント', '', ''],
        
        # 腫瘍性疾患（カンマ区切り）
        '腫瘍性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', 'HCC,N2,unknown_tumor', ''],
        '腫瘍性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', 'N', ''],
        '腫瘍性疾患-転移性（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '転移情報', ''],
        '腫瘍性疾患-他の原発性（テキスト）(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '他の原発情報', ''],
        
        # その他の疾患フィールド（空値）
        '肝細胞性疾患（肝硬変）-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', ''],
        '肝細胞性疾患（肝硬変）-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', ''],
        '急性肝不全-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', ''],
        '急性肝不全-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', ''],
        '代謝性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', ''],
        '代謝性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', ''],
        '血管性疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', ''],
        '血管性疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', ''],
        'その他の疾患-疾患コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', ''],
        'その他の疾患-群コード(R)[初回調査用紙（レシピエント／ドナー情報）]': ['', '', '']
    }
    
    df = pd.DataFrame(test_data)
    
    print("=== カンマ区切り対応テスト ===")
    print("行1: 胆汁鬱滞性疾患（3つのコード）")
    print("行2: 腫瘍性疾患（3つのコード）")
    print("行3: データなし")
    
    # 変換処理を実行
    result_df = processor.process_disease_codes(df)
    
    print("\n=== 変換結果 ===")
    for i in range(len(result_df)):
        print(f"\n行{i+1}の結果:")
        has_data = False
        for slot in range(1, 6):
            l_val = result_df.iloc[i].get(f'GENSIKKAN{slot}_L', '')
            h_val = result_df.iloc[i].get(f'GENSIKKAN{slot}_H', '')
            cmnt_val = result_df.iloc[i].get(f'GENSIKKAN{slot}_CMNT', '')
            
            if l_val or h_val or cmnt_val:
                print(f"  GENSIKKAN{slot}: L={l_val}, H={h_val}, CMNT={cmnt_val}")
                has_data = True
        
        if not has_data:
            print("  (該当データなし)")
    
    return result_df


if __name__ == "__main__":
    test_updated_processor()