// i18n.jsx — tiny language layer. EN / GR (Greek).
// Stores selection in localStorage; broadcasts changes via a window event so all
// mounted components re-render even across micro-roots.

const I18N_KEY = 'frontline_lang';
const DEFAULT_LANG = 'en';

const LANGS = [
  { code: 'en', label: 'EN', full: 'English'   },
  { code: 'gr', label: 'GR', full: 'Ελληνικά' },
];

// ---------- Shared dictionary (sidebar, topbar, buttons, common labels) ----------
const COMMON = {
  // Sidebar — operations
  'nav.ops':         { en: 'Operations',  gr: 'Λειτουργίες' },
  'nav.dashboard':   { en: 'Dashboard',   gr: 'Πίνακας' },
  'nav.shipments':   { en: 'Cases',       gr: 'Υποθέσεις' },
  'nav.stock':       { en: 'Stock List',  gr: 'Απόθεμα' },
  'nav.quotes':      { en: 'Quotes',      gr: 'Προσφορές' },
  'nav.customs':     { en: 'Customs',     gr: 'Τελωνεία' },
  'nav.docs':        { en: 'Delivery Notes', gr: 'Δελτία Αποστολής' },
  'nav.invoices':    { en: 'Invoices',    gr: 'Τιμολόγια' },
  'nav.vat':         { en: 'VAT Exemptions', gr: 'Απαλλακτικά ΦΠΑ' },
  // Sidebar — network
  'nav.network':     { en: 'Network',     gr: 'Δίκτυο' },
  'nav.clients':     { en: 'Clients',     gr: 'Πελάτες' },
  'nav.suppliers':   { en: 'Suppliers',   gr: 'Προμηθευτές' },
  'nav.partners':    { en: 'Partners',    gr: 'Συνεργάτες' },
  'nav.settings':    { en: 'Settings',    gr: 'Ρυθμίσεις' },

  // Settings modal
  'settings.title':       { en: 'Settings',                                    gr: 'Ρυθμίσεις' },
  'settings.sub':         { en: 'Applies across every page, unless a page overrides it.',
                            gr: 'Εφαρμόζεται σε όλες τις σελίδες, εκτός αν τις παρακάμψει.' },
  'settings.appearance':  { en: 'Appearance',                                  gr: 'Εμφάνιση' },
  'settings.labels':      { en: 'Form label position',                         gr: 'Θέση ετικετών φόρμας' },
  'settings.labels.hint': { en: 'Where field labels sit relative to the input box.',
                            gr: 'Πού τοποθετούνται οι ετικέτες σε σχέση με το κουτί.' },
  'settings.lang':        { en: 'Language',                                    gr: 'Γλώσσα' },
  'settings.close':       { en: 'Close',                                       gr: 'Κλείσιμο' },
  'settings.tables':      { en: 'Table layout',                                gr: 'Διάταξη πίνακα' },
  'settings.tables.hint': { en: 'How list pages show extra fields. Printing always uses the wide layout (landscape).',
                            gr: 'Πώς οι πίνακες εμφανίζουν επιπλέον πεδία. Η εκτύπωση χρησιμοποιεί πάντα την πλήρη διάταξη (οριζόντια).' },
  'settings.nav':         { en: 'Navigation',                                  gr: 'Πλοήγηση' },
  'settings.navorder':    { en: 'Sidebar order',                              gr: 'Σειρά πλαϊνής στήλης' },
  'settings.navorder.hint':{en: 'Drag to reorder, or use the up/down arrows.', gr: 'Σύρετε για αλλαγή σειράς, ή χρησιμοποιήστε τα βέλη.' },
  'settings.navorder.reset':{en: 'Reset to default',                          gr: 'Επαναφορά' },
  'settings.navorder.up': { en: 'Move up',                                    gr: 'Μετακίνηση πάνω' },
  'settings.navorder.down':{en: 'Move down',                                  gr: 'Μετακίνηση κάτω' },
  'settings.navorder.drag':{en: 'Drag to reorder',                            gr: 'Σύρετε για αλλαγή σειράς' },
  'switch.table.compact': { en: 'More button',                                 gr: 'Με κουμπί "Περισσότερα"' },
  'switch.table.wide':    { en: 'Show every column',                           gr: 'Όλες οι στήλες' },

  // Topbar
  'tb.search':       { en: 'Search shipments, IDs, consignees…', gr: 'Αναζήτηση αποστολών, ΙΔ, παραλήπτες…' },
  'tb.new':          { en: 'New booking',   gr: 'Νέα κράτηση' },
  'tb.back':         { en: 'Back',          gr: 'Πίσω' },

  // Common buttons
  'btn.save':        { en: 'Save',          gr: 'Αποθήκευση' },
  'btn.submit':      { en: 'Submit',        gr: 'Υποβολή' },
  'btn.cancel':      { en: 'Cancel',        gr: 'Ακύρωση' },
  'btn.add_row':     { en: 'Add row',       gr: 'Προσθήκη γραμμής' },

  // Tweaks
  'tweak.form':      { en: 'Form',                gr: 'Φόρμα' },
  'tweak.labels':    { en: 'Label position',      gr: 'Θέση ετικέτας' },
  'tweak.labels.hint':{ en: 'Default across the app — pages can override.', gr: 'Προεπιλογή για όλη την εφαρμογή — οι σελίδες μπορούν να το αλλάξουν.' },
  'tweak.label.side':{ en: 'side',                gr: 'πλάι' },
  'tweak.label.top': { en: 'top',                 gr: 'πάνω' },
  'tweak.lang':      { en: 'Language',            gr: 'Γλώσσα' },

  // In-page label-position switch
  'switch.labels':   { en: 'Labels',              gr: 'Ετικέτες' },
  'switch.labels.side':{ en: 'Side',              gr: 'Πλάι' },
  'switch.labels.top':{ en: 'On top',             gr: 'Πάνω' },
  'switch.labels.reset':{ en: 'Reset',            gr: 'Επαναφορά' },
  'switch.labels.overridden':{ en: 'Overrides default', gr: 'Αντικαθιστά την προεπιλογή' },

  // Misc
  'noop.empty_table':{ en: 'No rows yet.',        gr: 'Δεν υπάρχουν γραμμές.' },
  'placeholder.select': { en: 'Select…',          gr: 'Επιλέξτε…' },
};

