"""
Mineral database loader for CIS parameters
"""

import json
import os
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
from pathlib import Path


@dataclass
class MineralEntry:
    """CIS parameters for a single mineral"""
    name: str
    formula: str
    crystal_system: str
    space_group: Optional[str]
    K0: float
    K0_std: float
    Kprime: float
    Kprime_std: float
    V0: float
    V0_std: float
    alpha: float
    alpha_std: Optional[float]
    gamma: float
    gamma_std: Optional[float]
    quality: str  # ★ rating
    references: List[str]


class MineralDatabase:
    """
    Load and query mineral CIS parameters
    
    Data from Stixrude & Lithgow-Bertelloni (2011) and
    3,200 experimental P-V-T points
    """
    
    def __init__(self, db_path: Optional[str] = None):
        """
        Initialize mineral database
        
        Parameters
        ----------
        db_path : str, optional
            Path to JSON database file
            If None, uses default location
        """
        if db_path is None:
            # Try multiple possible locations
            possible_paths = [
                "data/cis_database.json",
                "../data/cis_database.json",
                "/data/cis_database.json",
                os.path.join(os.path.dirname(__file__), "../../data/cis_database.json")
            ]
            
            for path in possible_paths:
                if os.path.exists(path):
                    db_path = path
                    break
            
            if db_path is None:
                # Create in-memory database with key minerals
                self.minerals = self._create_default_database()
                return
        
        # Load from file
        with open(db_path, 'r') as f:
            data = json.load(f)
        
        self.minerals = {}
        for mineral_data in data:
            mineral = MineralEntry(**mineral_data)
            self.minerals[mineral.name.lower()] = mineral
    
    def _create_default_database(self) -> Dict[str, MineralEntry]:
        """Create in-memory database with key minerals"""
        minerals = {}
        
        # Bridgmanite
        minerals['bridgmanite'] = MineralEntry(
            name='bridgmanite',
            formula='MgSiO3',
            crystal_system='orthorhombic',
            space_group='Pbnm',
            K0=260.7,
            K0_std=3.8,
            Kprime=3.97,
            Kprime_std=0.11,
            V0=24.45,
            V0_std=0.05,
            alpha=2.0e-5,
            alpha_std=0.2e-5,
            gamma=1.57,
            gamma_std=0.08,
            quality='★★★★★',
            references=['Stixrude & Lithgow-Bertelloni (2011)',
                       'Murakami et al. (2012)']
        )
        
        # Forsterite
        minerals['forsterite'] = MineralEntry(
            name='forsterite',
            formula='Mg2SiO4',
            crystal_system='orthorhombic',
            space_group='Pbnm',
            K0=128.4,
            K0_std=1.8,
            Kprime=4.31,
            Kprime_std=0.08,
            V0=43.79,
            V0_std=0.10,
            alpha=2.85e-5,
            alpha_std=0.15e-5,
            gamma=1.21,
            gamma_std=0.05,
            quality='★★★★★',
            references=['Stixrude & Lithgow-Bertelloni (2011)']
        )
        
        # Periclase
        minerals['periclase'] = MineralEntry(
            name='periclase',
            formula='MgO',
            crystal_system='cubic',
            space_group='Fm-3m',
            K0=160.3,
            K0_std=0.8,
            Kprime=3.99,
            Kprime_std=0.03,
            V0=11.25,
            V0_std=0.02,
            alpha=3.12e-5,
            alpha_std=0.10e-5,
            gamma=1.524,
            gamma_std=0.01,
            quality='★★★★★',
            references=['Stixrude & Lithgow-Bertelloni (2011)',
                       'Tange et al. (2009)']
        )
        
        # Add more minerals as needed
        
        return minerals
    
    def get_mineral(self, name: str) -> Optional[MineralEntry]:
        """Get mineral by name (case insensitive)"""
        return self.minerals.get(name.lower())
    
    def list_minerals(self) -> List[str]:
        """List all available minerals"""
        return list(self.minerals.keys())
    
    def search_by_system(self, crystal_system: str) -> List[MineralEntry]:
        """Search minerals by crystal system"""
        results = []
        for mineral in self.minerals.values():
            if mineral.crystal_system.lower() == crystal_system.lower():
                results.append(mineral)
        return results
    
    def get_kprime_prior(self, crystal_system: str) -> Tuple[float, float]:
        """
        Get K' prior from crystal symmetry (H4 hypothesis)
        
        Returns
        -------
        Tuple[float, float]
            (mean, standard deviation)
        """
        priors = {
            "cubic": (4.01, 0.24),
            "tetragonal": (4.18, 0.31),
            "hexagonal": (4.29, 0.38),
            "trigonal": (4.29, 0.38),
            "orthorhombic": (4.44, 0.41),
            "monoclinic": (4.67, 0.52),
            "triclinic": (4.91, 0.61)
        }
        
        return priors.get(crystal_system.lower(), (4.5, 0.5))
    
    def summary(self) -> Dict:
        """Return database summary"""
        return {
            "total_minerals": len(self.minerals),
            "cubic": len(self.search_by_system("cubic")),
            "tetragonal": len(self.search_by_system("tetragonal")),
            "hexagonal": len(self.search_by_system("hexagonal")),
            "orthorhombic": len(self.search_by_system("orthorhombic")),
            "monoclinic": len(self.search_by_system("monoclinic")),
            "triclinic": len(self.search_by_system("triclinic")),
            "minerals": self.list_minerals()
        }
