import { w as writable, d as derived, r as readable, g as get } from "./index4.js";
import { s as server } from "./grain-types.js";
import { t as tick } from "./index-server.js";
import { ppmt } from "financial";
function productionAnnuelle(productible, puissance, degradation, i) {
  return productible * puissance * Math.pow(1 - degradation / 100, i);
}
class Derived {
  p;
  s;
  modified;
  constructor(s) {
    this.s = s;
    this.modified = writable(false);
    this.p = Object.fromEntries(
      Object.entries(s).map(([k, v]) => {
        const w = writable(v);
        w.subscribe((value) => {
          this.s[k] = value;
          this.modified.set(true);
        });
        return [k, w];
      })
    );
    this.N = writable(30);
    this.investissement = derived(
      [this.p.puissance, this.p.ratio, this.p.enedis],
      ([$puissance, $ratio, $enedis]) => $puissance ? $puissance * 1e3 * $ratio + $enedis : 0
    );
    this.apport = derived(
      [this.investissement, this.p.apport],
      ([$investissement, $apport]) => Math.min($investissement, $apport)
    );
    this.primeInvestissement = derived(
      this.p.puissance,
      ($puissance) => ($puissance <= 3 ? 0.3 : $puissance <= 9 ? 0.23 : $puissance <= 36 ? 0.2 : $puissance <= 100 ? 0.1 : 0) * 1e3 * $puissance
    );
    function tarifSurplus_(tarifCRE, puissance) {
      let resultat = tarifCRE.prix[0];
      for (let i = 0; i < tarifCRE.limites.length; i++) {
        if (puissance < tarifCRE.limites[i]) {
          return resultat;
        } else {
          resultat = tarifCRE.prix[i];
        }
      }
      return resultat;
    }
    this.tarifSurplus = derived(
      [this.p.tarif_cre, this.p.puissance, this.N],
      ([$tarifCRE, $puissance, $N], _, update) => {
        update((tarifSurplus) => {
          if (!tarifSurplus || tarifSurplus.length < $N) {
            tarifSurplus = Array($N);
          }
          const t = tarifSurplus_($tarifCRE, $puissance);
          for (let i = 0; i < $N; i++) {
            tarifSurplus[i] = t * Math.pow(1 + $tarifCRE.inflation / 100, i);
          }
          return tarifSurplus;
        });
      }
    );
    this.productionAnnuelle = derived(
      [this.p.productible, this.p.puissance, this.p.degradation, this.N],
      ([$productible, $puissance, $degradation, $N], _, update) => {
        update((prod) => {
          if (!prod || prod.length < $N) {
            prod = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            prod[i] = productionAnnuelle(
              $productible,
              $puissance,
              $degradation,
              i
            );
          }
          return prod;
        });
      }
    );
    this.tarifLocal = derived(
      [this.p.prix, this.p.inflation, this.N],
      ([$prix, $inflation, $N], _, update) => {
        update((tarif) => {
          console.log("TARIF", $N);
          if (!tarif || tarif.length < $N) {
            tarif = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            tarif[i] = $prix * Math.pow(1 + $inflation / 100, i);
          }
          return tarif;
        });
      }
    );
    this.tarifAllo = derived(
      [this.p.cout_elec, this.p.inflation_elec, this.N],
      ([$coutElec, $inflationElec, $N], _, update) => {
        update((tarif) => {
          if (!tarif || tarif.length < $N) {
            tarif = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            tarif[i] = $coutElec * Math.pow(1 + $inflationElec / 100, i);
          }
          return tarif;
        });
      }
    );
    this.chiffreAffaires = derived(
      [
        this.primeInvestissement,
        this.productionAnnuelle,
        this.p.autoconso,
        this.tarifLocal,
        this.tarifSurplus,
        this.p.autoprod,
        this.tarifAllo,
        this.N
      ],
      ([
        $primeInvestissement,
        $productionAnnuelle,
        $autoconso,
        $tarifLocal,
        $tarifSurplus,
        $autoprod,
        $tarifAllo,
        $N
      ], _, update) => {
        update((ca) => {
          if (!ca || ca.length < $N) {
            ca = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            ca[i] = (i == 0 ? $primeInvestissement : 0) + $productionAnnuelle[i] * ($autoconso / 100 * $tarifLocal[i] + (1 - $autoconso / 100) * $tarifSurplus[i] + $autoprod / 100 * $tarifAllo[i]);
          }
          return ca;
        });
      }
    );
    this.turpe = derived(
      [
        this.p.puissance,
        this.p.turpe,
        this.p.autoconso,
        this.productionAnnuelle,
        this.p.turpe_injection,
        this.p.inflation,
        this.N
      ],
      ([
        $puissance,
        $turpe,
        $autoconso,
        $productionAnnuelle,
        $turpeInjection,
        $inflation,
        $N
      ], _, update) => {
        update((turpe) => {
          if (!turpe || turpe.length < $N) {
            turpe = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            turpe[i] = ($puissance * $turpe + (1 - $autoconso / 100) * $productionAnnuelle[i] * $turpeInjection) * Math.pow(1 + $inflation / 100, i);
          }
          return turpe;
        });
      }
    );
    this.assurance = derived(
      [this.investissement, this.p.assurance, this.p.inflation, this.N],
      ([$investissement, $assurance, $inflation, $N], _, update) => {
        update((assurance) => {
          if (!assurance || assurance.length < $N) {
            assurance = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            assurance[i] = $investissement * $assurance / 100 * Math.pow(1 + $inflation / 100, i);
          }
          return assurance;
        });
      }
    );
    this.exploitation = derived(
      [this.p.puissance, this.p.maintenance, this.p.inflation, this.N],
      ([$puissance, $maintenance, $inflation, $N], _, update) => {
        update((expl) => {
          if (!expl || expl.length < $N) {
            expl = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            expl[i] = $puissance * $maintenance * Math.pow(1 + $inflation / 100, i);
          }
          return expl;
        });
      }
    );
    this.divers = derived(
      [this.p.divers, this.p.puissance, this.p.inflation, this.N],
      ([$divers, $puissance, $inflation, $N], _, update) => {
        update((divers) => {
          if (!divers || divers.length < $N) {
            divers = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            divers[i] = $divers * $puissance * Math.pow(1 + $inflation / 100, i);
          }
          return divers;
        });
      }
    );
    this.charges = derived(
      [
        this.investissement,
        this.p.frais_divers,
        this.exploitation,
        this.turpe,
        this.assurance,
        this.divers,
        this.N
      ],
      ([
        $investissement,
        $fraisDivers,
        $exploitation,
        $turpe,
        $assurance,
        $divers,
        $N
      ], _, update) => {
        update((charges) => {
          if (!charges || charges.length < $N) {
            charges = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            charges[i] = ($investissement && i == 0 ? $fraisDivers : 0) + $exploitation[i] + $turpe[i] + $assurance[i] + $divers[i];
          }
          return charges;
        });
      }
    );
    this.valeurAjoutee = derived(
      [this.chiffreAffaires, this.charges, this.N],
      ([$chiffreAffaires, $charges, $N], _, update) => {
        update((va) => {
          if (!va || va.length < $N) {
            va = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            va[i] = $chiffreAffaires[i] - $charges[i];
          }
          return va;
        });
      }
    );
    this.amortissement = derived(
      [this.p.duree_amortissement, this.investissement, this.N],
      ([$dureeAmortissement, $investissement, $N], _, update) => {
        update((a) => {
          if (!a || a.length < $N) {
            a = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            if (i < $dureeAmortissement) {
              a[i] = $investissement / $dureeAmortissement;
            } else {
              a[i] = 0;
            }
          }
          return a;
        });
      }
    );
    this.provisionOnduleurs = derived(
      [
        this.p.puissance,
        this.p.provision_onduleurs,
        this.p.inflation,
        this.N
      ],
      ([$puissance, $provision, $inflation, $N], _, update) => {
        update((a) => {
          if (!a || a.length < $N) {
            a = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            a[i] = $puissance * 1e3 * $provision * Math.pow(1 + $inflation / 100, i) / 10;
          }
          return a;
        });
      }
    );
    this.accise = derived(
      [this.productionAnnuelle, this.N],
      ([$productionAnnuelle, $N], _, update) => {
        update((a) => {
          if (!a || a.length < $N) {
            a = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            a[i] = $productionAnnuelle[i] * 1e-3;
          }
          return a;
        });
      }
    );
    this.taxeFonciere = readable(0);
    this.cfe = readable(0);
    this.ifer = derived(
      [this.p.puissance, this.p.ratio_dc_ac, this.N],
      ([$puissance, $ratio, $N], _, update) => {
        update((a) => {
          if (!a || a.length < $N) {
            a = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            a[i] = $puissance < 100 ? 0 : 3.394 * $puissance * $ratio;
          }
          return a;
        });
      }
    );
    this.impots = derived(
      [this.ifer, this.taxeFonciere, this.cfe, this.N],
      ([$ifer, $taxeFonciere, $cfe, $N], _, update) => {
        update((a) => {
          if (!a || a.length < $N) {
            a = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            a[i] = $ifer[i] + $taxeFonciere + $cfe;
          }
          return a;
        });
      }
    );
    this.ebe = derived(
      [this.valeurAjoutee, this.impots, this.N],
      ([$va, $impots, $N], _, update) => {
        update((a) => {
          if (!a || a.length < $N) {
            a = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            a[i] = $va[i] - $impots[i];
          }
          return a;
        });
      }
    );
    this.dette = derived(
      [this.investissement, this.p.apport],
      ([$inv, $app]) => Math.max(0, $inv - $app)
    );
    this.dette.subscribe(this.banque.dette.set);
    this.p.echeances.subscribe(this.banque.duree.set);
    this.p.interet.subscribe(
      ($interet) => this.banque.taux.set($interet / 100)
    );
    this.interetsDetteSenior = derived(
      [this.banque.resultat, this.N],
      ([$banque, $N], _, update) => {
        update((ids) => {
          if (!ids || ids.length < $N) {
            ids = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            ids[i] = i < $banque.interetsAnnuels.length ? $banque.interetsAnnuels[i] : 0;
          }
          return ids;
        });
      }
    );
    this.interetsDSRA = derived(
      [this.interetsDetteSenior, this.p.taux_dsra, this.N],
      ([$ids, $taux, $N], _, update) => {
        update((a) => {
          if (!a || a.length < $N) {
            a = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            a[i] = $ids[i] * $taux / 100;
          }
          return a;
        });
      }
    );
    this.resultatFiscal = derived(
      [
        this.ebe,
        this.amortissement,
        this.provisionOnduleurs,
        this.interetsDetteSenior,
        this.interetsDSRA,
        this.N
      ],
      ([$ebe, $amortissement, $provision, $ids, $dsra, $N], _, update) => {
        update((rf) => {
          if (!rf || rf.length < $N) {
            rf = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            rf[i] = $ebe[i] - $amortissement[i] - $provision[i] - $ids[i] - $dsra[i];
          }
          return rf;
        });
      }
    );
    this.is = derived(
      [this.resultatFiscal, this.p.taux_is, this.N],
      ([$r, $taux, $N], _, update) => {
        update((is) => {
          if (!is || is.length < $N) {
            is = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            is[i] = $r[i] <= 0 ? 0 : $r[i] * $taux / 100;
          }
          return is;
        });
      }
    );
    this.resultatNet = derived(
      [this.resultatFiscal, this.is, this.N],
      ([$r, $is, $N], _, update) => {
        update((r) => {
          if (!r || r.length < $N) {
            r = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            r[i] = $r[i] - $is[i];
          }
          return r;
        });
      }
    );
    this.tresorerieDisponibleDetteSenior = derived(
      [this.ebe, this.is, this.N],
      ([$ebe, $is, $N], _, update) => {
        update((r) => {
          if (!r || r.length < $N) {
            r = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            r[i] = $ebe[i] - $is[i];
          }
          return r;
        });
      }
    );
    this.serviceDetteSenior = derived(
      [
        this.interetsDSRA,
        this.interetsDetteSenior,
        this.banque.resultat,
        this.N
      ],
      ([$dsra, $ids, $b, $N], _, update) => {
        update((r) => {
          if (!r || r.length < $N) {
            r = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            r[i] = $dsra[i] + $ids[i] + $b.remboursementAnnuel[i];
          }
          return r;
        });
      }
    );
    this.dscr = derived(
      [
        this.banque.resultat,
        this.tresorerieDisponibleDetteSenior,
        this.serviceDetteSenior,
        this.N
      ],
      ([$b, $treso, $service, $N], _, update) => {
        update((r) => {
          if (!r || r.length < $N) {
            r = Array($N);
          }
          for (let i = 0; i < $N; i++) {
            if (i < $b.remboursementAnnuel.length) {
              r[i] = $treso[i] / $service[i];
            } else {
              r[i] = 0;
            }
          }
          return r;
        });
      }
    );
  }
  investissement;
  apport;
  primeInvestissement;
  N;
  tarifSurplus;
  productionAnnuelle;
  tarifLocal;
  tarifAllo;
  chiffreAffaires;
  turpe;
  assurance;
  exploitation;
  divers;
  charges;
  valeurAjoutee;
  accise;
  taxeFonciere;
  cfe;
  ifer;
  impots;
  ebe;
  amortissement;
  resultatFiscal;
  provisionOnduleurs;
  interetsDetteSenior;
  interetsDSRA;
  is;
  dette;
  resultatNet;
  dscr;
  tresorerieDisponibleDetteSenior;
  serviceDetteSenior;
  banque = new Banque();
}
class Banque {
  // V3
  dette = writable(0);
  // V4
  taux = writable(0);
  // Z8
  duree = writable(0);
  // Z7
  dureeDifferee = writable(1);
  // V8
  nombrePeriodesParAn = writable(12);
  prorataPeriodique = derived(this.nombrePeriodesParAn, (n) => 1 / n);
  // V6
  dureeAns = derived(
    [this.duree, this.nombrePeriodesParAn],
    ([$a, $b]) => $a / $b
  );
  dureeAns_ = derived(this.dureeAns, Math.ceil);
  taux_ = derived(this.taux, (t) => Math.min(t, 1));
  // V10
  nombreEcheancesPeriodeTronquee = derived(
    [this.dureeAns, this.nombrePeriodesParAn],
    ([a, b]) => a * b
  );
  // V9
  nombreEcheances = derived(this.nombreEcheancesPeriodeTronquee, Math.ceil);
  // W11
  totalPeriodes = derived(
    [this.dureeAns, this.nombrePeriodesParAn, this.dureeDifferee],
    ([$a, $b, $c]) => $a * $b - $c
  );
  // X11
  periodeRemboursementCapital = this.dureeDifferee;
  resultat = derived(
    [
      this.duree,
      this.dureeAns_,
      this.dette,
      this.periodeRemboursementCapital,
      this.nombreEcheancesPeriodeTronquee,
      this.taux_,
      this.prorataPeriodique,
      this.periodeRemboursementCapital,
      this.totalPeriodes,
      this.nombreEcheances,
      this.nombrePeriodesParAn
    ],
    ([
      $duree,
      $dureeAns_,
      $dette,
      $periode,
      $nombreEcheancesPeriodeTronquee,
      $taux_,
      $prorataPeriodique,
      $periodeRemboursementCapital,
      $totalPeriodes,
      $nombreEcheances,
      $nombrePeriodesParAn
    ], _, update) => {
      update((resultat) => {
        if (resultat.remboursement.length != $duree + 1) {
          resultat.remboursement = new Array(Math.ceil($duree) + 1);
          resultat.crd = new Array(Math.ceil($duree) + 1);
          resultat.interets = new Array(Math.ceil($duree) + 1);
          resultat.remboursementAnnuel = new Array($dureeAns_);
          resultat.crdAnnuel = new Array($dureeAns_);
          resultat.interetsAnnuels = new Array($dureeAns_);
        }
        resultat.crd[0] = $dette;
        resultat.remboursement[0] = 0;
        resultat.interets[0] = 0;
        resultat.crdAnnuel[0] = $dette;
        resultat.remboursementAnnuel[0] = 0;
        resultat.interetsAnnuels[0] = 0;
        for (let i = 1; i <= $duree; i++) {
          if (i <= $periode) {
            resultat.remboursement[i] = 0;
          } else if (i < $nombreEcheancesPeriodeTronquee) {
            resultat.remboursement[i] = ppmt(
              $taux_ * $prorataPeriodique,
              i - $periodeRemboursementCapital,
              $totalPeriodes,
              -$dette
            );
          } else if (i == $nombreEcheances) {
            resultat.remboursement[i] = resultat.crd[i - 1];
          } else {
            resultat.remboursement[i] = 0;
          }
          resultat.crd[i] = resultat.crd[i - 1] - resultat.remboursement[i];
          resultat.interets[i] = resultat.crd[i - 1] * $taux_ * $prorataPeriodique;
          if (i % $nombrePeriodesParAn == 0) {
            resultat.crdAnnuel[i / $nombrePeriodesParAn] = resultat.crd[i];
            resultat.remboursementAnnuel[i / $nombrePeriodesParAn] = 0;
            resultat.interetsAnnuels[i / $nombrePeriodesParAn] = 0;
          }
          resultat.remboursementAnnuel[Math.floor(i / $nombrePeriodesParAn)] += resultat.remboursement[i];
          resultat.interetsAnnuels[Math.floor(i / $nombrePeriodesParAn)] += resultat.interets[i];
        }
        return resultat;
      });
    },
    {
      remboursement: new Array(0),
      remboursementAnnuel: new Array(0),
      crd: new Array(0),
      crdAnnuel: new Array(0),
      interets: new Array(0),
      interetsAnnuels: new Array(0)
    }
  );
}
async function updatePv(puissance, communaute, pvgis, soleil_) {
  if (communaute?.isMoving) {
    return;
  }
  console.log("updatePv", puissance);
  let azimuth = 0;
  let p_total = 0;
  let inclinaison = 0;
  const lat = Math.round(communaute?.lat || 45.56747);
  const lng = Math.round(communaute?.lng || 5.92285);
  console.log("com", communaute);
  if (communaute?.compteurs) {
    for (const c of communaute.compteurs) {
      azimuth += c.azimuth * c.puissance;
      inclinaison += c.inclinaison * c.puissance;
      p_total += c.puissance;
    }
    if (p_total <= puissance) {
      inclinaison += lat * (puissance - p_total);
    } else {
      azimuth *= puissance / p_total;
      inclinaison *= puissance / p_total;
    }
    if (puissance > 0) {
      azimuth /= puissance;
      inclinaison /= puissance;
    } else {
      azimuth = 0;
      inclinaison = lat;
    }
    azimuth = Math.round(azimuth);
    inclinaison = Math.round(inclinaison);
  }
  const d = /* @__PURE__ */ new Date();
  const min_t = new Date(d.getFullYear(), 0, 1).getTime() / 1e3;
  const max_t = min_t + 364 * 24 * 3600;
  const pvgis_ = get(pvgis);
  if (!pvgis_.pvgis || pvgis_.pvgis.inputs.location.latitude != lat || pvgis_.pvgis.inputs.location.longitude != lng || pvgis_.pvgis.inputs.mounting_system.fixed.slope["value"] != inclinaison || pvgis_.pvgis.inputs.mounting_system.fixed.azimuth["value"] != azimuth) {
    console.log("Updating PVGIS", lat, lng, inclinaison, azimuth);
    pvgis_.loading = true;
    pvgis.set(pvgis_);
    await tick();
    console.log(inclinaison, azimuth, p_total);
    const annuelle = await fetch(
      `${server}/pvgis?lat=${lat}&lng=${lng}&azimuth=${azimuth}&inclinaison=${inclinaison}`,
      {}
    );
    try {
      pvgis_.pvgis = await annuelle.json();
    } catch (e) {
      console.log(e);
    }
    pvgis_.loading = false;
    pvgis.set(pvgis_);
  }
  console.log(pvgis);
  const soleil = get(soleil_);
  soleil.hourly = { x: [], y: [] };
  soleil.daily = { x: [], y: [] };
  soleil.weekly = { x: [], y: [] };
  const start = new Date(min_t * 1e3);
  const janvier = new Date(start.getFullYear(), 0, 1);
  console.log("UP", max_t, !!pvgis_.pvgis);
  for (let t = min_t; t < max_t; t += 3600) {
    const tt = new Date(t * 1e3);
    let pp = 0;
    if (pvgis_.pvgis) {
      const len = pvgis_.pvgis.outputs.hourly.length;
      const n = (t * 1e3 - janvier.getTime()) / 36e5 % len;
      const pvvar = "P";
      pp = pvgis_.pvgis.outputs.hourly[Math.floor(n)][pvvar] * puissance / 1e3;
      soleil.hourly.x.push(tt);
      soleil.hourly.y.push(pp);
      if ((t - min_t) % (24 * 3600) == 0) {
        if ((t - min_t) % (24 * 7 * 3600) == 0) {
          soleil.weekly.x.push(tt);
          soleil.weekly.y.push(pp);
        } else {
          soleil.weekly.y[soleil.weekly.y.length - 1] += pp;
        }
        soleil.daily.x.push(tt);
        soleil.daily.y.push(pp);
      } else {
        soleil.daily.y[soleil.daily.y.length - 1] += pp;
        soleil.weekly.y[soleil.weekly.y.length - 1] += pp;
      }
    }
  }
  soleil_.set(soleil);
}
export {
  Derived as D,
  productionAnnuelle as p,
  updatePv as u
};
