// Demo-scherm: een bedrijfsboeking die via Recras binnenkomt, NAGEBOOTST.
//
// ================== LEES DIT EERST ==================
// Er is GEEN koppeling met Recras. Niet in dit scherm, niet in de database, nergens in UPgolf.
// Gemeten op 12 augustus 2026 op de stagingdatabase: nul tabellen en nul kolommen met "recras" in de
// naam, en drie edge functions (stuur-bevestiging, mollie-betaling, mollie-webhook) waarvan er geen
// enkele Recras aanraakt. Bron: klanten/up-events/kennis/UPGOLF-ONDERZOEK-RECRAS-KOPPELING-20260812.md.
//
// Wat dit scherm WEL doet: het verzint zelf een bedrijfsboeking en zet daarmee starttijden dicht,
// zodat te zien is wat er straks gebeurt als een echte koppeling dat automatisch doet.
// Wat dit scherm NIET doet: iets ophalen, ergens verbinding mee maken of iets terugsturen.
//
// Die twee zinnen staan ook op het scherm zelf, in een balk die niet weg te klikken is. Iemand die
// dit voor het eerst ziet mag geen seconde denken dat er een koppeling draait.
// ====================================================
//
// WAT ER ECHT GEBEURT, technisch, per klik:
//   1. De starttijden van de gekozen dag, sport en tijdvak worden opgehaald uit `tijdsloten`.
//   2. Per starttijd wordt `zet_slotstatus(id, 'geblokkeerd', <opmerking met merkteken>)` aangeroepen.
//      Dat is dezelfde databasefunctie die de knop "Blok" op de tee sheet gebruikt. Er is dus geen
//      nieuwe of aparte weg naar de gegevens.
//   3. `zet_slotstatus` WEIGERT een starttijd met spelers erin: "Slot heeft nog % speler(s);
//      verplaats of annuleer die eerst". Gemeten in de functiebron zelf. Dat is goed gedrag, want
//      anders zou een gast een starttijd houden die officieel dicht staat.
//      Daarom loopt dit scherm ALLE starttijden af en stopt het niet bij de eerste weigering: het
//      meldt per starttijd of het gelukt is en zo niet, waarom niet. De balie moet kunnen zien:
//      deze zes staan dicht, deze twee niet, en dit is de reden.
//   4. Vrijgeven roept dezelfde functie aan met status `open` en zonder opmerking, alleen op de
//      starttijden die het merkteken van DEZE nagebootste boeking dragen.

const SIM_TEKENS = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; // zonder I, O, 0 en 1: die worden verwisseld
function simNieuweCode(){
  let s = ""; const r = crypto.getRandomValues(new Uint8Array(4));
  for(let i=0;i<4;i++) s += SIM_TEKENS[r[i] % SIM_TEKENS.length];
  return "SIM-" + s;
}

// De balk die zegt dat dit nagebootst is. Staat boven het scherm en boven de uitslag, en is niet
// weg te klikken. Bewust geen rood: rood betekent op deze schermen "er is iets mis", en hier is
// niets mis, er is alleen iets niet echt.
function NabootsBalk({ kort }){
  return (
    <div className="nagebootst-balk" role="note">
      <span className="nagebootst-merk">Nagebootst</span>
      <div>
        <strong>Dit is een nabootsing, geen koppeling met Recras.</strong>
        {!kort && <span> Deze knop verzint zelf een bedrijfsboeking en zet daarmee starttijden dicht.
          Er wordt niets opgehaald bij Recras en er gaat niets naar Recras toe. UPgolf heeft vandaag
          geen Recras-koppeling. Zo laat dit scherm zien wat een echte koppeling straks zou doen.</span>}
      </div>
    </div>
  );
}

