# -*- coding: utf-8 -*-
from __future__ import annotations
from typing import Any
from .backends import BackendNotAvailableError, normalize_backend, to_builtin

def _element_from_input(atom: str|int|Any):
    from pymatgen.core import Element
    if isinstance(atom, int): return Element.from_Z(atom)
    s=str(atom).strip(); return Element.from_Z(int(s)) if s.isdigit() else Element(s)

def get_atom_inf(atom: str|int|Any, *, backend: str='pymatgen') -> dict[str, Any]:
    b=normalize_backend(backend); b='pymatgen' if b=='auto' else b
    if b!='pymatgen': raise BackendNotAvailableError(f'backend not implemented: {backend!r}')
    el=_element_from_input(atom)
    ret={'backend':'pymatgen','symbol':el.symbol,'Z':int(el.Z),'name':el.name}
    for key in ['atomic_mass','atomic_radius','atomic_radius_calculated','average_ionic_radius','mendeleev_no','row','group','X']:
        try:
            v=getattr(el,key)
            if v is not None: ret[key]=int(v) if key in {'mendeleev_no','row','group'} else float(v)
        except Exception: pass
    for key in ['is_metal','is_transition_metal','is_alkali','is_alkaline','is_halogen','is_chalcogen','is_lanthanoid','is_actinoid','is_noble_gas','is_metalloid','is_post_transition_metal']:
        try: ret[key]=bool(getattr(el,key))
        except Exception: pass
    for key in ['oxidation_states','common_oxidation_states','icsd_oxidation_states','full_electronic_structure']:
        try: ret[key]=to_builtin(getattr(el,key))
        except Exception: pass
    try: ret['electronic_structure']=str(el.electronic_structure)
    except Exception: pass
    return ret

def get_composition_inf_from_formula(formula: str, *, backend: str='pymatgen') -> dict[str, Any]:
    b=normalize_backend(backend); b='pymatgen' if b=='auto' else b
    if b!='pymatgen': raise BackendNotAvailableError(f'backend not implemented: {backend!r}')
    from pymatgen.core import Composition
    c=Composition(str(formula)); elems=[]
    for el,amt in c.items():
        d={'symbol':getattr(el,'symbol',str(el)),'amount':float(amt)}
        try: d['Z']=int(el.Z)
        except Exception: pass
        elems.append(d)
    ret={'backend':'pymatgen','input_formula':str(formula),'formula':c.formula,
         'alphabetical_formula':c.alphabetical_formula,'reduced_formula':c.reduced_formula,
         'num_atoms':float(c.num_atoms),'elements':elems,'as_dict':{str(k):float(v) for k,v in c.as_dict().items()}}
    for name in ['chemical_system','anonymized_formula']:
        try: ret[name]=getattr(c,name)
        except Exception: pass
    try: ret['oxidation_state_guesses']=to_builtin(c.oxi_state_guesses())
    except Exception as exc: ret['oxidation_state_guess_error']=f'{type(exc).__name__}: {exc}'
    return ret
