// AiPreviewDayPlan.jsx — Forhåndsvisning «Lag dagsplan» (§4.1).
//
// Gjengir en REN KOPI av «Dagens oppgaver»-kortet fra dashbordet: samme
// kort-stil og samme rad-oppsett (avkryssingssirkel + tittel), og samme
// «Mål og prosjekter»-seksjon med referanse til målet/prosjektet oppgaven
// støtter (gjenbruker dashbordets `dash-gp-*`-klasser).
//
// Dynamikk (§4.1): AI leverer en FOKUSERT kjerneplan (2–5 oppgaver, `extra`
// = false) som vises i kortet, pluss inntil 5 TILLEGGSFORSLAG (`extra` = true)
// som ligger som «legg til ved ønske»-forslag under kortet. Brukeren kan:
//   • fjerne en oppgave fra planen med en enkel X (den flyttes ned til
//     forslagene, ingenting går tapt),
//   • legge til et forslag med «+ Legg til».
//
// Kontrollert: rapporterer { activeOps, rejected } opp via onChangeSelection.
// activeOps bygges av oppgavene som ligger i planen akkurat nå (kjerne + de
// tilleggene brukeren har lagt til). rejected = kjerneoppgaver brukeren har
// fjernet (så AI ikke foreslår dem på nytt i neste chat-runde).

// Løser hva en alias (item.ref eller item.new.link_ref) kobler til — mål
// (med milepæl+goal-navn) eller prosjekt — for visning («Mål: X», ikke «G3»).
function aiPvResolveLink(alias, aliasTitles, aliasTables, aliasParents) {
  if (!alias || !aliasTables) return null;
  const table = aliasTables[alias];
  if (table === 'goal_milestones') {
    const goalRef = aliasParents && aliasParents[alias];
    const goalName = goalRef && aliasTitles ? aliasTitles[goalRef] : null;
    const msName = aliasTitles && aliasTitles[alias];
    if (!goalName && !msName) return null;
    return { kind: 'goal', goalName, msName };
  }
  if (table === 'goal_milestone_todos') {
    // MT-alias kjeder til MS-alias (milepæl) → G-alias (mål) når begge finnes,
    // ellers rett til G-alias (milepælen ble kuttet av server-grensen).
    const parentRef = aliasParents && aliasParents[alias];
    const parentIsMs = parentRef && aliasTables[parentRef] === 'goal_milestones';
    const msName = parentIsMs ? (aliasTitles && aliasTitles[parentRef]) : null;
    const goalRef = parentIsMs ? (aliasParents && aliasParents[parentRef]) : parentRef;
    const goalName = goalRef && aliasTitles ? aliasTitles[goalRef] : null;
    if (!goalName && !msName) return null;
    return { kind: 'goal', goalName, msName };
  }
  if (table === 'projects' || table === 'project_todos') {
    const projectName = table === 'projects'
      ? (aliasTitles && aliasTitles[alias])
      : ((aliasParents && aliasTitles) ? aliasTitles[aliasParents[alias]] : null);
    if (!projectName) return null;
    return { kind: 'project', projectName };
  }
  return null;
}

// Korter av lange milepæl-/prosjektnavn med «…» på slutten (§3).
function aiPvTruncate(text, max) {
  if (!text) return text;
  return text.length > max ? `${text.slice(0, max).trimEnd()}…` : text;
}

// Etikett til «Mål og prosjekter»-referansen (samme som dashbordets
// `dash-gp-sub`, §2–3): «Mål: <navn> - <milepæl>» eller «Prosjekt: <navn>»,
// slik at det er tydelig at oppgaven kommer fra et mål/prosjekt uten å måtte
// tolke ikonet alene.
function aiPvLinkLabel(link) {
  if (!link) return null;
  if (link.kind === 'goal') {
    const goalName = link.goalName || 'Mål';
    const ms = aiPvTruncate(link.msName, 40);
    return ms ? `Mål: ${goalName} - ${ms}` : `Mål: ${goalName}`;
  }
  return `Prosjekt: ${link.projectName || 'Prosjekt'}`;
}

