// okonomi-fase1.jsx — Datalag for regnskap, periode og prognose
// Lastes etter okonomi.jsx. Eksporterer til window.

// ══════════════════════════════════════════════════════════════
// REGNSKAP
// ══════════════════════════════════════════════════════════════

async function okHentRegnskap(ar, avdelingId = null) {
  const q = window._sb.from('ok_regnskap')
    .select('*, avdeling:enheter!avdeling_id(id,navn,avd_nr), selskap:selskaper!selskap_id(id,navn), prosjekt:prosjekter!prosjekt_id(id,navn)')
    .eq('ar', ar)
    .order('periode').order('konto');
  if (avdelingId) q.eq('avdeling_id', avdelingId);
  const { data, error } = await q;
  if (error) throw error;
  return data || [];
}

async function okImporterRegnskap(linjer, ar, kilde = 'csv') {
  // linjer = [{ selskap_id, avdeling_id, konto, periode, belop, bilag_ref }]
  const sb = window._sb;
  const { data: { user } } = await sb.auth.getUser();

  // Slett eksisterende for samme ar+kilde (re-import)
  // Kun perioder som er representert i importen
  const perioder = [...new Set(linjer.map(l => l.periode))];
  await sb.from('ok_regnskap')
    .delete()
    .eq('ar', ar)
    .eq('kilde', kilde)
    .in('periode', perioder);

  // Insert i bolker à 200
  const BOLK = 200;
  let antall = 0;
  for (let i = 0; i < linjer.length; i += BOLK) {
    const { error } = await sb.from('ok_regnskap').insert(
      linjer.slice(i, i + BOLK).map(l => ({
        selskap_id:  l.selskap_id  || null,
        avdeling_id: l.avdeling_id || null,
        prosjekt_id: l.prosjekt_id || null,
        konto:       l.konto,
        periode:     l.periode,
        ar,
        belop:       l.belop,
        bilag_ref:   l.bilag_ref  || null,
        bilag_url:   l.bilag_url  || null,
        bilag_dato:  l.bilag_dato || null,
        kilde,
        importert_av: user?.id,
        importert_at: new Date().toISOString(),
      }))
    );
    if (error) throw error;
    antall += Math.min(BOLK, linjer.length - i);
  }
  return { antall, perioder };
}

async function okSlettRegnskap(ar, kilde, perioder = null) {
  const q = window._sb.from('ok_regnskap').delete().eq('ar', ar).eq('kilde', kilde);
  if (perioder?.length) q.in('periode', perioder);
  const { error } = await q;
  if (error) throw error;
}

// CSV-parser: konto, avd_nr, periode(YYYYMM), belop, bilag_ref
async function okParseRegnskapCsv(csvTekst, selskaper, enheter) {
  const linjer = csvTekst.trim().split('\n');
  const header = linjer[0].toLowerCase().split(',').map(s => s.trim());

  const kolidx = k => header.indexOf(k);
  const iKonto    = kolidx('konto');
  const iAvdNr    = kolidx('avd_nr');
  const iPeriode  = kolidx('periode');
  const iBeløp    = kolidx('belop') >= 0 ? kolidx('belop') : kolidx('beløp');
  const iBilag    = kolidx('bilag_ref');
  const iSelskap  = kolidx('selskap_id');

  if ([iKonto, iPeriode, iBeløp].some(i => i < 0))
    throw new Error('CSV mangler påkrevde kolonner: konto, periode, belop');

  const enhetByAvdNr = Object.fromEntries(enheter.map(e => [e.avd_nr, e.id]));
  const feil = [];
  const rader = [];

  linjer.slice(1).forEach((linje, idx) => {
    if (!linje.trim()) return;
    const c = linje.split(',').map(s => s.trim().replace(/^"|"$/g, ''));
    const konto   = parseInt(c[iKonto]);
    const periode = parseInt(c[iPeriode]);
    const belop   = parseFloat(c[iBeløp]?.replace(/\s/g,''));
    const avdNr   = iAvdNr >= 0 ? c[iAvdNr] : null;
    const avdId   = avdNr ? enhetByAvdNr[avdNr] : null;
    const selId   = iSelskap >= 0 ? c[iSelskap] : selskaper[0]?.id;

    if (isNaN(konto) || isNaN(periode) || isNaN(belop)) {
      feil.push({ rad: idx + 2, melding: `Ugyldig tall: konto=${c[iKonto]}, periode=${c[iPeriode]}, belop=${c[iBeløp]}` });
      return;
    }
    if (String(periode).length !== 6) {
      feil.push({ rad: idx + 2, melding: `Periode må være YYYYMM, fikk: ${periode}` });
      return;
    }

    rader.push({
      selskap_id:  selId   || null,
      avdeling_id: avdId   || null,
      konto,
      periode,
      ar:          Math.floor(periode / 100),
      belop,
      bilag_ref:   iBilag >= 0 ? c[iBilag] : null,
    });
  });

  return { rader, feil };
}

// ══════════════════════════════════════════════════════════════
// PERIODE-KONTROLL
// ══════════════════════════════════════════════════════════════

async function okHentPeriodeStatus(ar, selskapId = null) {
  const q = window._sb.from('ok_periode_status')
    .select('*')
    .eq('ar', ar)
    .order('periode');
  if (selskapId) q.eq('selskap_id', selskapId);
  const { data, error } = await q;
  if (error) throw error;
  return data || [];
}

