const hm = (m) => String(Math.floor(m / 60)).padStart(2, '0') + ':' + String(m % 60).padStart(2, '0');
const hshort = (m) => (m % 60 ? hm(m).replace(/^0/, '') : String(m / 60));
const shiftHrs = (s) => (s ? (s[1] - s[0] - (s[1] - s[0] > 300 ? 30 : 0)) / 60 : 0);

function Schedule() {
  const { L, lang, fmt, O, employees, setEmployees, toast } = useMizo();
  const [edit, setEdit] = React.useState(null);
  const [copy, setCopy] = React.useState(null), [copied, setCopied] = React.useState(null);
  const [dirty, setDirty] = React.useState(false);
  const dates = [26, 27, 28, 29, 30, 31, 1];
  const sales = [O.dowRev[0], O.dowRev[1], O.dowRev[2], ...O.forecast.slice(0, 4).map((f) => f.rev)];
  const dayCost = (e, d) => { const s = e.sched[d]; if (!s) return 0; if (e.type === 'salary') return e.salary / (Object.keys(e.sched).length * 2); return shiftHrs(s) * e.rate; };
  const tot = dates.map((_, d) => ({ h: employees.reduce((a, e) => a + shiftHrs(e.sched[d]), 0), c: employees.reduce((a, e) => a + dayCost(e, d), 0) }));
  const wkC = tot.reduce((a, t) => a + t.c, 0), wkS = sales.reduce((a, s) => a + s, 0);
  const save = (s) => { setEmployees(employees.map((e) => { if (e.id !== edit.emp) return e; const sc = { ...e.sched }; if (s) sc[edit.d] = s; else delete sc[edit.d]; return { ...e, sched: sc }; })); setDirty(true); setEdit(null); };
  const cur = edit && employees.find((e) => e.id === edit.emp);
  return (
    <div className="page">
      <PageHead sub={L('Week of October 26. Shifts feed the time clock, overtime warnings and the payroll estimate.', 'Semaine du 26 octobre. Les quarts alimentent le pointage, les alertes d’heures supp. et la paie.')}>
        {copied ? <span className="save-ok"><Icon n="check-circle" />{L(`Draft ready for the week of ${copied} · not published (demo)`, `Brouillon prêt pour la semaine du ${copied} · non publié (démo)`)}</span> : null}<button className="btn btn-secondary" onClick={() => setCopy({ wk: 'Nov 2', keep: true, skipOff: true })}><Icon n="copy" />{L('Copy to next week', 'Copier à la semaine suivante')}</button>
        <button className="btn btn-primary" onClick={() => { setDirty(false); toast(L(`Schedule published · ${employees.length} people notified`, `Horaire publié · ${employees.length} personnes avisées`)); }}><Icon n="paper-plane-tilt" />{dirty ? L('Publish changes', 'Publier les changements') : L('Publish', 'Publier')}</button>
      </PageHead>
      <Modal open={!!copy} onClose={() => setCopy(null)} title={<span className="wiz-title"><Icon n="copy" />{L('Copy this week’s schedule', 'Copier l’horaire de la semaine')}</span>} actions={<><button className="btn btn-secondary" onClick={() => setCopy(null)}>{L('Cancel', 'Annuler')}</button><button className="btn btn-primary" onClick={() => { setCopied(copy.wk === 'Nov 2' ? L('Nov 2', '2 nov.') : L('Nov 9', '9 nov.')); setCopy(null); }}><Icon n="copy" />{L('Create draft', 'Créer le brouillon')}</button></>}>
        {copy ? <>
          <Field label={L('Copy to the week of', 'Copier vers la semaine du')} id="cw-wk"><select id="cw-wk" className="input" value={copy.wk} onChange={(e) => setCopy({ ...copy, wk: e.target.value })}><option value="Nov 2">{L('Monday, November 2', 'lundi 2 novembre')}</option><option value="Nov 9">{L('Monday, November 9', 'lundi 9 novembre')}</option></select></Field>
          <div className="set-row"><div><div>{L('Keep the same people on each shift', 'Garder les mêmes personnes')}</div><div className="muted sm">{L('Otherwise shifts are copied as open shifts', 'Sinon, les quarts sont copiés comme quarts libres')}</div></div><Toggle on={copy.keep} label="keep" onChange={(v) => setCopy({ ...copy, keep: v })} /></div>
          <div className="set-row"><div><div>{L('Skip approved time off', 'Ignorer les congés approuvés')}</div><div className="muted sm">{L('Nobody is scheduled on a day they asked off', 'Personne n’est prévu un jour de congé')}</div></div><Toggle on={copy.skipOff} label="skip" onChange={(v) => setCopy({ ...copy, skipOff: v })} /></div>
          <div className="suggest"><Icon n="calendar" /><div>{L(`${employees.reduce((a, e) => a + Object.keys(e.sched || {}).length, 0)} shifts · ${fmt.num(Math.round(tot.reduce((a, x) => a + x.h, 0)))} hours · about ${fmt.money0(wkC)} in wages`, `${employees.reduce((a, e) => a + Object.keys(e.sched || {}).length, 0)} quarts · ${fmt.num(Math.round(tot.reduce((a, x) => a + x.h, 0)))} heures · environ ${fmt.money0(wkC)} de salaires`)}</div></div>
          <p className="muted sm" style={{ margin: 0 }}><Icon n="flask" /> {L('Demo: the draft is noted but this screen shows one week. Staff are only notified when you publish (Phase 2).', 'Démo : le brouillon est noté mais l’écran montre une semaine. L’équipe n’est avisée qu’à la publication (phase 2).')}</p>
        </> : null}
      </Modal>
      <section className="stats">
        <Stat label={L('Scheduled hours', 'Heures prévues')} value={fmt.num(Math.round(tot.reduce((a, t) => a + t.h, 0)))}>{employees.length} {L('people', 'personnes')}</Stat>
        <Stat label={L('Labour cost (est.)', 'Coût main-d’œuvre (est.)')} value={fmt.money0(wkC)}>{L('Wages only, before employer costs', 'Salaires seulement, avant charges')}</Stat>
        <Stat label={L('Labour vs. forecast sales', 'Main-d’œuvre vs ventes prévues')} value={fmt.pct((wkC / wkS) * 100)} tone={(wkC / wkS) * 100 > 30 ? 'warn' : 'pos'}>{L('Target under 30%', 'Cible sous 30 %')}</Stat>
        <Stat label={L('Status', 'État')} value={dirty ? L('Draft', 'Brouillon') : L('Published', 'Publié')} tone={dirty ? 'warn' : 'acc'}>{dirty ? L('Staff haven’t seen changes', 'Changements non publiés') : L('Tue, Oct 27 · 3:02 pm', 'mar. 27 oct. · 15 h 02')}</Stat>
      </section>
      <div className="panel panel-flush">
        <div className="table-scroll">
          <table className="table mtable sched">
            <thead><tr><th>{L('Team member', 'Employé')}</th>{O.dow.map((d, i) => <th key={i} className={i === 2 ? 'today' : ''}>{d[lang]} {dates[i]}</th>)}<th className="num">{L('Hours', 'Heures')}</th></tr></thead>
            <tbody>
              {employees.map((e) => { const wh = Object.keys(e.sched).reduce((a, d) => a + shiftHrs(e.sched[d]), 0); return (
                <tr key={e.id}>
                  <td><div className="emp-cell"><span className="emp-av">{e.name.split(' ').map((w) => w[0]).join('').slice(0, 2)}</span><div><div className="cell-main">{e.name.split(' ')[0]}</div><div className="cell-sub">{e.role[lang]}</div></div></div></td>
                  {dates.map((_, d) => { const s = e.sched[d]; return (
                    <td key={d} className={d === 2 ? 'today' : ''}>{s ? <button className="shift" onClick={() => setEdit({ emp: e.id, d })}>{hshort(s[0])}–{hshort(s[1])}</button> : <button className="shift empty" aria-label={L('Add shift', 'Ajouter')} onClick={() => setEdit({ emp: e.id, d })}><Icon n="plus" /></button>}</td>
                  ); })}
                  <td className="num">{wh > 40 && e.type === 'hourly' ? <Pill tone="warn">{fmt.num(wh)} h</Pill> : <span className="tnum">{fmt.num(wh)} h</span>}</td>
                </tr>
              ); })}
            </tbody>
            <tfoot>
              <tr><td className="muted">{L('Labour cost', 'Coût')}</td>{tot.map((t, d) => <td key={d} className={'tnum' + (d === 2 ? ' today' : '')}>{fmt.money0(t.c)}<div className="cell-sub">{fmt.num(Math.round(t.h))} h</div></td>)}<td></td></tr>
              <tr><td className="muted">{L('Sales (forecast)', 'Ventes (prévues)')}</td>{sales.map((s, d) => { const p = (tot[d].c / s) * 100; return <td key={d} className={'tnum' + (d === 2 ? ' today' : '')}>{fmt.kmoney(s)}<div className={'cell-sub ' + (p > 32 ? 'txt-neg' : p > 28 ? 'txt-warn' : 'txt-pos')}>{fmt.pct(p)}</div></td>; })}<td></td></tr>
            </tfoot>
          </table>
        </div>
      </div>
      {edit ? <ShiftModal emp={cur} d={edit.d} label={`${O.dow[edit.d][lang]} ${dates[edit.d]}`} onSave={save} onClose={() => setEdit(null)} /> : null}
    </div>
  );
}

