"""
設定管理モジュール

.envファイルおよび環境変数からの設定読み込みを担当する。
すべての接続情報やIPアドレスは環境変数経由で設定し、
ソースコードへのハードコードを回避する。
"""

import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional

from dotenv import load_dotenv


@dataclass
class RithmicConfig:
    """R|Trader Proプラグインモード接続設定"""
    # R|Trader Proのプラグインモードホスト
    host: str = "127.0.0.1"
    # プラグインモードポート
    port: int = 56000
    # 認証情報
    user: str = ""
    password: str = ""
    # 対象シンボル
    symbol: str = "GCJ6"
    # 取引所
    exchange: str = "COMEX"
    # R|API+ DLLディレクトリ
    dll_dir: str = ""


@dataclass
class ZmqConfig:
    """ZeroMQ通信設定"""
    # パブリッシャーのバインドアドレス (PUB側)
    pub_addr: str = "tcp://*:5555"
    # パブリッシャーポート
    pub_port: int = 5555
    # クライアント接続先ホスト
    client_host: str = "localhost"
    # クライアント接続先ポート
    client_port: int = 5555
    # ZeroMQの高水位マーク (HWM) - バッファサイズ制御
    hwm: int = 10000
    hwm: int = 10000
    # 受信タイムアウト (ミリ秒)
    recv_timeout: int = 1000
    # コマンド受信ポート (REP側)
    rep_port: int = 5556
    # クライアントコマンド送信ポート
    req_port: int = 5556


@dataclass
class BridgeConfig:
    """ブリッジシステム全体の設定"""
    rithmic: RithmicConfig = field(default_factory=RithmicConfig)
    zmq: ZmqConfig = field(default_factory=ZmqConfig)

    @classmethod
    def from_env(cls, env_file: Optional[str] = None) -> "BridgeConfig":
        """
        環境変数または.envファイルから設定を読み込む。
        .envファイルが存在しなくてもエラーにならず、環境変数またはデフォルト値を使用する。

        Args:
            env_file: .envファイルのパス (Noneの場合はデフォルトパスを探索)

        Returns:
            BridgeConfig: 読み込まれた設定オブジェクト
        """
        # .envファイルの読み込み (存在する場合のみ)
        if env_file:
            if os.path.exists(env_file):
                load_dotenv(env_file)
        else:
            # カレントディレクトリの .env を探す (dotenvのデフォルト挙動)
            load_dotenv()

        # Rithmic設定の構築
        rithmic = RithmicConfig(
            host=os.getenv("RITHMIC_HOST", "127.0.0.1"),
            port=int(os.getenv("RITHMIC_PORT", "56000")),
            user=os.getenv("RITHMIC_USER", ""),
            password=os.getenv("RITHMIC_PASSWORD", ""),
            symbol=os.getenv("RITHMIC_SYMBOL", "GCJ6"),
            exchange=os.getenv("RITHMIC_EXCHANGE", "COMEX"),
            dll_dir=os.getenv("RAPI_DLL_DIR", ""),
        )

        # ZeroMQ設定の構築
        zmq_config = ZmqConfig(
            pub_addr=os.getenv("ZMQ_PUB_ADDR", "tcp://*:5555"),
            pub_port=int(os.getenv("ZMQ_PUB_PORT", "5555")),
            client_host=os.getenv("CLIENT_HOST", "localhost"),
            client_port=int(os.getenv("CLIENT_PORT", "5555")),
            rep_port=int(os.getenv("ZMQ_REP_PORT", "5556")),
            req_port=int(os.getenv("CLIENT_REQ_PORT", "5556")),
        )

        return cls(rithmic=rithmic, zmq=zmq_config)

    def get_pub_bind_addr(self) -> str:
        """パブリッシャーのバインドアドレスを返す"""
        return self.zmq.pub_addr

    def get_sub_connect_addr(self) -> str:
        """サブスクライバーの接続先アドレスを返す"""
        return f"tcp://{self.zmq.client_host}:{self.zmq.client_port}"

    def get_symbol_full(self) -> str:
        """完全なシンボル名を返す (例: GCJ6.COMEX)"""
        return f"{self.rithmic.symbol}.{self.rithmic.exchange}"


_config_cache: Optional[BridgeConfig] = None


def get_config(env_file: Optional[str] = None) -> BridgeConfig:
    """設定のシングルトン取得"""
    global _config_cache
    if _config_cache is None:
        _config_cache = BridgeConfig.from_env(env_file)
    return _config_cache
