'use strict';

// ── State ─────────────────────────────────────────────────────────────────────
const State = {
  token: null,
  user: null,
  restaurants: [],          // tous les restaurants de l'employé
  restaurantId: null,
  restaurantName: null,
  pointage: null,
  durationTimer: null,
  clockTimer: null,
};

// ── API ───────────────────────────────────────────────────────────────────────
// Sur pointage.crewplan.fr l’API est sur app.crewplan.fr (cf. frontend environment.prod.ts).
// Un relatif `/api` renverrait du HTML (SPA / 404) → erreur JSON « Unexpected token '<' ».
const API_BASE =
  typeof window !== 'undefined' && window.location.hostname === 'pointage.crewplan.fr'
    ? 'https://app.crewplan.fr/api'
    : '/api';

const API = {
  base: API_BASE,

  headers() {
    const h = { 'Content-Type': 'application/json' };
    if (State.token) h['Authorization'] = `Bearer ${State.token}`;
    return h;
  },

  async post(path, body) {
    const r = await fetch(this.base + path, {
      method: 'POST',
      headers: this.headers(),
      body: JSON.stringify(body),
    });
    if (!r.ok) {
      const err = await r.json().catch(() => ({ message: 'Erreur réseau' }));
      throw new Error(err.message || 'Erreur');
    }
    return r.json();
  },

  async put(path, body = {}) {
    const r = await fetch(this.base + path, {
      method: 'PUT',
      headers: this.headers(),
      body: JSON.stringify(body),
    });
    if (!r.ok) {
      const err = await r.json().catch(() => ({ message: 'Erreur réseau' }));
      throw new Error(err.message || 'Erreur');
    }
    return r.json();
  },

  async get(path) {
    const r = await fetch(this.base + path, { headers: this.headers() });
    if (!r.ok) {
      if (r.status === 401) throw new Error('SESSION_EXPIRED');
      const err = await r.json().catch(() => ({ message: 'Erreur réseau' }));
      throw new Error(err.message || 'Erreur');
    }
    return r.json();
  },
};

// ── Storage ───────────────────────────────────────────────────────────────────
const Store = {
  save() {
    localStorage.setItem('cp_token', State.token || '');
    localStorage.setItem('cp_user', JSON.stringify(State.user || null));
    localStorage.setItem('cp_restaurant_id', State.restaurantId || '');
    localStorage.setItem('cp_restaurant_name', State.restaurantName || '');
  },
  load() {
    State.token = localStorage.getItem('cp_token') || null;
    State.restaurantId = localStorage.getItem('cp_restaurant_id') || null;
    State.restaurantName = localStorage.getItem('cp_restaurant_name') || null;
    try {
      State.user = JSON.parse(localStorage.getItem('cp_user')) || null;
    } catch { State.user = null; }
  },
  clear() {
    ['cp_token', 'cp_user', 'cp_restaurant_id', 'cp_restaurant_name'].forEach(
      (k) => localStorage.removeItem(k)
    );
  },
};

// ── View management ───────────────────────────────────────────────────────────
function showView(name) {
  document.querySelectorAll('.view').forEach((v) => v.classList.remove('active'));
  const el = document.getElementById(`view-${name}`);
  if (el) el.classList.add('active');
}

// ── Horloge ───────────────────────────────────────────────────────────────────
const DAYS_FR   = ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'];
const MONTHS_FR = ['janvier','février','mars','avril','mai','juin','juillet','août','septembre','octobre','novembre','décembre'];

function fmt(d)       { return d.toTimeString().slice(0, 5); }
function fmtISO(iso)  { return iso ? fmt(new Date(iso)) : '—'; }
function elapsed(iso) {
  if (!iso) return '—';
  const s = Math.floor((Date.now() - new Date(iso).getTime()) / 1000);
  return `${String(Math.floor(s/3600)).padStart(2,'0')}:${String(Math.floor((s%3600)/60)).padStart(2,'0')}:${String(s%60).padStart(2,'0')}`;
}

function isOnPause(p) {
  if (!p?.pauses?.length) return false;
  const last = p.pauses[p.pauses.length - 1];
  return last && !last.end;
}

function totalPauseMs(pauses, now) {
  if (!pauses?.length) return 0;
  let ms = 0;
  for (const seg of pauses) {
    const s = new Date(seg.start).getTime();
    const e = seg.end ? new Date(seg.end).getTime() : now;
    ms += Math.max(0, e - s);
  }
  return ms;
}

/** Temps effectif travaillé (hors pauses), pour la journée en cours */
function elapsedWorked(p) {
  if (!p?.clockIn) return '—';
  const start = new Date(p.clockIn).getTime();
  const pauseMs = totalPauseMs(p.pauses || [], Date.now());
  const s = Math.floor((Date.now() - start - pauseMs) / 1000);
  if (s < 0) return '00:00:00';
  return `${String(Math.floor(s/3600)).padStart(2,'0')}:${String(Math.floor((s%3600)/60)).padStart(2,'0')}:${String(s%60).padStart(2,'0')}`;
}