function RecrasSimulatie({ baan, toon }){
  const [datum,setDatum]     = useState("2026-09-09");
  const [bedrijf,setBedrijf] = useState("Van der Meer Installaties");
  const [sport,setSport]     = useState("footgolf");
  const [van,setVan]         = useState("15:00");
  const [tot,setTot]         = useState("17:00");
  const [personen,setPersonen]=useState(60);

  const [sloten,setSloten]   = useState([]);       // starttijden van die dag en sport
  const [lopend,setLopend]   = useState([]);       // nagebootste boekingen die nu sloten dichthouden
  const [bezig,setBezig]     = useState(false);
  const [f,setF]             = useState(null);
  const [uitslag,setUitslag] = useState(null);

  // Alles ophalen wat dit scherm toont: de starttijden van de gekozen dag en sport, plus alle
  // starttijden die op dit moment een nagebootste blokkade dragen. Dat tweede staat er los van de
  // gekozen datum: een blokkade die op een andere dag is blijven staan moet je kunnen zien.
  const laad = useCallback(async()=>{
    if(!baan) return;
    setF(null);
    const [dag, blok] = await Promise.all([
      db.from("tijdsloten").select("id,datum,starttijd,sport,status,opmerking,max_spelers")
        .eq("baan_id",baan).eq("datum",datum).eq("sport",sport).order("starttijd"),
      db.from("tijdsloten").select("id,datum,starttijd,sport,status,opmerking")
        .eq("baan_id",baan).like("opmerking", SIM_MERK+"%").order("datum").order("starttijd"),
    ]);
    if(dag.error){ setF(fout(dag.error)); return; }
    setSloten(dag.data||[]);
    // Groeperen op de SIM-code in de opmerking. Dat is de enige koppeling die er is.
    const groepen = {};
    (blok.data||[]).forEach(s=>{
      const c = simCode(s.opmerking) || "zonder code";
      if(!groepen[c]) groepen[c] = { code:c, opmerking:s.opmerking, datum:s.datum, sloten:[] };
      groepen[c].sloten.push(s);
      if(s.datum < groepen[c].datum) groepen[c].datum = s.datum;
    });
    setLopend(Object.keys(groepen).sort().map(k=>groepen[k]));
  },[baan,datum,sport]);
  useEffect(()=>{ laad(); },[laad]);

  const inVenster = sloten.filter(s => String(s.starttijd).slice(0,5) >= van && String(s.starttijd).slice(0,5) <= tot);
  const teBlokkeren = inVenster.filter(s => s.status === "open");
  const alDicht     = inVenster.filter(s => s.status !== "open");

  async function binnenhalen(){
    if(!bedrijf.trim()){ setF("Vul een bedrijfsnaam in."); return; }
    if(teBlokkeren.length === 0){ setF("Geen open starttijden in dit tijdvak."); return; }
    setBezig(true); setF(null); setUitslag(null);
    const code = simNieuweCode();
    const opmerking = SIM_MERK+" · "+code+" · "+bedrijf.trim()+" · "+personen+" pers.";
    const regels = [];
    // Bewust een voor een en bewust doorlopen na een weigering. Een `Promise.all` zou de eerste fout
    // laten winnen en de rest verzwijgen, en dan weet de balie niet welke starttijden wel dicht zijn.
    for(const s of teBlokkeren){
      const r = await db.rpc("zet_slotstatus",{ p_tijdslot_id:s.id, p_status:"geblokkeerd", p_opmerking:opmerking });
      regels.push({
        tijd: String(s.starttijd).slice(0,5),
        gelukt: !r.error,
        // De melding van de database zelf, niet een eigen samenvatting ervan.
        reden: r.error ? (r.error.message || String(r.error)) : null,
      });
    }
    setBezig(false);
    const gelukt = regels.filter(r=>r.gelukt).length;
    setUitslag({
      soort:"blokkade", code, bedrijf:bedrijf.trim(), personen, datum, sport, van, tot,
      regels, gelukt, mislukt: regels.length-gelukt,
    });
    toon && toon(gelukt+" starttijd"+(gelukt===1?"":"en")+" dicht (nagebootst)");
    laad();
  }

  async function vrijgeven(groep){
    setBezig(true); setF(null); setUitslag(null);
    const regels = [];
    for(const s of groep.sloten){
      const r = await db.rpc("zet_slotstatus",{ p_tijdslot_id:s.id, p_status:"open", p_opmerking:null });
      regels.push({ tijd:String(s.starttijd).slice(0,5), datum:s.datum, gelukt: !r.error,
        reden: r.error ? (r.error.message || String(r.error)) : null });
    }
    setBezig(false);
    const gelukt = regels.filter(r=>r.gelukt).length;
    setUitslag({ soort:"vrijgave", code:groep.code, regels, gelukt, mislukt: regels.length-gelukt });
    toon && toon(gelukt+" starttijd"+(gelukt===1?"":"en")+" weer vrij");
    laad();
  }

  if(!baan) return <div className="leeg">Kies eerst een baan.</div>;

  return (
    // `paneel` is oorspronkelijk het uitschuifblad van een dialoog en draagt daarom een maximale
    // hoogte met een eigen schuifbalk. Op een gewoon scherm levert dat een venster in een venster op,
    // en dan valt de uitslag onder de vouw zonder dat je het ziet. `demoscherm` haalt die twee regels
    // eraf, alleen hier.
    <div className="paneel demoscherm">
      <NabootsBalk/>

      {/* Het uitlegpaneel. Dit staat met opzet OP het scherm en niet in een los document: wie voor
          het scherm staat moet kunnen aanwijzen wat hij vertelt. De drie zinnen hieronder zijn
          precies de drie dingen die verteld worden, en ze zijn inhoudelijk gelijk aan
          klanten/up-events/DEMO-UITLEG-RECRAS-KOPPELING-20260812.html, zodat het scherm en dat
          document elkaar niet tegenspreken. */}
      <div className="kaart uitlegkaart">
        <div className="kop">Zo werkt het, in drie stappen</div>
        <ol className="uitleg-stappen">
          <li><strong>Footgolf boeken gaat via dit systeem.</strong> Op de footgolfpagina van UP komt
            een link naar dit reserveringssysteem. Wie met een paar man komt footgolfen kiest hier
            zijn starttijd, net als bij golf.</li>
          <li><strong>Boekt een bedrijf via Recras, dan kunnen wij Recras koppelen.</strong> Een
            bedrijf dat een offerte wil, met eten en drinken en een factuur erbij, blijft in Recras.
            Daar is Recras goed in en dit systeem heeft daar niets voor.</li>
          <li><strong>Die koppeling zet die tijden hier automatisch dicht.</strong> Zo kan dezelfde
            starttijd nooit twee keer verkocht worden. Wordt de boeking in Recras geannuleerd, dan
            gaan die tijden hier weer open.</li>
        </ol>
        <p className="bij">Bij UP draait dit al: Kitchen Robot is aan Recras gekoppeld en daar gaat het
          zelfs beide kanten op. Voor footgolf is maar een richting nodig, en dat is de kleinste en
          veiligste variant.</p>
        <p className="bij"><strong>Wat ik hier eerlijk bij zeg.</strong> De koppeling met Recras wordt
          op dit scherm nagebootst, omdat ik de Recras-sleutel van UP niet heb. Je ziet dus WAT er zou
          gebeuren, niet dat het al gebeurt. De boeking hieronder komt uit het formulier op dit scherm
          en niet uit Recras. Het dichtzetten van de starttijden is wel echt: dat gebeurt in dit
          systeem, en je ziet het meteen terug op de tee sheet.</p>
      </div>

      <div className="kaart">
        <div className="kop">Er komt een bedrijfsboeking binnen</div>
        <p className="bij">Vul in wat er in Recras geboekt zou zijn. Bij op de knop drukken gaan de
          bijbehorende starttijden in dit systeem dicht, met de reden erbij.</p>

        <div className="sub">Bedrijf</div>
        <input value={bedrijf} onChange={e=>setBedrijf(e.target.value)} placeholder="Naam van het bedrijf"/>

        <div className="sub">Dag</div>
        <input type="date" value={datum} onChange={e=>setDatum(e.target.value)}/>

        <div className="sub">Sport</div>
        <select value={sport} onChange={e=>setSport(e.target.value)}>
          <option value="footgolf">Footgolf</option>
          <option value="golf">Golf</option>
        </select>

        <div className="sub">Van</div>
        <input type="time" value={van} onChange={e=>setVan(e.target.value)}/>
        <div className="sub">Tot en met</div>
        <input type="time" value={tot} onChange={e=>setTot(e.target.value)}/>

        <div className="sub">Aantal personen</div>
        <input type="number" min="1" value={personen} onChange={e=>setPersonen(Number(e.target.value)||1)}/>

        <div className="rij"><div className="sub">Starttijden in dit tijdvak</div>
          <div>{inVenster.length===0 ? "geen" : inVenster.length}</div></div>
        <div className="rij"><div className="sub">Daarvan nu open</div>
          <div>{teBlokkeren.length}</div></div>
        {alDicht.length>0 && <div className="rij"><div className="sub">Stond al dicht</div>
          <div>{alDicht.length}</div></div>}

        {f && <div className="fout">{f}</div>}
        <div className="acties">
          <button className="doe primair" onClick={binnenhalen} disabled={bezig||teBlokkeren.length===0}>
            {bezig ? "Bezig…" : "Bedrijfsboeking binnenhalen (nagebootst)"}
          </button>
          <button className="mini" onClick={laad} disabled={bezig}>Opnieuw ophalen</button>
        </div>
      </div>

      {uitslag && uitslag.soort==="blokkade" && (
        <div className="kaart">
          <div className="kop">Wat er is gebeurd</div>
          <NabootsBalk kort/>
          <p className="bij"><strong>{uitslag.bedrijf}</strong>, {uitslag.personen} personen,
            {" "}{uitslag.van} tot {uitslag.tot}. Kenmerk {uitslag.code}.</p>
          <div className="rij"><div className="sub">Dichtgezet</div><div>{uitslag.gelukt}</div></div>
          <div className="rij"><div className="sub">Niet dichtgekregen</div><div>{uitslag.mislukt}</div></div>
          {uitslag.mislukt>0 && <p className="bij">De starttijden hieronder zijn niet dichtgegaan omdat
            er al spelers in zitten. Dat is met opzet: de database weigert dat, anders zou iemand een
            starttijd houden die officieel dicht staat. Bel die mensen of verplaats ze, en zet de
            starttijd daarna met de hand dicht op de tee sheet.</p>}
          <div className="tabelwrap"><table className="tabel"><tbody>
            {uitslag.regels.map(r=>(
              <tr key={r.tijd}>
                <td>{r.tijd}</td>
                <td>{r.gelukt ? <span className="uitslag-ok">dicht</span> : <span className="uitslag-nee">niet dicht</span>}</td>
                <td>{r.reden || ""}</td>
              </tr>))}
          </tbody></table></div>
        </div>)}

      {uitslag && uitslag.soort==="vrijgave" && (
        <div className="kaart">
          <div className="kop">Vrijgegeven</div>
          <NabootsBalk kort/>
          <p className="bij">Nagebootste boeking {uitslag.code} is geannuleerd.</p>
          <div className="rij"><div className="sub">Weer open</div><div>{uitslag.gelukt}</div></div>
          <div className="rij"><div className="sub">Niet gelukt</div><div>{uitslag.mislukt}</div></div>
          <div className="tabelwrap"><table className="tabel"><tbody>
            {uitslag.regels.map(r=>(
              <tr key={r.datum+r.tijd}>
                <td>{kortDat(r.datum)}</td><td>{r.tijd}</td>
                <td>{r.gelukt ? <span className="uitslag-ok">open</span> : <span className="uitslag-nee">nog dicht</span>}</td>
                <td>{r.reden || ""}</td>
              </tr>))}
          </tbody></table></div>
        </div>)}

      <div className="kaart">
        <div className="kop">Nagebootste bedrijfsboekingen die nu starttijden dichthouden</div>
        {lopend.length===0 && <p className="bij">Geen. Er staat op deze baan geen enkele starttijd dicht
          door een nabootsing.</p>}
        {lopend.map(g=>(
          <div className="rij" key={g.code}>
            <div>
              <strong>{g.code}</strong>{" "}
              <span className="sub">{kortDat(g.datum)} · {g.sloten.length} starttijd{g.sloten.length===1?"":"en"}</span>
              <div className="sub">{g.opmerking}</div>
            </div>
            <div className="acties">
              <button className="mini gevaar" onClick={()=>vrijgeven(g)} disabled={bezig}>
                Boeking annuleren en vrijgeven
              </button>
            </div>
          </div>))}
        <p className="bij">Vrijgeven raakt alleen de starttijden met dit kenmerk in de opmerking. Een
          starttijd die de balie zelf heeft dichtgezet blijft dicht.</p>
      </div>

      <div className="kaart">
        <div className="kop">Wat hier echt is en wat nagebootst</div>
        <p className="bij"><strong>Echt:</strong> het dichtzetten en vrijgeven zelf. Dat loopt langs
          dezelfde weg als de knop Blok op de tee sheet, en het resultaat staat in de echte
          oefendatabase. Ook echt is de weigering bij een starttijd waar al spelers in zitten.</p>
        <p className="bij"><strong>Nagebootst:</strong> de bedrijfsboeking. Die komt niet uit Recras,
          hij komt uit het formulier hierboven. Er is geen Recras-sleutel, geen aanroep en geen webhook.
          Een echte koppeling zou dit periodiek zelf doen; dat moet gebouwd worden door de bouwer bij UP.</p>
      </div>
    </div>
  );
}
