import json
import os
import tempfile
import shutil
from pathlib import Path
from datetime import datetime
from typing import Dict, Optional
from dataclasses import dataclass, asdict
import logging

logger = logging.getLogger(__name__)

@dataclass
class OptimizedParams:
    instrument: str
    timeframe: str
    atr_period: int = 14
    sl_atr_multiplier: float = 1.5
    risk_reward_ratio: float = 3.0
    trail_distance_atr: float = 1.0
    fitness_score: float = 0.0
    total_trades: int = 0
    win_rate: float = 0.0
    profit_factor: float = 0.0
    max_drawdown_pct: float = 0.0
    backtest_start: Optional[str] = None
    backtest_end: Optional[str] = None

    def to_dict(self) -> Dict:
        return asdict(self)

    @classmethod
    def from_dict(cls, data: Dict) -> 'OptimizedParams':
        return cls(**data)

class ParameterStore:
    def __init__(self, base_path: str = 'params'):
        self.base_path = Path(base_path)
        self.base_path.mkdir(parents=True, exist_ok=True)
        self.main_file = self.base_path / 'optimized_params.json'

    def save(self, params: OptimizedParams):
        key = f"{params.instrument}_{params.timeframe}"
        all_params = self.load_all()
        all_params[key] = params.to_dict()
        
        # Атомарная запись для защиты от corruption при параллельных процессах
        tmp_fd, tmp_path = tempfile.mkstemp(dir=self.base_path, suffix='.tmp')
        try:
            with os.fdopen(tmp_fd, 'w', encoding='utf-8') as f:
                json.dump(all_params, f, indent=2, ensure_ascii=False, default=str)
            shutil.move(tmp_path, self.main_file)
            logger.info(f"✅ Сохранено: {key} (fitness={params.fitness_score:.3f})")
        except Exception as e:
            if os.path.exists(tmp_path):
                os.remove(tmp_path)
            logger.error(f"❌ Ошибка сохранения параметров: {e}")

    def load(self, instrument: str, timeframe: str) -> Optional[OptimizedParams]:
        key = f"{instrument}_{timeframe}"
        all_params = self.load_all()
        if key in all_params:
            logger.debug(f"📥 Загружено: {key}")
            return OptimizedParams.from_dict(all_params[key])
        return None

    def load_all(self) -> Dict[str, Dict]:
        if not self.main_file.exists():
            return {}
        try:
            with open(self.main_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        except (json.JSONDecodeError, PermissionError):
            logger.warning("⚠️ Поврежденный файл параметров. Создается пустой.")
            return {}