
"""PKTron Chemistry — Periodic Table elements database & helpers."""
import numpy as np

# Abridged periodic table: symbol -> (Z, name, atomic_mass_amu, group, period)
ELEMENTS = {
    "H" : (1,  "Hydrogen",    1.008,  1,  1),
    "He": (2,  "Helium",      4.003,  18, 1),
    "Li": (3,  "Lithium",     6.941,  1,  2),
    "Be": (4,  "Beryllium",   9.012,  2,  2),
    "B" : (5,  "Boron",       10.81,  13, 2),
    "C" : (6,  "Carbon",      12.011, 14, 2),
    "N" : (7,  "Nitrogen",    14.007, 15, 2),
    "O" : (8,  "Oxygen",      15.999, 16, 2),
    "F" : (9,  "Fluorine",    18.998, 17, 2),
    "Ne": (10, "Neon",        20.180, 18, 2),
    "Na": (11, "Sodium",      22.990, 1,  3),
    "Mg": (12, "Magnesium",   24.305, 2,  3),
    "Al": (13, "Aluminium",   26.982, 13, 3),
    "Si": (14, "Silicon",     28.086, 14, 3),
    "P" : (15, "Phosphorus",  30.974, 15, 3),
    "S" : (16, "Sulfur",      32.065, 16, 3),
    "Cl": (17, "Chlorine",    35.453, 17, 3),
    "Ar": (18, "Argon",       39.948, 18, 3),
    "K" : (19, "Potassium",   39.098, 1,  4),
    "Ca": (20, "Calcium",     40.078, 2,  4),
    "Fe": (26, "Iron",        55.845, 8,  4),
    "Cu": (29, "Copper",      63.546, 11, 4),
    "Zn": (30, "Zinc",        65.38,  12, 4),
    "Br": (35, "Bromine",     79.904, 17, 4),
    "Kr": (36, "Krypton",     83.798, 18, 4),
    "Ag": (47, "Silver",      107.87, 11, 5),
    "I" : (53, "Iodine",      126.90, 17, 5),
    "Au": (79, "Gold",        196.97, 11, 6),
    "Hg": (80, "Mercury",     200.59, 12, 6),
    "Pb": (82, "Lead",        207.2,  14, 6),
    "U" : (92, "Uranium",     238.03, 3,  7),
}

def get_element(symbol):
    """Return element dict by symbol."""
    if symbol not in ELEMENTS:
        raise KeyError(f"Unknown element: {symbol}")
    Z, name, mass, group, period = ELEMENTS[symbol]
    return {"symbol":symbol,"Z":Z,"name":name,
            "atomic_mass":mass,"group":group,"period":period}

def atomic_mass(symbol):
    return ELEMENTS[symbol][2]

def atomic_number(symbol):
    return ELEMENTS[symbol][0]

def molar_mass(formula_dict):
    """
    Compute molar mass from formula dict e.g. {"H":2,"O":1} -> 18.015
    """
    return sum(atomic_mass(sym)*count for sym,count in formula_dict.items())

def electron_config_shells(Z):
    """Return (n_shells, electrons_per_shell) list — simplified Bohr model."""
    shells = []
    remaining = Z
    capacities = [2, 8, 8, 18, 18, 32]
    for cap in capacities:
        if remaining <= 0:
            break
        fill = min(remaining, cap)
        shells.append(fill)
        remaining -= fill
    return shells

def ionisation_energy_approx(Z):
    """Approximate 1st ionisation energy via Slater rules (eV)."""
    sigma = 0.30*(Z-1)   # crude shielding
    Zeff  = max(1, Z - sigma)
    n     = len(electron_config_shells(Z))
    return float(13.6 * Zeff**2 / n**2)