function startClock() {
  if (State.clockTimer) clearInterval(State.clockTimer);
  const tick = () => {
    const now = new Date();
    const t = document.getElementById('clock-time');
    const d = document.getElementById('clock-date');
    if (t) t.textContent = fmt(now);
    if (d) d.textContent = `${DAYS_FR[now.getDay()]} ${now.getDate()} ${MONTHS_FR[now.getMonth()]} ${now.getFullYear()}`;
  };
  tick();
  State.clockTimer = setInterval(tick, 1000);
}

function startDuration() {
  if (State.durationTimer) clearInterval(State.durationTimer);
  const el = document.getElementById('duration-display');
  if (!el || !State.pointage?.clockIn) return;
  const tick = () => { el.textContent = elapsedWorked(State.pointage); };
  tick();
  State.durationTimer = setInterval(tick, 1000);
}

function stopTimers() {
  clearInterval(State.durationTimer);
  clearInterval(State.clockTimer);
  State.durationTimer = State.clockTimer = null;
}

// ── Logout ────────────────────────────────────────────────────────────────────
function logout() {
  stopTimers();
  Store.clear();
  Object.assign(State, {
    token: null, user: null, restaurants: [],
    restaurantId: null, restaurantName: null, pointage: null,
  });
  renderLogin();
}

// ── Vue : Login ───────────────────────────────────────────────────────────────
function renderLogin(hint = '') {
  showView('login');

    const errEl  = document.getElementById('login-error');
    const hintEl = document.getElementById('login-hint');
    const btn    = document.getElementById('login-btn');

    if (hintEl) hintEl.textContent = hint || '';
    if (errEl)  { errEl.textContent = ''; errEl.classList.remove('show'); }

  document.getElementById('login-form').onsubmit = async (e) => {
    e.preventDefault();
    errEl.textContent = '';
    btn.disabled = true;
    btn.textContent = 'Connexion…';

    try {
      const email    = document.getElementById('login-email').value.trim();
      const password = document.getElementById('login-password').value;
      const data     = await API.post('/auth/login', { email, password });

      State.token = data.token;
      State.user  = data.user;
      Store.save();

      await afterLogin();
    } catch (err) {
      errEl.textContent = err.message;
      errEl.classList.add('show');
      btn.disabled = false;
      btn.textContent = 'Se connecter';
    }
  };
}

// ── Après login : récupérer les restaurants de l'employé ─────────────────────
async function afterLogin() {
  // Toujours récupérer la liste réelle des restaurants de l'employé
  try {
    State.restaurants = await API.get('/restaurants/mine');
  } catch {
    State.restaurants = [];
  }

  if (State.restaurants.length === 0) {
    // Peut-être admin/manager — essayer de continuer avec le restaurant stocké
    if (State.restaurantId) {
      try {
        const r = await API.get(`/restaurants/${State.restaurantId}`);
        State.restaurantName = r.name;
        Store.save();
        return renderPointage();
      } catch { /* ignore */ }
    }
    showView('error');
    document.getElementById('error-msg').textContent =
      "Vous n'êtes assigné(e) à aucun restaurant. Contactez votre responsable.";
    return;
  }

  // Si l'URL a fourni un restaurantId → vérifier qu'il est dans la liste
  const ridFromURL = new URLSearchParams(window.location.search).get('restaurantId');

  if (ridFromURL) {
    const match = State.restaurants.find((r) => r._id === ridFromURL);
    if (match) { selectRestaurant(match); return renderPointage(); }
  }

  // Si le storage a un restaurantId valide dans la liste → l'utiliser
  if (State.restaurantId) {
    const match = State.restaurants.find((r) => r._id === State.restaurantId);
    if (match) {
      State.restaurantName = match.name;
      Store.save();
      return renderPointage();
    }
    // Restaurant en cache invalide → on réinitialise
    State.restaurantId = null;
    State.restaurantName = null;
  }

  // Un seul restaurant → sélection automatique
  if (State.restaurants.length === 1) {
    selectRestaurant(State.restaurants[0]);
    return renderPointage();
  }

  // Plusieurs restaurants → sélecteur
  renderRestaurantPicker();
}

// ── Vue : Sélecteur de restaurant ─────────────────────────────────────────────
function renderRestaurantPicker() {
  showView('pick-restaurant');

  const list = document.getElementById('restaurant-list');
  list.innerHTML = '';

  const nameEl = document.getElementById('pick-user-name');
  if (nameEl) nameEl.textContent = State.user?.name || '';

  State.restaurants.forEach((r) => {
    const btn = document.createElement('button');
    btn.className = 'restaurant-pick-btn';
    btn.innerHTML = `
      <span class="pick-icon">🍽️</span>
      <span class="pick-name">${r.name}</span>
      ${r.address ? `<span class="pick-address">${r.address}</span>` : ''}
    `;
    btn.onclick = () => {
      selectRestaurant(r);
      renderPointage();
    };
    list.appendChild(btn);
  });
}

