# config_handler.py
#
import configparser
import os
from typing import Any, Dict, Optional

import configparser
import os
import re
from typing import Any, Dict, Optional

class ConfigHandler:
    """変数置換機能付きの設定ファイル管理クラス"""
    
    def __init__(self, ini_file_path: str, variables: Dict[str, str] = None):
        """
        Args:
            ini_file_path (str): INIファイルのパス
            variables (Dict[str, str], optional): 置換用の変数辞書
        """
        self.ini_file_path = ini_file_path
        self.variables = variables or {}
        self.config = configparser.ConfigParser()
        self.load_config()
    
    def _substitute_variables(self, text: str) -> str:
        """
        テキスト内の変数を置換する

        Args:
            text (str): 置換対象のテキスト

        Returns:
            str: 置換後のテキスト
        """
        # ${var}形式の変数を置換
        pattern1 = r'\${([^}]+)}'
        # [var]形式の変数を置換
        pattern2 = r'\[([^\]]+)\]'
        
        def replace_var(match):
            var_name = match.group(1)
            return self.variables.get(var_name, match.group(0))
        
        # 両方のパターンで置換を実行
        text = re.sub(pattern1, replace_var, text)
        text = re.sub(pattern2, replace_var, text)
        
        return text
    
    def load_config(self) -> None:
        """設定ファイルを読み込み、変数を置換する"""
        if not os.path.exists(self.ini_file_path):
            raise FileNotFoundError(f"設定ファイルが見つかりません: {self.ini_file_path}")
        
        # まず生のテキストとして読み込む
        with open(self.ini_file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 変数を置換
        substituted_content = self._substitute_variables(content)
        
        # 置換済みの内容を StringIO 経由で configparser に読み込ませる
        from io import StringIO
        self.config.read_file(StringIO(substituted_content))
    
    def get_value(self, section: str, key: str, default: Any = None) -> Optional[str]:
        """
        指定されたセクションのキーの値を取得する
        
        Args:
            section (str): セクション名
            key (str): キー名
            default (Any): デフォルト値（オプション）
            
        Returns:
            Optional[str]: 設定値。存在しない場合はデフォルト値
        """
        try:
            return self.config[section][key]
        except KeyError:
            return default
    
    def get_section(self, section: str) -> Dict[str, str]:
        """
        指定されたセクションの全ての設定を取得する
        
        Args:
            section (str): セクション名
            
        Returns:
            Dict[str, str]: セクションの設定をディクショナリで返す
        """
        try:
            return dict(self.config[section])
        except KeyError:
            return {}
    
    def get_all_sections(self) -> Dict[str, Dict[str, str]]:
        """
        全てのセクションの設定を取得する
        
        Returns:
            Dict[str, Dict[str, str]]: 全セクションの設定をネストされたディクショナリで返す
        """
        return {section: dict(self.config[section]) for section in self.config.sections()}





# 使用例
if __name__ == "__main__":
    # サンプルのINIファイル作成
    sample_ini = """
[Database]
host = localhost
port = 5432
database = mydb
user = admin
password = secret

[Application]
debug = true
log_level = INFO
max_connections = 100

[Paths]
data_dir = /var/data
log_file = /var/log/app.log
"""
    
    # サンプルINIファイルを作成
    with open('config.ini', 'w', encoding='utf-8') as f:
        f.write(sample_ini)
    
    # 設定を読み込んで使用
    config = ConfigHandler('config.ini')
    
    # 特定の値を取得
    db_host = config.get_value('Database', 'host')
    db_port = config.get_value('Database', 'port')
    print(f"Database connection: {db_host}:{db_port}")
    
    # セクション全体を取得
    db_config = config.get_section('Database')
    print("Database configuration:", db_config)
    
    # 全ての設定を取得
    all_config = config.get_all_sections()
    print("All configurations:", all_config)


# サンプル：
# # 設定ファイルから値を取得
# config = ConfigHandler('config.ini')
# 
# # データベース設定を取得
# db_host = config.get_value('Database', 'host')
# db_port = config.get_value('Database', 'port')
# db_name = config.get_value('Database', 'database')
# 
# # アプリケーション設定を取得
# debug_mode = config.get_value('Application', 'debug')
# log_level = config.get_value('Application', 'log_level')
# 
