import math
import numpy as np

H = 20.0  # horizon jaar; scenario LCA-S1, geen gemeten stationinventaris
# (naam, hoeveelheid, eenheid, kg CO2-eq per eenheid, levensduur jaar)
# De eerste groep zijn expliciete aanvullende screeningaannamen.
vast = [
    ("stationschil: hout",1200,"kg",.26,30),
    ("stationschil: staal",300,"kg",2.5,30),
    ("stationschil: beton",2000,"kg",.12,30),
    ("stationschil: isolatie",150,"kg",3.,30),
    ("modulegebouw",1,"pakket",650.,30),
    ("module rek/water/pomp",1,"pakket",110.,15),
    ("PV module",1.4,"kWp",600.,25),
    ("PV extra station",4.2,"kWp",600.,25),
    ("modulebatterij",2*12.8*120/1000,"kWh",100.,8),
    ("modulelampen",2,"stuk",50.,8),
    ("module-elektronica",1,"pakket",60.,10),
    ("windinstallatie",1,"pakket",650.,20),
    ("warmtepomp/installaties",1,"pakket",800.,15),
    ("waterstofketen",1,"pakket",1000.,10),
    ("extra centrale elektronica",1,"pakket",150.,10),
]

def positief(x,naam,nul=True):
    if isinstance(x,bool) or not math.isfinite(x) or x<0 or (not nul and x==0):
        raise ValueError(naam)
    return float(x)

def lca(B_kWh,import_kWh_jaar=200.,netfactor=.15,
        batterij_factor=100.,station_batterij_leven=10.,pv_factor=600.):
    # B is de nog te kiezen 48 V-stationcapaciteit. B=10 is alleen S1.
    for naam,x in [("B",B_kWh),("import",import_kWh_jaar),
                   ("netfactor",netfactor),("batterijfactor",batterij_factor),
                   ("PV-factor",pv_factor)]: positief(x,naam)
    positief(station_batterij_leven,"batterijleven",False)
    rijen=[]
    for naam,q,u,f,leven in vast:
        if naam.startswith("PV "): f=pv_factor
        if naam=="modulebatterij": f=batterij_factor
        aantal=math.ceil(H/leven) # eerste pakket plus vervanging vóór einde horizon
        rijen.append((naam,q,u,f,leven,aantal,q*f*aantal))
    n=math.ceil(H/station_batterij_leven)
    rijen.append(("48 V-stationbatterij (scenario)",B_kWh,"kWh",
                  batterij_factor,station_batterij_leven,n,B_kWh*batterij_factor*n))
    productie=sum(r[-1] for r in rijen)
    overige={"transport":300.,"eindprocessen":500.,
             "verbruiksgoederen":H*30., # module 10 + station 20 kg CO2-eq/jaar
             "netimport":H*import_kWh_jaar*netfactor,
             "overige gebruiksemissies":H*15.} # open screeningpost, geen koudemiddelkeuze
    totaal=productie+sum(overige.values())
    return totaal,rijen,overige

TOTAAL,RIJEN,OVERIG=lca(10.)
print("LCA-S1: H=20 jaar, B=10 kWh (uitsluitend scenario)")
for naam,q,u,f,leven,n,c in RIJEN:
    print(f"{naam:31} {n} pakket(ten), {c:.1f} kg CO2-eq")
print("overige posten",OVERIG)
print("totaal",round(TOTAAL,1),"kg CO2-eq; per stationsjaar",round(TOTAAL/H,2))
print("B=0/10/30 (geen haalbaarheidstoets)",
      [round(lca(b)[0]/H,2) for b in [0,10,30]])
print("batterijleven 8/10/12 jaar",
      [round(lca(10.,station_batterij_leven=l)[0]/H,2) for l in [8,10,12]])
print("netfactor 0.05/0.15/0.40",
      [round(lca(10.,netfactor=g)[0]/H,2) for g in [.05,.15,.4]])
print("PV-factor 420/600/780",
      [round(lca(10.,pv_factor=g)[0]/H,2) for g in [420,600,780]])
print("CO2 + fossiel CH4 + N2O",100+2*29.8+.1*273,"kg CO2-eq")
# Verschil tussen eindige projectgrens en jaarlijkse vervangingsallocatie.
print("modulebatterij: project per jaar",3.072*100*3/H,
      "tegen langetermijnallocatie",3.072*100/8)
# Afzonderlijke tegenfeitelijke paneelvergelijking; GEEN krediet in stationtotaal.
energy=carbon=0.; te=tc=None; CE=[(0.,0.)]; CC=[(0.,0.)]
for jaar in range(1,26):
    bruikbaar=350.*.70*.995**(jaar-1) # kWh/jaar van één 350 Wp-paneel
    dE=bruikbaar*2. # kWh primaire energie per kWh vervangen netstroom (aanname)
    dC=bruikbaar*.20*.97**(jaar-1) # kg CO2-eq; dalende vermeden factor (aanname)
    if te is None and energy+dE>=1200: te=jaar-1+(1200-energy)/dE
    if tc is None and carbon+dC>=250: tc=jaar-1+(250-carbon)/dC
    energy+=dE; carbon+=dC
    CE.append((float(jaar),energy)); CC.append((float(jaar),carbon))
print("paneel: energiepayback",round(te,6),"jaar; koolstofpayback",round(tc,6))
print("paneel: 25 jaar vermeden",round(energy,2),"kWh primair en",round(carbon,2),"kg CO2-eq")
assert abs(TOTAAL-(lca(0.)[0]+2000.))<1e-8
assert math.ceil(H/10)==2 and math.ceil(H/8)==3
for slecht in [float("nan"),float("inf"),-1.]:
    try: lca(slecht)
    except ValueError: pass
    else: raise AssertionError("parameter niet afgewezen")