const getLang = () => {
  try { return localStorage.getItem(I18N_KEY) || DEFAULT_LANG; }
  catch (e) { return DEFAULT_LANG; }
};

const setLang = (code) => {
  try { localStorage.setItem(I18N_KEY, code); } catch (e) {}
  window.dispatchEvent(new CustomEvent('langchange', { detail: { code } }));
};

// React hook — returns [lang, setLang, t(key, dict?)]
const useLang = (extraDict) => {
  const [lang, setLangState] = React.useState(getLang());
  React.useEffect(() => {
    const handler = (e) => setLangState(e.detail.code);
    window.addEventListener('langchange', handler);
    return () => window.removeEventListener('langchange', handler);
  }, []);
  const t = React.useCallback((key, fallback) => {
    const dict = (extraDict && extraDict[key]) || COMMON[key];
    if (!dict) return fallback != null ? fallback : key;
    return dict[lang] || dict[DEFAULT_LANG] || key;
  }, [lang, extraDict]);
  const change = React.useCallback((code) => setLang(code), []);
  return [lang, change, t];
};

// ---------- Pill toggle component ----------
const LanguageToggle = () => {
  const [lang, change] = useLang();
  return (
    <div className="lang-toggle" role="group" aria-label="Language">
      {LANGS.map(l => (
        <button
          key={l.code}
          type="button"
          className={lang === l.code ? 'on' : ''}
          onClick={() => change(l.code)}
          title={l.full}
        >
          {l.label}
        </button>
      ))}
    </div>
  );
};

Object.assign(window, { useLang, setLang, getLang, LanguageToggle, LANGS, COMMON });

// ---------- Global UI prefs (label position, etc.) — persisted in localStorage ----------
// `labels` is the global default; `pageLabels[pageKey]` is an optional per-page
// override that wins over the default for that page only. An undefined override
// means "follow the global default" for that page.
const PREFS_KEY = 'frontline_prefs';
const DEFAULT_PREFS = { labels: 'side', pageLabels: {}, tableMode: 'compact', sidebarOrder: null };