function selectRestaurant(r) {
  State.restaurantId   = r._id;
  State.restaurantName = r.name;
  Store.save();
}

// ── Vue : Pointage ────────────────────────────────────────────────────────────
async function renderPointage() {
  stopTimers();

  try {
    State.pointage = await API.get(`/pointage/today?restaurantId=${State.restaurantId}`);
  } catch (err) {
    if (err.message === 'SESSION_EXPIRED') { logout(); return; }
    State.pointage = null;
  }

  // Header restaurant + logout
  const headerName = document.getElementById('restaurant-name-header');
  if (headerName) headerName.textContent = State.restaurantName || 'Restaurant';

  // Si plusieurs restaurants → bouton changer
  const changeBtn = document.getElementById('change-restaurant-btn');
  if (changeBtn) {
    if (State.restaurants.length > 1) {
      changeBtn.style.display = 'inline-block';
      changeBtn.onclick = () => renderRestaurantPicker();
    } else {
      changeBtn.style.display = 'none';
    }
  }

  // Employé
  const avatar  = document.getElementById('employee-avatar');
  const empName = document.getElementById('employee-name');
  const empRole = document.getElementById('employee-role');
  if (avatar)  avatar.textContent  = State.user?.name?.charAt(0)?.toUpperCase() || '?';
  if (empName) empName.textContent = State.user?.name || '';
  if (empRole) empRole.textContent = roleLabel(State.user?.role);

  // Logout
  document.getElementById('logout-btn').onclick = logout;

  renderStatus();
  // Sync bottom-nav active state
  ['nav-pointage-pt', 'nav-planning-pt'].forEach((id) => {
    const el = document.getElementById(id);
    if (el) el.classList.toggle('active', id === 'nav-pointage-pt');
  });

  showView('pointage');
  startClock();
  loadWeekHistory();
}

// ── Historique semaine ────────────────────────────────────────────────────────
async function loadWeekHistory() {
  const container = document.getElementById('history-list');
  if (!container) return;

  try {
    const entries = await API.get(`/pointage/week?restaurantId=${State.restaurantId}`);
    renderWeekHistory(entries);
  } catch {
    container.innerHTML = '<p style="color:var(--muted);font-size:.8rem;text-align:center">—</p>';
  }
}

function renderWeekHistory(entries) {
  const container = document.getElementById('history-list');
  if (!container) return;

  if (!entries || entries.length === 0) {
    container.innerHTML = '<p style="color:var(--muted);font-size:.8rem;text-align:center">Aucun pointage cette semaine</p>';
    return;
  }

  const STATUS_FR = {
    present: 'Présent', retard: 'Retard', depart_anticipe: 'Départ anticipé',
    absent: 'Absent', en_cours: 'En cours',
  };
  const STATUS_COLOR = {
    present: 'var(--green)', retard: 'var(--amber)', depart_anticipe: 'var(--amber)',
    absent: 'var(--red)', en_cours: 'var(--primary)',
  };

  container.innerHTML = entries.map((e) => {
    const day = new Date(e.date || e.clockIn);
    const dayLabel = `${DAYS_FR[day.getDay()]} ${day.getDate()}`;
    const inn  = e.clockIn  ? fmtISO(e.clockIn)  : '—';
    const out  = e.clockOut ? fmtISO(e.clockOut) : '—';
    const color = STATUS_COLOR[e.status] || 'var(--muted)';
    const statusLabel = STATUS_FR[e.status] || e.status || '—';
    return `
      <div class="history-row">
        <span class="history-day">${dayLabel}</span>
        <span class="history-times">${inn} → ${out}</span>
        <span class="history-status" style="color:${color}">${statusLabel}</span>
      </div>`;
  }).join('');
}

function roleLabel(role) {
  return { superadmin: 'Super Admin', admin: 'Responsable', member: 'Employé' }[role] || role || '';
}