function ShiftModal({ emp, d, label, onSave, onClose }) {
  const { L } = useMizo();
  const s = emp.sched[d];
  const [a, setA] = React.useState(hm(s ? s[0] : 600));
  const [b, setB] = React.useState(hm(s ? s[1] : 1080));
  const toM = (x) => { const [h, m] = x.split(':').map(Number); return h * 60 + (m || 0); };
  const ok = toM(b) > toM(a);
  return (
    <Modal open onClose={onClose} title={`${emp.name.split(' ')[0]} · ${label}`} actions={<>
      {s ? <button className="btn btn-ghost" onClick={() => onSave(null)} style={{ marginRight: 'auto' }}><Icon n="trash" />{L('Remove shift', 'Retirer')}</button> : null}
      <button className="btn btn-secondary" onClick={onClose}>{L('Cancel', 'Annuler')}</button>
      <button className="btn btn-primary" disabled={!ok} onClick={() => onSave([toM(a), toM(b)])}>{s ? L('Save shift', 'Enregistrer') : L('Add shift', 'Ajouter')}</button>
    </>}>
      <div className="form-grid">
        <div className="field"><label>{L('Starts', 'Début')}</label><input className="input" type="time" step="900" value={a} onChange={(e) => setA(e.target.value)} /></div>
        <div className="field"><label>{L('Ends', 'Fin')}</label><input className="input" type="time" step="900" value={b} onChange={(e) => setB(e.target.value)} /></div>
      </div>
      <p className="muted sm" style={{ margin: 0 }}>{ok ? L(`${shiftHrs([toM(a), toM(b)])} paid hours · 30 min unpaid break on shifts over 5 h`, `${shiftHrs([toM(a), toM(b)])} h payées · pause de 30 min non payée après 5 h`) : L('End must be after start', 'La fin doit suivre le début')}</p>
    </Modal>
  );
}