const getPrefs = () => {
  try {
    const stored = JSON.parse(localStorage.getItem(PREFS_KEY) || '{}');
    return {
      ...DEFAULT_PREFS,
      ...stored,
      pageLabels: { ...(stored.pageLabels || {}) },
    };
  } catch (e) { return { ...DEFAULT_PREFS, pageLabels: {} }; }
};
const setPref = (k, v) => {
  const p = getPrefs(); p[k] = v;
  try { localStorage.setItem(PREFS_KEY, JSON.stringify(p)); } catch (e) {}
  window.dispatchEvent(new CustomEvent('prefschange', { detail: { key: k, value: v, prefs: p } }));
};

// Per-page label-position override. Pass null/undefined to clear the override
// and have that page follow the global `labels` setting again.
const setPageLabels = (pageKey, value) => {
  const p = getPrefs();
  const next = { ...(p.pageLabels || {}) };
  if (value == null) delete next[pageKey];
  else next[pageKey] = value;
  setPref('pageLabels', next);
};

// Resolve the effective label position for a given page key, honoring the
// per-page override when present.
const effectiveLabels = (prefs, pageKey) => {
  const o = prefs && prefs.pageLabels && pageKey ? prefs.pageLabels[pageKey] : null;
  return o || (prefs && prefs.labels) || 'side';
};
const usePrefs = () => {
  const [prefs, setPrefsState] = React.useState(getPrefs());
  React.useEffect(() => {
    const onChange = (e) => setPrefsState(e.detail.prefs);
    window.addEventListener('prefschange', onChange);
    return () => window.removeEventListener('prefschange', onChange);
  }, []);
  return [prefs, setPref];
};

// Resolve effective sidebar item order from prefs. If the user has set a
// custom order, items appear in that order; any items defined by the app but
// missing from the saved order fall in at the end (so adding new nav items
// later doesn't strand them); unknown ids in the saved order are ignored.
const effectiveSidebarOrder = (prefs, defaultIds) => {
  const saved = prefs && Array.isArray(prefs.sidebarOrder) ? prefs.sidebarOrder : null;
  if (!saved || !saved.length) return defaultIds.slice();
  const known = new Set(defaultIds);
  const used = new Set();
  const out = [];
  saved.forEach(id => { if (known.has(id) && !used.has(id)) { out.push(id); used.add(id); } });
  defaultIds.forEach(id => { if (!used.has(id)) out.push(id); });
  return out;
};

Object.assign(window, { usePrefs, setPref, getPrefs, setPageLabels, effectiveLabels, effectiveSidebarOrder });

// ---------- Table mode (compact "More button" vs wide "Show every column") -------
// Shared across every list page. Reads the pref, listens for beforeprint /
// afterprint, and force-flushes a synchronous re-render so the printed sheet
// always carries every column (regardless of what the user chose on screen).
// Returns `{ wideMode, printing, mode }`.
const useTableMode = () => {
  const [prefs] = usePrefs();
  const [printing, setPrinting] = React.useState(false);

  React.useEffect(() => {
    const flush = (val) => {
      if (window.ReactDOM && ReactDOM.flushSync) {
        ReactDOM.flushSync(() => setPrinting(val));
      } else {
        setPrinting(val);
      }
    };
    const onBefore = () => flush(true);
    const onAfter  = () => flush(false);
    window.addEventListener('beforeprint', onBefore);
    window.addEventListener('afterprint',  onAfter);
    const mql = window.matchMedia ? window.matchMedia('print') : null;
    const onMql = (e) => flush(e.matches);
    if (mql && mql.addEventListener) mql.addEventListener('change', onMql);
    return () => {
      window.removeEventListener('beforeprint', onBefore);
      window.removeEventListener('afterprint',  onAfter);
      if (mql && mql.removeEventListener) mql.removeEventListener('change', onMql);
    };
  }, []);

  const mode = prefs.tableMode || 'compact';
  return { wideMode: printing || mode === 'wide', printing, mode };
};

window.useTableMode = useTableMode;