function renderStatus() {
  const p         = State.pointage;
  const statusCard = document.getElementById('status-card');
  const actionBtn  = document.getElementById('action-btn');
  const actionText = document.getElementById('action-text');
  const btnIcon    = document.getElementById('btn-icon');
  const secondaryBtn = document.getElementById('secondary-btn');
  const secondaryText = document.getElementById('secondary-text');
  const secondaryIcon = document.getElementById('secondary-icon');

  if (!p) {
    statusCard.innerHTML = `
      <p class="status-label">Statut aujourd'hui</p>
      <p class="status-value" style="color:var(--muted)">Pas encore pointé</p>`;
    actionBtn.className = 'btn-action btn-in';
    actionBtn.disabled  = false;
    actionText.textContent = 'Pointer mon arrivée';
    btnIcon.textContent    = '▶';
    actionBtn.onclick = handleClockIn;
    if (secondaryBtn) {
      secondaryBtn.style.display = 'none';
      secondaryBtn.setAttribute('aria-hidden', 'true');
      secondaryBtn.onclick = null;
    }

  } else if (!p.clockOut) {
    const onPause = isOnPause(p);
    const lastPause = onPause ? p.pauses[p.pauses.length - 1] : null;
    if (onPause) {
      statusCard.innerHTML = `
        <p class="status-label"><span class="pulse-dot" style="background:var(--amber)"></span>En pause depuis ${fmtISO(lastPause.start)}</p>
        <p class="status-value">Temps travaillé : <span id="duration-display">—</span></p>`;
    } else {
      statusCard.innerHTML = `
        <p class="status-label"><span class="pulse-dot"></span>En service depuis ${fmtISO(p.clockIn)}</p>
        <p class="status-value">Temps travaillé : <span id="duration-display">—</span></p>`;
    }
    startDuration();
    if (secondaryBtn && secondaryText && secondaryIcon) {
      secondaryBtn.style.display = 'block';
      secondaryBtn.removeAttribute('aria-hidden');
      secondaryBtn.disabled = false;
      if (onPause) {
        secondaryBtn.className = 'btn-action btn-resume';
        secondaryText.textContent = 'Reprendre le service';
        secondaryIcon.textContent = '▶';
        secondaryBtn.onclick = handlePauseEnd;
      } else {
        secondaryBtn.className = 'btn-action btn-pause';
        secondaryText.textContent = 'Déclarer une pause';
        secondaryIcon.textContent = '☕';
        secondaryBtn.onclick = handlePauseStart;
      }
    }
    actionBtn.className = 'btn-action btn-out';
    actionBtn.disabled  = false;
    actionText.textContent = 'Pointer ma sortie';
    btnIcon.textContent    = '⏹';
    actionBtn.onclick = handleClockOut;

  } else {
    const labels = {
      present:'Journée complète ✓', retard:'Arrivée en retard',
      depart_anticipe:'Départ anticipé', absent:'Absent', en_cours:'En cours',
    };
    statusCard.innerHTML = `
      <p class="status-label">Journée terminée</p>
      <div class="status-times">
        <div><span>Arrivée</span><strong>${fmtISO(p.clockIn)}</strong></div>
        <div><span>Départ</span><strong>${fmtISO(p.clockOut)}</strong></div>
      </div>
      <p class="status-value" style="margin-top:.75rem;color:var(--green)">${labels[p.status] || p.status}</p>`;
    actionBtn.className = 'btn-action btn-done';
    actionBtn.disabled  = true;
    actionText.textContent = 'Journée enregistrée';
    btnIcon.textContent    = '✓';
    actionBtn.onclick = null;
    if (secondaryBtn) {
      secondaryBtn.style.display = 'none';
      secondaryBtn.setAttribute('aria-hidden', 'true');
      secondaryBtn.onclick = null;
    }
  }
}

// ── QR Scanner ────────────────────────────────────────────────────────────────
const QRScanner = {
  stream: null,
  rafId: null,
  resolved: false,

  open() {
    this.resolved = false;
    const overlay = document.getElementById('qr-scanner-overlay');
    overlay.classList.add('open');
    overlay.setAttribute('aria-hidden', 'false');
    document.getElementById('qr-cancel').onclick = () => this.close();
    this._setStatus('');
    this._startCamera();
  },

  close() {
    this._stopCamera();
    const overlay = document.getElementById('qr-scanner-overlay');
    overlay.classList.remove('open');
    overlay.setAttribute('aria-hidden', 'true');
  },

  _setStatus(msg, type = '') {
    const el = document.getElementById('qr-status');
    if (!el) return;
    el.textContent = msg;
    el.className = `qr-status${type ? ' ' + type : ''}`;
  },

  async _startCamera() {
    try {
      this.stream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: 'environment', width: { ideal: 1280 }, height: { ideal: 720 } },
        audio: false,
      });
      const video = document.getElementById('qr-video');
      video.srcObject = this.stream;
      video.play();
      video.onloadedmetadata = () => this._scanLoop();
    } catch (err) {
      const msg = err.name === 'NotAllowedError'
        ? 'Accès à la caméra refusé. Vérifiez les permissions.'
        : 'Impossible d\'accéder à la caméra.';
      this._setStatus(msg, 'error');
    }
  },

  _stopCamera() {
    if (this.rafId) { cancelAnimationFrame(this.rafId); this.rafId = null; }
    if (this.stream) {
      this.stream.getTracks().forEach((t) => t.stop());
      this.stream = null;
    }
    const video = document.getElementById('qr-video');
    if (video) { video.srcObject = null; }
  },

  _scanLoop() {
    const video  = document.getElementById('qr-video');
    const canvas = document.getElementById('qr-canvas');
    if (!video || !canvas || !this.stream) return;

    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const tick = () => {
      if (this.resolved || !this.stream) return;

      if (video.readyState === video.HAVE_ENOUGH_DATA) {
        canvas.width  = video.videoWidth;
        canvas.height = video.videoHeight;
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const code = jsQR(imageData.data, imageData.width, imageData.height, {
          inversionAttempts: 'dontInvert',
        });
        if (code) {
          this.resolved = true;
          this._onScanned(code.data);
          return;
        }
      }

      this.rafId = requestAnimationFrame(tick);
    };

    this.rafId = requestAnimationFrame(tick);
  },

  _onScanned(raw) {
    const restaurantId = this._extractRestaurantId(raw);

    if (!restaurantId) {
      this._setStatus('QR Code non reconnu. Réessayez.', 'error');
      setTimeout(() => {
        this.resolved = false;
        this._scanLoop();
      }, 1800);
      return;
    }

    // Verify the scanned restaurantId belongs to this employee
    const match = State.restaurants.find((r) => r._id === restaurantId);
    if (!match) {
      this._setStatus('Ce QR Code ne correspond pas à votre établissement.', 'error');
      setTimeout(() => {
        this.resolved = false;
        this._scanLoop();
      }, 2200);
      return;
    }

    this._setStatus('QR Code validé !', 'success');
    // Switch restaurant if needed
    if (restaurantId !== State.restaurantId) selectRestaurant(match);

    setTimeout(() => {
      this.close();
      doClockIn();
    }, 600);
  },

  _extractRestaurantId(raw) {
    // Try JSON first: { "restaurantId": "..." }
    try {
      const obj = JSON.parse(raw);
      if (obj && obj.restaurantId) return obj.restaurantId;
    } catch { /* not JSON */ }

    // Try URL: ?restaurantId=...
    try {
      const url = new URL(raw);
      const rid = url.searchParams.get('restaurantId');
      if (rid) return rid;
    } catch { /* not a URL */ }

    // Try plain restaurantId string (24-char hex)
    if (/^[a-f0-9]{24}$/i.test(raw.trim())) return raw.trim();

    return null;
  },
};

