import os
import re
import pandas as pd
from typing import Dict, Optional, Tuple, Union


class Excel:
    def __init__(self, exel_path):
        self.path = exel_path
    
    def extract_data(self):
        df = pd.read_excel(self.path)

        #　key : Case Numner, value : 合併症の有無（True : 合併症あり，False : 合併症なし）
        data = {}

        for _, row in df.iterrows():
            # if row["除外理由"]:
            #     continue
            if pd.notna(row["No"]) and pd.notna(row["No/Slow flow during procedure"]) and pd.notna(row["IVUS解析除外"]):
                case_num = int(row["No"])

                if row["No/Slow flow during procedure"] == 1:
                    data[int(case_num)] = True
                elif row["No/Slow flow during procedure"] == 0:
                    data[int(case_num)] = False

        # for k, v in data.items():
        #     print(f"Case Number : {k}, Complication : {v}")
            
        return data
    
    def rename(self, root_dir):
        data_dict = self.extract_data()
        No_data = []

        for case in os.listdir(root_dir):
            case_dir = os.path.join(root_dir, case)
            if os.path.isdir(case_dir):
                images_dir = os.path.join(case_dir, "images") # IVUS元画像用のディレクトリ

                for image in os.listdir(images_dir):
                    image_path = os.path.join(images_dir, image)
                    rest_path, ext = os.path.splitext(image)    
                    parts = rest_path.split("_")
                    case_num = int(float(parts[1]))

                    # ファイル名に "_T" または "_F" が含まれている画像ファイルはリネーム処理の対象外
                    if image.endswith("_T.png") or image.endswith("_F.png"):
                        continue

                    if case_num not in data_dict:
                        No_data.append(case_num)
                        continue

                    """
                        合併症の有無によってファイル名を変更
                        合併症の場合 : frame_49_4020_T.png, frame_49_4020_F.png
                    """
                    if data_dict[case_num]:
                        new_image_name = f"{parts[0]}_{case_num}_{parts[-1]}_T{ext}"
                    else:
                        new_image_name = f"{parts[0]}_{case_num}_{parts[-1]}_F{ext}"
                    
                    new_image_path = os.path.join(images_dir, new_image_name)
                    os.rename(image_path, new_image_path)
        
        No_data = sorted(set(No_data))
        for case_num in No_data:
            print(f"Case Number : {case_num} is not found in the excel file.")
        print(f"Total {len(No_data)} cases are not found in the excel file.")
    
    def improve_name(self, root_dir):
        for case in os.listdir(root_dir):
            case_dir = os.path.join(root_dir, case)
            if os.path.isdir(case_dir):
                images_dir = os.path.join(case_dir, "images")

                for image in os.listdir(images_dir):
                    image_path = os.path.join(images_dir, image)
                    
                    rest_name, ext = os.path.splitext(image)
                    parts = rest_name.split("_")

                    if parts[-2] == "F" or parts[-2] == "T":
                        new_image_name = f"{parts[0]}_{parts[1]}_{parts[-1]}_{parts[-2]}{ext}"
                        new_image_path = os.path.join(images_dir, new_image_name)
                        os.rename(image_path, new_image_path)

    def restore_name(self, root_dir):
        for case in os.listdir(root_dir):
            case_dir = os.path.join(root_dir, case)
            if os.path.isdir(case_dir):
                images_dir = os.path.join(case_dir, 'images')

                for image in os.listdir(images_dir):
                    image_path = os.path.join(images_dir, image)

                    rest_name, ext = os.path.splitext(image)
                    parts = rest_name.split("_")    # frame_66_60_F

                    if parts[-1] == "F" or parts[-1] == "T":
                        new_image_name = f"{parts[0]}_{parts[1]}_{parts[2]}{ext}"
                        new_image_path = os.path.join(images_dir, new_image_name)
                        os.rename(image_path, new_image_path)


class DICOMTagCSVController:
    """
    DICOMタグ抽出で作成されたCSVファイルを制御するクラス
    """

    def __init__(self, csv_path: str):
        """
        初期化
        Args:
            csv_path (str): DICOMタグ抽出で作成されたCSVファイルのパス
        """
        self.csv_path = csv_path
        self.df = None
        self._load_csv()

    def _load_csv(self):
        """
        CSVファイルを読み込む
        """
        try:
            if not os.path.exists(self.csv_path):
                raise FileNotFoundError(f"CSVファイルが見つかりません: {self.csv_path}")
            
            self.df = pd.read_csv(self.csv_path)
        except Exception as e:
            raise ValueError(f"CSVファイルの読み込みエラー: {e}")
        
    def get_pixel_spacing(self, case_id: Union[int, str]) -> Optional[Tuple[float, float]]:
        """
        指定された症例番号のPixel Spacingを取得("pre"がついているもので，最大の数値のもの)
        """
        try:
            # case_idを文字列または数値として検索
            if isinstance(case_id, str):
                mask = self.df['case_id'].astype(str) == str(case_id)
            else:
                mask = self.df['case_id'] == case_id

            matching_rows = self.df[mask]

            if len(matching_rows) == 0:
                raise ValueError(f"症例番号 {case_id} がDICOMタグ抽出で作成されたCSVファイルに見つかりません")
            
            # "pre"が含まれている行のみをフィルタリング
            pre_rows = matching_rows[matching_rows['case_name'].str.contains("pre", na=False)]

            if len(pre_rows) == 0:
                raise ValueError(f"症例番号 {case_id} に対して，'pre'が含まれている行が見つかりません")
            
            # 複数の"pre"が含まれている行が存在する場合，最大の数値を持つものを選択
            if len(pre_rows) > 1:
                max_pre_number = -1
                selected_row = None

                for idx, row in pre_rows.iterrows():
                    case_name = row['case_name']

                    # "pre"の後の数字を抽出
                    match = re.search(r'pre(\d+)', case_name)
                    if match:
                        pre_number = int(match.group(1))
                        if pre_number > max_pre_number:
                            max_pre_number = pre_number
                            selected_row = row
                    else:
                        # "pre"のみで数字がない場合
                        if max_pre_number == -1:
                            selected_row = row
                
                if selected_row is None:
                    raise ValueError(f"症例番号 {case_id} に対して，'pre'のみで数字がない行が見つかりました")
                
                row_data = selected_row
            else:
                # pre_rowsが1行の場合
                row_data = pre_rows.iloc[0]
            
            # pixel spacingを取得
            pixel_spacing_row = row_data['pixel_spacing_row']
            pixel_spacing_col = row_data['pixel_spacing_col']

            if pd.isna(pixel_spacing_row) or pd.isna(pixel_spacing_col):
                raise ValueError(f"症例番号 {case_id} に対して，Pixel Spacingが見つかりません")
            
            return float(pixel_spacing_row), float(pixel_spacing_col)
        
        except Exception as e:
            raise ValueError(f"Pixel Spacingの取得エラー: {e}")

if __name__ == '__main__':
    excel_path = "../../../data/CHIBAMI_case_list_2023rev20240523.xlsx"
    root_path = "../../../data/list"
    # excel_path = "../../Data/CHIBAMI_case_list.xlsx"
    # root_path = "../../Data/list"

    excel = Excel(excel_path)
    data = excel.extract_data()
    # print(data)

    # excel.rename(root_path)
    # excel.improve_name(root_path) 
    # excel.restore_name(root_path)