"""환경 변수 로드 및 애플리케이션 설정."""

from __future__ import annotations

import os
from dataclasses import dataclass
from pathlib import Path

from dotenv import load_dotenv

from deepcoin.data.intervals import DEFAULT_DOWNLOAD_INTERVALS

_PROJECT_ROOT = Path(__file__).resolve().parents[2]


def _resolve_project_path(raw: str) -> Path:
    """프로젝트 루트 기준 상대 경로를 절대 경로로 변환한다."""
    path = Path(raw)
    if not path.is_absolute():
        path = _PROJECT_ROOT / path
    return path


def _parse_int_list(raw: str) -> list[int]:
    """쉼표 구분 정수 목록을 파싱한다.

    Args:
        raw: 예) "3,5,10,15"

    Returns:
        정수 리스트. 빈 입력이면 빈 리스트.
    """
    if not raw or not raw.strip():
        return []
    return [int(part.strip()) for part in raw.split(",") if part.strip()]


@dataclass(frozen=True)
class Settings:
    """DeepCoin 실행 설정."""

    symbol: str
    coin_name: str
    api_url: str
    candle_count: int
    download_intervals: list[int]
    download_days: int
    db_path: Path
    request_sleep_sec: float
    request_retries: int
    # Ground Truth (1단계)
    gt_interval_min: int
    gt_lookback_days: int
    gt_zigzag_reversal_pct: float
    gt_min_leg_pct: float
    gt_pullback_min_pct: float
    gt_pullback_local_order: int
    gt_breakout_buffer_pct: float
    gt_breakout_consolidation_bars: int
    gt_breakout_min_rally_pct: float
    gt_div_local_order: int
    gt_div_min_bars_between: int
    gt_div_min_rsi_diff: float
    gt_div_min_future_move_pct: float
    ground_truth_file: Path
    ground_truth_v1_file: Path
    ground_truth_v2_file: Path
    ground_truth_chart_v1_file: Path
    ground_truth_chart_v2_file: Path
    ground_truth_chart_v3_file: Path
    gt_initial_cash_krw: float
    gt_trading_fee_rate: float
    # Techniques (2단계)
    techniques_dir: Path
    analysis_report_json: Path
    analysis_report_html: Path
    gt_align_tolerance_bars: int

    @property
    def market(self) -> str:
        """빗썸 마켓 코드 (예: KRW-BTC)."""
        return f"KRW-{self.symbol}"