// ── Actions clock-in / clock-out ──────────────────────────────────────────────
function handleClockIn() {
  if (typeof jsQR === 'undefined') {
    // jsQR not loaded yet, fall back to direct clock-in
    doClockIn();
    return;
  }
  QRScanner.open();
}

async function doClockIn() {
  const btn = document.getElementById('action-btn');
  if (btn) btn.disabled = true;
  try {
    const p = await API.post('/pointage/clock-in', { restaurantId: State.restaurantId });
    showSuccess('in', p.clockIn);
  } catch (err) {
    if (btn) btn.disabled = false;
    showToast(err.message, 'error');
  }
}

async function handleClockOut() {
  const btn = document.getElementById('action-btn');
  const sec = document.getElementById('secondary-btn');
  btn.disabled = true;
  if (sec) sec.disabled = true;
  try {
    const p = await API.put('/pointage/clock-out', { restaurantId: State.restaurantId });
    showSuccess('out', p.clockOut);
  } catch (err) {
    btn.disabled = false;
    if (sec) sec.disabled = false;
    showToast(err.message, 'error');
  }
}

async function handlePauseStart() {
  const btn = document.getElementById('action-btn');
  const sec = document.getElementById('secondary-btn');
  if (btn) btn.disabled = true;
  if (sec) sec.disabled = true;
  try {
    const p = await API.put('/pointage/pause-start', { restaurantId: State.restaurantId });
    State.pointage = p;
    renderStatus();
    showToast('Pause enregistrée', 'success');
  } catch (err) {
    showToast(err.message, 'error');
    if (btn) btn.disabled = false;
    if (sec) sec.disabled = false;
  }
}

async function handlePauseEnd() {
  const btn = document.getElementById('action-btn');
  const sec = document.getElementById('secondary-btn');
  if (btn) btn.disabled = true;
  if (sec) sec.disabled = true;
  try {
    const p = await API.put('/pointage/pause-end', { restaurantId: State.restaurantId });
    State.pointage = p;
    renderStatus();
    showToast('Reprise enregistrée', 'success');
  } catch (err) {
    showToast(err.message, 'error');
    if (btn) btn.disabled = false;
    if (sec) sec.disabled = false;
  }
}

// ── Vue : Succès ──────────────────────────────────────────────────────────────
function showSuccess(type, timeIso) {
  stopTimers();
  const icon  = document.getElementById('success-icon');
  const title = document.getElementById('success-title');
  const msg   = document.getElementById('success-msg');
  const time  = document.getElementById('success-time');

  icon.className = `success-icon ${type}`;
  if (type === 'in') {
    icon.textContent  = '▶';
    title.textContent = 'Arrivée enregistrée !';
    msg.textContent   = 'Bonne journée 👋';
  } else {
    icon.textContent  = '⏹';
    title.textContent = 'Départ enregistré !';
    msg.textContent   = 'À bientôt 👋';
  }
  time.textContent = fmtISO(timeIso);

  document.getElementById('back-btn').onclick = () => renderPointage();
  showView('success');
}

// ── Navigation par onglets ────────────────────────────────────────────────────
function switchTab(tab) {
  if (tab === 'planning') {
    renderPlanningView();
  } else {
    renderPointage();
  }
}

// ── Vue : Planning employé ────────────────────────────────────────────────────
const PlanState = {
  weekOffset: 0,   // 0 = semaine courante, -1 = semaine passée, +1 = prochaine
  entries: [],
  monday: null,
};