// Stabil nøkkel-liste fra et resultat (ref for eksisterende, new:<idx> for nye).
function aiPvDayKeys(result) {
  const sorted = Array.isArray(result?.items)
    ? result.items.slice().sort((a, b) => (a.rank || 0) - (b.rank || 0))
    : [];
  return sorted.map((it, idx) => ({ it, key: it.ref || `new:${idx}`, isNew: !!it.new }));
}
// Kjerneplanen (extra !== true) — starter inne i planen.
function aiPvDayCoreKeys(result) {
  return new Set(aiPvDayKeys(result).filter(x => !x.it.extra).map(x => x.key));
}

function AiPreviewDayPlan({ result, onChangeSelection, aliasTitles, aliasTables, aliasParents }) {
  const allItems = React.useMemo(() => aiPvDayKeys(result), [result]);
  const ops = Array.isArray(result?.ops) ? result.ops : [];

  // Hvilke oppgaver ligger i planen nå. Kjerneplan (extra !== true) starter
  // inne; tilleggsforslag (extra === true) starter ute.
  const [inPlan, setInPlan] = React.useState(() => aiPvDayCoreKeys(result));
  const firstRun = React.useRef(true);
  React.useEffect(() => {
    // Behold seed-en fra initialiseringen på første render; nullstill kun når
    // et NYTT resultat kommer inn (ny chat-runde).
    if (firstRun.current) { firstRun.current = false; return; }
    setInPlan(aiPvDayCoreKeys(result));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [result]);

  // Meld opp aktive ops + rejected hver gang planen endres.
  React.useEffect(() => {
    const planItems = allItems.filter(x => inPlan.has(x.key));
    const planRefs = new Set(planItems.filter(x => x.it.ref).map(x => x.it.ref));

    // create_task-ops følger rekkefølgen på de nye oppgavene i items-lista.
    const newInPlan = [];
    allItems.forEach(x => { if (x.isNew) newInPlan.push(inPlan.has(x.key)); });

    let createPtr = -1;
    const kept = ops.filter(op => {
      if (op.op === 'create_task') { createPtr++; return !!newInPlan[createPtr]; }
      if (!op.ref) return false;
      return planRefs.has(op.ref);
    });

    // Enhver eksisterende oppgave i planen skal faktisk få forfall i dag, ellers
    // dukker den ikke opp på «Dagens oppgaver»-kortet selv om brukeren nettopp
    // godkjente den inn i dagsplanen.
    const today = new Date().toISOString().slice(0, 10);
    const hasDueOp = new Set(kept.filter(o => o.op === 'reschedule').map(o => o.ref));
    const activeOps = kept.slice();
    planItems.forEach(x => {
      const ref = x.it.ref;
      if (!ref || hasDueOp.has(ref)) return;
      activeOps.push({ id: `auto-due-${ref}`, op: 'reschedule', ref, value: today });
    });

    // Fjernede kjerneoppgaver rapporteres som rejected (ikke foreslå igjen).
    // Tilleggsforslag som bare ikke er lagt til, avvises ikke.
    const rejected = allItems.filter(x => !x.it.extra && !inPlan.has(x.key)).map(x => x.key);

    onChangeSelection && onChangeSelection({ activeOps, rejected });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [inPlan, result]);

  function removeFromPlan(key) {
    setInPlan(prev => { const n = new Set(prev); n.delete(key); return n; });
  }
  function addToPlan(key) {
    setInPlan(prev => { const n = new Set(prev); n.add(key); return n; });
  }

  // Utled visnings-metadata for én oppgave (tittel, mål/prosjekt-referanse, slot).
  function decorate(x) {
    const item = x.it;
    const title = item.new
      ? item.new.title
      : ((aliasTitles && aliasTitles[item.ref]) || item.title || item.ref);
    const linkRef = item.new ? item.new.link_ref : item.ref;
    const link = linkRef ? aiPvResolveLink(linkRef, aliasTitles, aliasTables, aliasParents) : null;
    return { item, title: title || 'Oppgave', link, isNew: !!item.new, slot: item.slot };
  }

  const planItems = allItems.filter(x => inPlan.has(x.key)).map(x => ({ ...x, ...decorate(x) }));
  const trayItems = allItems.filter(x => !inPlan.has(x.key)).map(x => ({ ...x, ...decorate(x) }));

  // Skille «rene» oppgaver fra mål-/prosjektoppgaver — akkurat som dashbordet.
  const plain = planItems.filter(x => !x.link);
  const gp = planItems.filter(x => x.link);

  function slotStart(slot) {
    return slot && slot.start ? String(slot.start) : null;
  }

  function Row({ x }) {
    const start = slotStart(x.slot);
    return (
      <div className={`dash-panel-row ai-pv-tc-row${x.link ? ' dash-gp-row' : ''}`}>
        <span className="dash-panel-check" aria-hidden="true"></span>
        {x.link ? (
          <div className="dash-gp-main">
            <span className="dash-panel-text">
              {x.title}
              {x.isNew && <span className="ai-pv-tc-new">Ny</span>}
            </span>
            <span className="dash-gp-sub">
              <i className={`ti ${x.link.kind === 'goal' ? 'ti-target-arrow' : 'ti-layout-grid'}`}></i>
              {aiPvLinkLabel(x.link)}
            </span>
          </div>
        ) : (
          <span className="dash-panel-text" style={{ flex: 1 }}>
            {x.title}
            {x.isNew && <span className="ai-pv-tc-new">Ny</span>}
          </span>
        )}
        {start && <span className="dash-gp-time">{start}</span>}
        <button className="ai-pv-tc-x" onClick={() => removeFromPlan(x.key)}
          title="Fjern fra planen" aria-label="Fjern fra planen">
          <i className="ti ti-x"></i>
        </button>
      </div>
    );
  }

  return (
    <div className="ai-pv ai-pv-day">
      {/* Ren kopi av «Dagens oppgaver»-kortet */}
      <div className="ai-pv-todaycard">
        <div className="ai-pv-todaycard-head">
          <span className="ai-pv-todaycard-title">Dagens oppgaver</span>
          <span className="ai-pv-todaycard-badge">{planItems.length}</span>
        </div>
        <div className="ai-pv-todaycard-body">
          {planItems.length === 0 ? (
            <p className="ai-pv-todaycard-empty">Ingen oppgaver i planen – legg til fra forslagene.</p>
          ) : (
            <>
              {plain.map(x => <Row key={x.key} x={x} />)}
              {gp.length > 0 && (
                <>
                  <div className="dash-gp-divider" />
                  <div className="dash-gp-head"><i className="ti ti-target-arrow"></i>Mål og prosjekter</div>
                  {gp.map(x => <Row key={x.key} x={x} />)}
                </>
              )}
            </>
          )}
        </div>
      </div>

      {/* Tilleggsforslag — legg til ved ønske */}
      {trayItems.length > 0 && (
        <div className="ai-pv-extras">
          <div className="ai-pv-extras-head">
            <i className="ti ti-sparkles"></i>Flere forslag – legg til ved ønske
          </div>
          <div className="ai-pv-extras-list">
            {trayItems.map(x => (
              <button key={x.key} className="ai-pv-extra" onClick={() => addToPlan(x.key)}
                title="Legg til i planen">
                <i className="ti ti-plus ai-pv-extra-ic"></i>
                <span className="ai-pv-extra-main">
                  <span className="ai-pv-extra-t">
                    {x.title}
                    {x.isNew && <span className="ai-pv-tc-new">Ny</span>}
                  </span>
                  {(x.link || x.item.reason) && (
                    <span className="ai-pv-extra-sub">
                      {x.link ? aiPvLinkLabel(x.link) : x.item.reason}
                    </span>
                  )}
                </span>
                <span className="ai-pv-extra-add">Legg til</span>
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

window.AiPreviewDayPlan = AiPreviewDayPlan;