def load_settings(env_path: Path | None = None) -> Settings:
    """`.env`를 로드하고 Settings를 반환한다.

    Args:
        env_path: `.env` 경로. None이면 프로젝트 루트.

    Returns:
        Settings 인스턴스.
    """
    path = env_path or (_PROJECT_ROOT / ".env")
    load_dotenv(path, override=False)

    default_intervals = ",".join(str(i) for i in DEFAULT_DOWNLOAD_INTERVALS)
    intervals_raw = os.getenv("DOWNLOAD_INTERVALS", default_intervals)
    intervals = sorted(set(_parse_int_list(intervals_raw)))

    db_raw = os.getenv("DB_PATH", "coins.db")
    db_path = Path(db_raw)
    if not db_path.is_absolute():
        db_path = _PROJECT_ROOT / db_path

    gt_file = _resolve_project_path(
        os.getenv("GROUND_TRUTH_FILE", "data/ground_truth/ground_truth_trades_v3.json")
    )
    gt_v1_file = _resolve_project_path(
        os.getenv("GROUND_TRUTH_V1_FILE", "data/ground_truth/ground_truth_trades_v1.json")
    )
    gt_v2_file = _resolve_project_path(
        os.getenv("GROUND_TRUTH_V2_FILE", "data/ground_truth/ground_truth_trades_v2.json")
    )
    gt_chart_v1 = _resolve_project_path(
        os.getenv("GROUND_TRUTH_CHART_V1_FILE", "docs/02_ground_truth/ground_truth_chart_v1.html")
    )
    gt_chart_v2 = _resolve_project_path(
        os.getenv("GROUND_TRUTH_CHART_V2_FILE", "docs/02_ground_truth/ground_truth_chart_v2.html")
    )
    gt_chart_v3 = _resolve_project_path(
        os.getenv("GROUND_TRUTH_CHART_V3_FILE", "docs/02_ground_truth/ground_truth_chart_v3.html")
    )

    tech_dir_raw = os.getenv("TECHNIQUES_DIR", "data/techniques")
    tech_dir = Path(tech_dir_raw)
    if not tech_dir.is_absolute():
        tech_dir = _PROJECT_ROOT / tech_dir

    analysis_json_raw = os.getenv("ANALYSIS_REPORT_JSON", "docs/03_analysis/comparison_report.json")
    analysis_html_raw = os.getenv("ANALYSIS_REPORT_HTML", "docs/03_analysis/comparison_report.html")
    analysis_json = Path(analysis_json_raw)
    analysis_html = Path(analysis_html_raw)
    if not analysis_json.is_absolute():
        analysis_json = _PROJECT_ROOT / analysis_json
    if not analysis_html.is_absolute():
        analysis_html = _PROJECT_ROOT / analysis_html

    return Settings(
        symbol=os.getenv("SYMBOL", "BTC").upper(),
        coin_name=os.getenv("COIN_NAME", "비트코인"),
        api_url=os.getenv("BITHUMB_API_URL", "https://api.bithumb.com").rstrip("/"),
        candle_count=int(os.getenv("BITHUMB_API_CANDLE_COUNT", "200")),
        download_intervals=intervals,
        download_days=int(os.getenv("DOWNLOAD_DAYS", "730")),
        db_path=db_path,
        request_sleep_sec=float(os.getenv("API_REQUEST_SLEEP_SEC", "0.35")),
        request_retries=int(os.getenv("API_REQUEST_RETRIES", "3")),
        gt_interval_min=int(os.getenv("GT_INTERVAL_MIN", "240")),
        gt_lookback_days=int(os.getenv("GT_LOOKBACK_DAYS", "730")),
        gt_zigzag_reversal_pct=float(os.getenv("GT_ZIGZAG_REVERSAL_PCT", "5.0")),
        gt_min_leg_pct=float(os.getenv("GT_MIN_LEG_PCT", "3.0")),
        gt_pullback_min_pct=float(os.getenv("GT_PULLBACK_MIN_PCT", "1.5")),
        gt_pullback_local_order=int(os.getenv("GT_PULLBACK_LOCAL_ORDER", "10")),
        gt_breakout_buffer_pct=float(os.getenv("GT_BREAKOUT_BUFFER_PCT", "0.1")),
        gt_breakout_consolidation_bars=int(os.getenv("GT_BREAKOUT_CONSOLIDATION_BARS", "200")),
        gt_breakout_min_rally_pct=float(os.getenv("GT_BREAKOUT_MIN_RALLY_PCT", "2.0")),
        gt_div_local_order=int(os.getenv("GT_DIV_LOCAL_ORDER", "20")),
        gt_div_min_bars_between=int(os.getenv("GT_DIV_MIN_BARS_BETWEEN", "1500")),
        gt_div_min_rsi_diff=float(os.getenv("GT_DIV_MIN_RSI_DIFF", "5.0")),
        gt_div_min_future_move_pct=float(os.getenv("GT_DIV_MIN_FUTURE_MOVE_PCT", "4.0")),
        ground_truth_file=gt_file,
        ground_truth_v1_file=gt_v1_file,
        ground_truth_v2_file=gt_v2_file,
        ground_truth_chart_v1_file=gt_chart_v1,
        ground_truth_chart_v2_file=gt_chart_v2,
        ground_truth_chart_v3_file=gt_chart_v3,
        gt_initial_cash_krw=float(os.getenv("GT_INITIAL_CASH_KRW", "400000")),
        gt_trading_fee_rate=float(os.getenv("GT_TRADING_FEE_RATE", "0.0005")),
        techniques_dir=tech_dir,
        analysis_report_json=analysis_json,
        analysis_report_html=analysis_html,
        gt_align_tolerance_bars=int(os.getenv("GT_ALIGN_TOLERANCE_BARS", "480")),
    )