function Checklists() {
  const { L, lang, fmt, O, toast } = useMizo();
  const [lists, setLists] = React.useState(O.checklists);
  const [temps, setTemps] = React.useState(O.temps);
  const [read, setRead] = React.useState({});
  const toggle = (k, i) => setLists({ ...lists, [k]: { ...lists[k], items: lists[k].items.map((it, j) => (j === i ? { ...it, done: !it.done, by: it.done ? null : 'Eleni' } : it)) } });
  const all = Object.values(lists).flatMap((l) => l.items), done = all.filter((i) => i.done).length;
  const bad = (t) => (t.hot ? t.v < t.lim : t.v > t.lim);
  const log = (i) => { const v = Number(read[i]); if (read[i] === '' || read[i] == null || isNaN(v)) return; setTemps(temps.map((t, j) => (j === i ? { ...t, v, t: '14:20' } : t))); setRead({ ...read, [i]: '' }); toast(L('Temperature logged', 'Température notée')); };
  return (
    <div className="page">
      <PageHead sub={L('Opening, shift change and closing routines, plus the food-safety temperature log.', 'Routines d’ouverture, de changement de quart et de fermeture, et registre des températures.')} />
      <section className="stats">
        <Stat label={L('Tasks done today', 'Tâches faites aujourd’hui')} value={`${done} / ${all.length}`}>{fmt.pct((done / all.length) * 100)}</Stat>
        <Stat label={L('Opening', 'Ouverture')} value={lists.open.items.every((i) => i.done) ? L('Complete', 'Terminée') : L('1 left', '1 restante')} tone={lists.open.items.every((i) => i.done) ? 'pos' : 'warn'}>{L('Due', 'Prévue')} {lists.open.due}</Stat>
        <Stat label={L('Temperatures out of range', 'Températures hors limite')} value={temps.filter(bad).length} tone={temps.filter(bad).length ? 'neg' : 'pos'}>{L('MAPAQ requires a daily log', 'Le MAPAQ exige un registre quotidien')}</Stat>
      </section>
      <section className="cl-grid">
        {Object.entries(lists).map(([k, l]) => { const d = l.items.filter((i) => i.done).length; return (
          <div key={k} className="panel">
            <div className="panel-head"><div><h3>{l.name[lang]}</h3><p className="muted">{L('Due', 'Prévu')} {l.due} · {d}/{l.items.length}</p></div>{d === l.items.length ? <Pill tone="pos">{L('Done', 'Fait')}</Pill> : null}</div>
            <div className="hbar-track"><div className="hbar-fill first" style={{ width: (d / l.items.length) * 100 + '%' }}></div></div>
            <ul className="cl">
              {l.items.map((it, i) => (
                <li key={i}><label className={'check' + (it.done ? ' done' : '')}><input type="checkbox" checked={it.done} onChange={() => toggle(k, i)} /><span>{it.name[lang]}</span></label>{it.by ? <span className="muted sm">{it.by}</span> : null}</li>
              ))}
            </ul>
          </div>
        ); })}
      </section>
      <div className="panel panel-flush">
        <div className="panel-head pad"><div><h3>{L('Temperature log', 'Registre des températures')}</h3><p className="muted">{L('Cold at or below 4 °C, frozen at or below −18 °C, hot holding at or above 60 °C', 'Froid ≤ 4 °C, congelé ≤ −18 °C, maintien chaud ≥ 60 °C')}</p></div></div>
        <div className="table-scroll">
          <table className="table mtable">
            <thead><tr><th>{L('Unit', 'Appareil')}</th><th className="num">{L('Last reading', 'Dernière lecture')}</th><th className="hide-sm">{L('Logged', 'Notée')}</th><th>{L('Status', 'État')}</th><th>{L('New reading', 'Nouvelle lecture')}</th></tr></thead>
            <tbody>{temps.map((t, i) => (
              <tr key={i}><td className="cell-main">{t.name[lang]}</td><td className="num tnum">{fmt.num(t.v)} °C</td><td className="tnum hide-sm">{t.t}</td><td>{bad(t) ? <Pill tone="neg">{L('Out of range', 'Hors limite')}</Pill> : <Pill tone="pos">OK</Pill>}</td>
                <td><div className="portion"><input className="input" type="number" step="0.1" placeholder="°C" value={read[i] ?? ''} onChange={(e) => setRead({ ...read, [i]: e.target.value })} /><button className="btn btn-secondary" onClick={() => log(i)}>{L('Log', 'Noter')}</button></div></td></tr>
            ))}</tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Schedule, ShiftModal, Checklists });