async function okSettPeriodeStatus(selskapId, ar, periode, status, merknad = null) {
  const { data: { user } } = await window._sb.auth.getUser();
  const { error } = await window._sb.from('ok_periode_status').upsert({
    selskap_id: selskapId,
    ar, periode, status, merknad,
    lukket_av: status === 'lukket' ? user?.id : null,
    lukket_at: status === 'lukket' ? new Date().toISOString() : null,
  }, { onConflict: 'selskap_id,ar,periode' });
  if (error) throw error;
}

// ══════════════════════════════════════════════════════════════
// PROGNOSE
// ══════════════════════════════════════════════════════════════

async function okHentPrognoser(ar) {
  const { data, error } = await window._sb.from('ok_prognose_versjon')
    .select('*, versjon:bud_versjoner!bud_versjon_id(id,navn,ar,status)')
    .eq('ar', ar)
    .order('created_at');
  if (error) throw error;
  return data || [];
}

async function okOpprettPrognose(budVersjonId, ar, navn = 'Prognose') {
  const { data: { user } } = await window._sb.auth.getUser();
  const { data, error } = await window._sb.from('ok_prognose_versjon')
    .upsert({ bud_versjon_id: budVersjonId, ar, navn, opprettet_av: user?.id },
             { onConflict: 'bud_versjon_id' })
    .select().single();
  if (error) throw error;
  return data;
}

async function okHentPrognoseLinje(prognoseVersjonId, avdelingId = null) {
  const q = window._sb.from('ok_prognose_linje')
    .select('*')
    .eq('prognose_versjon_id', prognoseVersjonId)
    .order('periode').order('konto');
  if (avdelingId) q.eq('avdeling_id', avdelingId);
  const { data, error } = await q;
  if (error) throw error;
  return data || [];
}

async function okLagrePrognoseLinje(prognoseVersjonId, avdelingId, konto, periode, felt) {
  // felt = { belop_override?, belop_justering?, kommentar?, kilde? }
  const { data: { user } } = await window._sb.auth.getUser();
  const { data, error } = await window._sb.from('ok_prognose_linje')
    .upsert({
      prognose_versjon_id: prognoseVersjonId,
      avdeling_id: avdelingId,
      konto, periode,
      ...felt,
      endret_av: user?.id,
      endret_at: new Date().toISOString(),
    }, { onConflict: 'prognose_versjon_id,avdeling_id,konto,periode' })
    .select().single();
  if (error) throw error;
  return data;
}

async function okSlettPrognoseLinje(id) {
  const { error } = await window._sb.from('ok_prognose_linje').delete().eq('id', id);
  if (error) throw error;
}

async function okRegistrerFlytt(prognoseVersjonId, {
  konto, fraAvdelingId, tilAvdelingId, fraPeriode, tilPeriode, belop, begrunnelse
}) {
  const { data: { user } } = await window._sb.auth.getUser();
  const sb = window._sb;

  // 1. Registrer flytten
  const { data: flytt, error: fErr } = await sb.from('ok_prognose_flytt').insert({
    prognose_versjon_id: prognoseVersjonId,
    konto, fra_avdeling_id: fraAvdelingId, til_avdeling_id: tilAvdelingId,
    fra_periode: fraPeriode, til_periode: tilPeriode, belop, begrunnelse,
    opprettet_av: user?.id,
  }).select().single();
  if (fErr) throw fErr;

  // 2. Oppdater prognose-linjer for fra og til
  const oppdater = async (avdId, periode, delta) => {
    const { data: eks } = await sb.from('ok_prognose_linje')
      .select('id, belop_justering')
      .eq('prognose_versjon_id', prognoseVersjonId)
      .eq('avdeling_id', avdId).eq('konto', konto).eq('periode', periode)
      .maybeSingle();
    const nyJustering = (Number(eks?.belop_justering || 0)) + delta;
    await okLagrePrognoseLinje(prognoseVersjonId, avdId, konto, periode, {
      belop_justering: nyJustering, kilde: 'flytt',
    });
  };

  await oppdater(fraAvdelingId, fraPeriode, -belop);
  await oppdater(tilAvdelingId, tilPeriode,  belop);

  return flytt;
}

// Hent beregnede prognose-tall via PostgreSQL-funksjon
async function okBeregnPrognose(prognoseVersjonId, avdelingId = null) {
  const { data, error } = await window._sb.rpc('ok_prognose_beregn', {
    p_prognose_versjon_id: prognoseVersjonId,
    p_avdeling_id:         avdelingId,
  });
  if (error) throw error;
  return data || [];
}

// Rapport-funksjon
async function okBeregnRapport(ar, budVersjonId, tomPeriode = null, avdelingId = null) {
  const { data, error } = await window._sb.rpc('ok_beregn_periode', {
    p_ar:             ar,
    p_bud_versjon_id: budVersjonId,
    p_tom_periode:    tomPeriode,
    p_avdeling_id:    avdelingId,
  });
  if (error) throw error;
  return data || [];
}

// ══════════════════════════════════════════════════════════════
// EKSPORT
// ══════════════════════════════════════════════════════════════

Object.assign(window, {
  okHentRegnskap,
  okImporterRegnskap,
  okSlettRegnskap,
  okParseRegnskapCsv,
  okHentPeriodeStatus,
  okSettPeriodeStatus,
  okHentPrognoser,
  okOpprettPrognose,
  okHentPrognoseLinje,
  okLagrePrognoseLinje,
  okSlettPrognoseLinje,
  okRegistrerFlytt,
  okBeregnPrognose,
  okBeregnRapport,
});