function getMonday(offset = 0) {
  const now = new Date();
  const day = now.getDay();
  const diff = now.getDate() - ((day + 6) % 7) + offset * 7;
  const mon = new Date(now);
  mon.setDate(diff);
  mon.setHours(0, 0, 0, 0);
  return mon;
}

function formatDate(d) {
  // Utiliser la date locale (pas UTC) pour éviter le décalage de timezone
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`;
}

function renderPlanningView() {
  stopTimers();
  // Sync bottom-nav active state across both views
  ['nav-pointage-pt', 'nav-planning-pt'].forEach((id) => {
    const el = document.getElementById(id);
    if (el) el.classList.toggle('active', id === 'nav-planning-pt');
  });

  const nameEl = document.getElementById('plan-restaurant-name');
  if (nameEl) nameEl.textContent = State.restaurantName || 'Restaurant';

  // Nav buttons
  document.getElementById('plan-prev').onclick = () => { PlanState.weekOffset--; loadPlanning(); };
  document.getElementById('plan-next').onclick = () => { PlanState.weekOffset++; loadPlanning(); };

  showView('planning');
  loadPlanning();
}

async function loadPlanning() {
  const monday = getMonday(PlanState.weekOffset);
  const sunday = new Date(monday); sunday.setDate(monday.getDate() + 6);

  // Week label
  const opts = { day: 'numeric', month: 'long' };
  const monStr = monday.toLocaleDateString('fr-FR', opts);
  const sunStr = sunday.toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' });
  document.getElementById('week-label').textContent = `${monStr} — ${sunStr}`;
  document.getElementById('week-sub').textContent =
    PlanState.weekOffset === 0 ? 'Cette semaine' :
    PlanState.weekOffset === -1 ? 'Semaine passée' :
    PlanState.weekOffset === 1 ? 'Semaine prochaine' :
    `S${getWeekNumber(monday)}`;

  // Disable next if too far
  document.getElementById('plan-next').disabled = PlanState.weekOffset >= 4;
  document.getElementById('plan-prev').disabled = PlanState.weekOffset <= -8;

  const container = document.getElementById('plan-days');
  const emptyEl   = document.getElementById('plan-empty');
  const summaryEl = document.getElementById('week-summary');
  container.innerHTML = '<div class="plan-loading"><div class="loader-sm"></div></div>';
  emptyEl.style.display = 'none';
  summaryEl.style.display = 'none';
  const dlBtn = document.getElementById('plan-download-btn');
  if (dlBtn) dlBtn.style.display = 'none';

  try {
    const weekStart = formatDate(monday);
    const data = await API.get(`/planning/my?restaurantId=${State.restaurantId}&weekStart=${weekStart}`);

    container.innerHTML = '';

    const entries = (data && data.entries) ? data.entries : [];
    PlanState.entries = entries;
    PlanState.monday  = monday;

    // Show/hide download button based on whether there's a planning
    const dlBtn = document.getElementById('plan-download-btn');
    if (dlBtn) dlBtn.style.display = entries.length > 0 ? 'inline-flex' : 'none';

    renderWeekDays(monday, entries);

    if (entries.length > 0) {
      renderWeekSummary(entries, summaryEl);
    }

  } catch (err) {
    if (err.message === 'SESSION_EXPIRED') { logout(); return; }
    container.innerHTML = '';
    emptyEl.style.display = 'flex';
  }
}

function getWeekNumber(d) {
  const date = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
  date.setUTCDate(date.getUTCDate() + 4 - (date.getUTCDay() || 7));
  const yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
  return Math.ceil((((date - yearStart) / 86400000) + 1) / 7);
}

function renderWeekDays(monday, entries) {
  const container = document.getElementById('plan-days');

  // Grouper les entries par date
  const byDate = {};
  entries.forEach((e) => {
    const key = e.date.split('T')[0];
    if (!byDate[key]) byDate[key] = [];
    byDate[key].push(e);
  });

  const STATUS_LABELS = { scheduled: 'Planifié', confirmed: 'Confirmé', absent: 'Absent' };
  const STATUS_CLASS  = { scheduled: 'shift-scheduled', confirmed: 'shift-confirmed', absent: 'shift-absent' };

  for (let i = 0; i < 7; i++) {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    const key = formatDate(d);
    const dayEntries = byDate[key] || [];
    const isToday = key === formatDate(new Date());

    const dayEl = document.createElement('div');
    dayEl.className = `plan-day${isToday ? ' plan-day-today' : ''}${dayEntries.length === 0 ? ' plan-day-off' : ''}`;

    const dayName = DAYS_FR[d.getDay()];
    const dayNum  = d.getDate();
    const monthName = MONTHS_FR[d.getMonth()];

    if (dayEntries.length === 0) {
      dayEl.innerHTML = `
        <div class="plan-day-header">
          <span class="day-name">${dayName}</span>
          <span class="day-date">${dayNum} ${monthName}</span>
          ${isToday ? '<span class="today-badge">Aujourd\'hui</span>' : ''}
        </div>
        <div class="plan-day-off-label">Repos</div>`;
    } else {
      const shiftsHTML = dayEntries.map((e) => {
        const hours = computeShiftHours(e.startTime, e.endTime);
        return `
          <div class="shift-card ${STATUS_CLASS[e.status] || 'shift-scheduled'}">
            <div class="shift-card-left">
              <span class="shift-name-lg">${e.shiftName}</span>
              <span class="shift-time-lg">⏰ ${e.startTime} – ${e.endTime}</span>
              ${e.note ? `<span class="shift-note">📝 ${e.note}</span>` : ''}
            </div>
            <div class="shift-card-right">
              <span class="shift-duration">${hours}</span>
              <span class="shift-status-badge ${STATUS_CLASS[e.status]}">${STATUS_LABELS[e.status] || e.status}</span>
            </div>
          </div>`;
      }).join('');

      dayEl.innerHTML = `
        <div class="plan-day-header">
          <span class="day-name">${dayName}</span>
          <span class="day-date">${dayNum} ${monthName}</span>
          ${isToday ? '<span class="today-badge">Aujourd\'hui</span>' : ''}
        </div>
        ${shiftsHTML}`;
    }

    container.appendChild(dayEl);
  }
}

function computeShiftHours(start, end) {
  if (!start || !end) return '';
  const [sh, sm] = start.split(':').map(Number);
  const [eh, em] = end.split(':').map(Number);
  let mins = (eh * 60 + em) - (sh * 60 + sm);
  if (mins < 0) mins += 24 * 60;
  const h = Math.floor(mins / 60);
  const m = mins % 60;
  return m > 0 ? `${h}h${String(m).padStart(2,'0')}` : `${h}h`;
}

function renderWeekSummary(entries, summaryEl) {
  summaryEl.style.display = 'flex';
  const shifts   = entries.length;
  let totalMins  = 0;
  const statuses = entries.map((e) => e.status);

  entries.forEach((e) => {
    const [sh, sm] = e.startTime.split(':').map(Number);
    const [eh, em] = e.endTime.split(':').map(Number);
    let m = (eh * 60 + em) - (sh * 60 + sm);
    if (m < 0) m += 24 * 60;
    totalMins += m;
  });

  const h = Math.floor(totalMins / 60);
  const m = totalMins % 60;
  const hoursStr = m > 0 ? `${h}h${String(m).padStart(2,'0')}` : `${h}h`;

  const hasAbsent = statuses.includes('absent');
  const allConfirmed = statuses.every((s) => s === 'confirmed');

  document.getElementById('sum-hours-val').textContent = hoursStr;
  summaryEl.querySelector('#sum-shifts .sum-num').textContent = shifts;

  const statusChip = document.getElementById('sum-status');
  if (hasAbsent) {
    statusChip.innerHTML = '<span class="sum-num" style="color:var(--red)">⚠️</span><span class="sum-label">Absence</span>';
  } else if (allConfirmed) {
    statusChip.innerHTML = '<span class="sum-num" style="color:var(--green)">✓</span><span class="sum-label">Confirmé</span>';
  } else {
    statusChip.innerHTML = '<span class="sum-num" style="color:var(--muted)">○</span><span class="sum-label">En attente</span>';
  }
}

// ── Export / téléchargement du planning ───────────────────────────────────────
function downloadPlanning() {
  const entries  = PlanState.entries;
  const monday   = PlanState.monday;
  if (!entries || entries.length === 0 || !monday) return;

  const sunday = new Date(monday);
  sunday.setDate(monday.getDate() + 6);

  const opts = { day: 'numeric', month: 'long', year: 'numeric' };
  const weekRange = `${monday.toLocaleDateString('fr-FR', opts)} — ${sunday.toLocaleDateString('fr-FR', opts)}`;

  // Regrouper par date
  const byDate = {};
  entries.forEach((e) => {
    const key = e.date.split('T')[0];
    if (!byDate[key]) byDate[key] = [];
    byDate[key].push(e);
  });

  const lines = [
    `Mon planning — ${State.restaurantName || 'CrewPlan'}`,
    `Semaine du ${weekRange}`,
    '─'.repeat(40),
  ];

  for (let i = 0; i < 7; i++) {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    const key  = formatDate(d);
    const dayEntries = byDate[key] || [];
    const dayLabel = `${DAYS_FR[d.getDay()]} ${d.getDate()} ${MONTHS_FR[d.getMonth()]}`;

    if (dayEntries.length === 0) {
      lines.push(`${dayLabel} : Repos`);
    } else {
      dayEntries.forEach((e) => {
        const hours = computeShiftHours(e.startTime, e.endTime);
        lines.push(`${dayLabel} : ${e.shiftName}  ${e.startTime}–${e.endTime}  (${hours})`);
        if (e.note) lines.push(`  📝 ${e.note}`);
      });
    }
  }

  // Calcul total heures
  let totalMins = 0;
  entries.forEach((e) => {
    const [sh, sm] = e.startTime.split(':').map(Number);
    const [eh, em] = e.endTime.split(':').map(Number);
    let m = (eh * 60 + em) - (sh * 60 + sm);
    if (m < 0) m += 24 * 60;
    totalMins += m;
  });
  const h = Math.floor(totalMins / 60);
  const m = totalMins % 60;
  lines.push('─'.repeat(40));
  lines.push(`Total : ${m > 0 ? `${h}h${String(m).padStart(2,'0')}` : `${h}h`} sur ${entries.length} shift(s)`);

  const text = lines.join('\n');
  const filename = `planning-${formatDate(monday)}.txt`;

  if (navigator.share) {
    navigator.share({ title: `Mon planning — semaine du ${formatDate(monday)}`, text }).catch(() => {});
  } else {
    const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
    const url  = URL.createObjectURL(blob);
    const a    = document.createElement('a');
    a.href     = url;
    a.download = filename;
    a.click();
    URL.revokeObjectURL(url);
  }
}

// ── Toast notifications ────────────────────────────────────────────────────────
function showToast(msg, type = 'info') {
  const t = document.getElementById('toast');
  if (!t) return;
  t.textContent = msg;
  t.className = `toast toast-${type} show`;
  setTimeout(() => t.classList.remove('show'), 3500);
}

// ── Init ──────────────────────────────────────────────────────────────────────
async function init() {
  showView('loading');
  Store.load();

  // restaurantId peut venir de l'URL (QR code) ou du storage
  const params = new URLSearchParams(window.location.search);
  const ridFromURL = params.get('restaurantId');
  if (ridFromURL) {
    State.restaurantId = ridFromURL;
    Store.save();
  }

  // Si restaurantId dans l'URL, essayer de récupérer le nom du restaurant
  if (State.restaurantId) {
    try {
      const r = await API.get(`/restaurants/${State.restaurantId}`);
      State.restaurantName = r.name;
      Store.save();
    } catch { /* nom depuis le storage */ }
  }

  if (State.token && State.user) {
    // Session existante
    try {
      await API.get('/auth/me'); // valider le token
    } catch {
      Store.clear();
      State.token = null;
      State.user = null;
      renderLogin();
      return;
    }
    try {
      await afterLogin();
    } catch (e) {
      console.error('afterLogin', e);
      showView('error');
      const msg = document.getElementById('error-msg');
      if (msg) {
        msg.textContent =
          'Impossible de charger l’application. Vérifiez votre connexion ou reconnectez-vous.';
      }
    }
  } else {
    renderLogin();
  }
}

document.addEventListener('DOMContentLoaded', init);

// ── PWA — Service Worker + Install ───────────────────────────────────────────
let deferredInstall = null;

if ('serviceWorker' in navigator) {
  navigator.serviceWorker
    .register('/sw.js', { updateViaCache: 'none' })
    .then((reg) => {
      // Vérifier une nouvelle version au retour sur l’onglet / l’app installée
      const check = () => {
        if (document.visibilityState === 'visible') reg.update().catch(() => {});
      };
      document.addEventListener('visibilitychange', check);
      window.addEventListener('focus', check);
      // Contrôle périodique (navigateurs ne re-téléchargent pas sw.js tout seuls)
      setInterval(check, 60 * 60 * 1000);

      reg.addEventListener('updatefound', () => {
        const installing = reg.installing;
        if (!installing) return;
        const wasControlled = !!navigator.serviceWorker.controller;
        installing.addEventListener('statechange', () => {
          if (installing.state === 'activated' && wasControlled) {
            window.location.reload();
          }
        });
      });
    })
    .catch(() => {});
}

// Chrome / Android : prompt natif
window.addEventListener('beforeinstallprompt', (e) => {
  e.preventDefault();
  deferredInstall = e;
  showInstallBanner('android');
});

// Après installation réussie
window.addEventListener('appinstalled', () => {
  deferredInstall = null;
  hideInstallBanner();
});

function showInstallBanner(platform) {
  const banner = document.getElementById('install-banner');
  if (!banner) return;
  banner.dataset.platform = platform;
  banner.classList.add('show');
}
function hideInstallBanner() {
  const banner = document.getElementById('install-banner');
  if (banner) banner.classList.remove('show');
}

function triggerInstall() {
  if (deferredInstall) {
    deferredInstall.prompt();
    deferredInstall.userChoice.then(() => { deferredInstall = null; hideInstallBanner(); });
  }
}

// iOS : pas de beforeinstallprompt → on détecte manuellement
const isIOS    = /iphone|ipad|ipod/i.test(navigator.userAgent);
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
const isStandalone = window.matchMedia('(display-mode: standalone)').matches
                  || window.navigator.standalone;

if (isIOS && isSafari && !isStandalone) {
  // Attendre que l'UI soit prête
  document.addEventListener('DOMContentLoaded', () => {
    setTimeout(() => showInstallBanner('ios'), 1500);
  });
}
