/* =========================================================
   Gestão de Mesas & Reservas — MVP (HTML/CSS/JS puro)
   Persiste em localStorage. Sem dependências.
   ========================================================= */

const STORAGE_KEY = "gestao_restaurante_v1";

/* ---------- Dados de exemplo (planta fixa) ---------- */
// x,y = posição em px dentro da planta (620px de altura).
// seats = lugares; shape 'round' para mesas pequenas.
const SEED_TABLES = [
  { id: "m1",  label: "1",  seats: 2, x: 120, y: 90,  shape: "round" },
  { id: "m2",  label: "2",  seats: 2, x: 260, y: 90,  shape: "round" },
  { id: "m3",  label: "3",  seats: 4, x: 400, y: 80 },
  { id: "m4",  label: "4",  seats: 4, x: 560, y: 80 },
  { id: "m5",  label: "5",  seats: 6, x: 720, y: 90 },
  { id: "m6",  label: "6",  seats: 4, x: 120, y: 250 },
  { id: "m7",  label: "7",  seats: 4, x: 290, y: 250 },
  { id: "m8",  label: "8",  seats: 2, x: 450, y: 260, shape: "round" },
  { id: "m9",  label: "9",  seats: 4, x: 590, y: 250 },
  { id: "m10", label: "10", seats: 6, x: 750, y: 260 },
  { id: "m11", label: "11", seats: 4, x: 150, y: 430 },
  { id: "m12", label: "12", seats: 4, x: 320, y: 430 },
  { id: "m13", label: "13", seats: 8, x: 520, y: 440 },
];

const SEED_RESERVATIONS = [
  { id: "r1", name: "Ana Costa",    party: 2, time: "19:30", phone: "912345678", status: "pending", tableIds: [] },
  { id: "r2", name: "Grupo Empresa", party: 8, time: "20:00", phone: "",          status: "pending", tableIds: [] },
];

/* ---------- Estado ---------- */
let state = load() || {
  tables: structuredClone(SEED_TABLES).map((t) => ({ ...t, groupId: null })),
  reservations: structuredClone(SEED_RESERVATIONS),
};
let selection = new Set(); // ids de mesas selecionadas
let seq = 3; // contador para novos ids de reserva

/* ---------- Persistência ---------- */
function save() {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
}
function load() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    return raw ? JSON.parse(raw) : null;
  } catch {
    return null;
  }
}

/* ---------- Helpers ---------- */
const $ = (sel) => document.querySelector(sel);
const tableById = (id) => state.tables.find((t) => t.id === id);
const seatsOf = (ids) => ids.reduce((s, id) => s + (tableById(id)?.seats || 0), 0);

// Reserva atribuída a uma mesa (se existir)
function reservationForTable(tableId) {
  return state.reservations.find((r) => r.tableIds.includes(tableId));
}

// Estado visual de uma mesa: free | reserved | seated
function tableStatus(tableId) {
  const r = reservationForTable(tableId);
  if (!r) return "free";
  return r.status === "seated" ? "seated" : "reserved";
}

// Todas as mesas que partilham o mesmo grupo
function groupMembers(groupId) {
  if (!groupId) return [];
  return state.tables.filter((t) => t.groupId === groupId);
}

/* =========================================================
   RENDER — Planta
   ========================================================= */
function renderFloor() {
  const floor = $("#floor");
  // remove mesas antigas (mantém as room-labels)
  floor.querySelectorAll(".table").forEach((el) => el.remove());

  state.tables.forEach((t) => {
    const size = 46 + t.seats * 6; // tamanho proporcional aos lugares
    const el = document.createElement("div");
    el.className = "table " + tableStatus(t.id);
    if (t.shape === "round") el.classList.add("round");
    if (t.groupId) el.classList.add("grouped");
    if (selection.has(t.id)) el.classList.add("selected");

    el.style.width = size + "px";
    el.style.height = size + "px";
    el.style.left = t.x + "px";
    el.style.top = t.y + "px";

    const r = reservationForTable(t.id);
    el.innerHTML = `
      <span class="t-num">${t.label}</span>
      <span class="t-seats">${t.seats} lug.</span>
      ${r ? `<span class="t-name">${escapeHtml(r.name)}</span>` : ""}
      ${t.groupId ? `<span class="g-badge">G·${seatsOf(groupMembers(t.groupId).map((m) => m.id))}</span>` : ""}
    `;

    el.addEventListener("click", () => toggleSelect(t.id));
    floor.appendChild(el);
  });
}

/* =========================================================
   RENDER — Toolbar / seleção
   ========================================================= */
function renderToolbar() {
  const ids = [...selection];
  $("#sel-count").textContent = ids.length;
  $("#sel-seats").textContent = seatsOf(ids);

  const anySel = ids.length > 0;
  const anyGrouped = ids.some((id) => tableById(id)?.groupId);
  const anyAssigned = ids.some((id) => reservationForTable(id));

  $("#btn-join").disabled = ids.length < 2;
  $("#btn-split").disabled = !anyGrouped;
  $("#btn-free").disabled = !anyAssigned;
  $("#btn-clear").disabled = !anySel;

  // mostra dica de atribuição quando há mesas livres selecionadas
  $("#assign-hint").hidden = !(anySel && !anyAssigned);
}

/* =========================================================
   RENDER — Listas de reservas
   ========================================================= */
function renderReservations() {
  const pending = state.reservations.filter((r) => r.tableIds.length === 0);
  const active = state.reservations.filter((r) => r.tableIds.length > 0);

  $("#pending-count").textContent = pending.length;
  $("#active-count").textContent = active.length;

  // --- Pendentes ---
  const pl = $("#pending-list");
  pl.innerHTML = "";
  if (pending.length === 0) {
    pl.innerHTML = `<li class="empty">Sem reservas pendentes.</li>`;
  }
  pending.forEach((r) => {
    const canAssign = selection.size > 0;
    const enough = seatsOf([...selection]) >= r.party;
    const li = document.createElement("li");
    li.className = "res-card";
    li.innerHTML = `
      <div class="r-top">
        <span class="r-name">${escapeHtml(r.name)}</span>
        <span>👥 ${r.party}</span>
      </div>
      <div class="r-meta">🕗 ${r.time}${r.phone ? " · 📞 " + escapeHtml(r.phone) : ""}</div>
      <div class="r-actions">
        <button class="btn primary-mini" data-assign="${r.id}" ${canAssign ? "" : "disabled"}>
          ${canAssign ? (enough ? "✓ Atribuir seleção" : "⚠ Atribuir (poucos lug.)") : "Atribuir"}
        </button>
        <button class="btn ghost" data-del="${r.id}">Apagar</button>
      </div>
    `;
    pl.appendChild(li);
  });

  // --- Na sala (atribuídas) ---
  const al = $("#active-list");
  al.innerHTML = "";
  if (active.length === 0) {
    al.innerHTML = `<li class="empty">Ninguém na sala ainda.</li>`;
  }
  active.forEach((r) => {
    const nums = r.tableIds.map((id) => tableById(id)?.label).join(", ");
    const li = document.createElement("li");
    li.className = "res-card " + r.status;
    li.innerHTML = `
      <div class="r-top">
        <span class="r-name">${escapeHtml(r.name)}</span>
        <span>👥 ${r.party}</span>
      </div>
      <div class="r-meta">🕗 ${r.time} · ${r.status === "seated" ? "🔴 Sentados" : "🟡 Reservada"}</div>
      <div class="r-tables">Mesa(s): ${nums}</div>
      <div class="r-actions">
        ${r.status === "reserved"
          ? `<button class="btn" data-seat="${r.id}">Marcar sentados</button>`
          : `<button class="btn" data-unseat="${r.id}">Voltar a reservada</button>`}
        <button class="btn danger" data-clear-res="${r.id}">Libertar mesa</button>
      </div>
    `;
    li.querySelector(".r-tables").addEventListener("click", () => {
      selection = new Set(r.tableIds);
      renderAll();
    });
    al.appendChild(li);
  });
}

/* =========================================================
   AÇÕES
   ========================================================= */
function toggleSelect(id) {
  if (selection.has(id)) selection.delete(id);
  else selection.add(id);
  renderAll();
}

function joinTables() {
  const ids = [...selection];
  if (ids.length < 2) return;
  // reutiliza um groupId existente na seleção, senão cria um novo
  const existing = ids.map((id) => tableById(id).groupId).find(Boolean);
  const gid = existing || "g_" + Date.now();
  ids.forEach((id) => (tableById(id).groupId = gid));
  save();
  renderAll();
}

function splitTables() {
  [...selection].forEach((id) => {
    const t = tableById(id);
    if (t.groupId) {
      // separa também as restantes mesas do mesmo grupo
      groupMembers(t.groupId).forEach((m) => (m.groupId = null));
    }
  });
  save();
  renderAll();
}

function assignReservation(resId) {
  const r = state.reservations.find((x) => x.id === resId);
  if (!r || selection.size === 0) return;

  // se alguma mesa selecionada pertence a um grupo, inclui o grupo inteiro
  const ids = new Set(selection);
  [...selection].forEach((id) => {
    const t = tableById(id);
    if (t.groupId) groupMembers(t.groupId).forEach((m) => ids.add(m.id));
  });

  // valida se as mesas já estão ocupadas por outra reserva
  const conflito = [...ids].find((id) => {
    const other = reservationForTable(id);
    return other && other.id !== resId;
  });
  if (conflito) {
    alert("Mesa " + tableById(conflito).label + " já tem uma reserva atribuída. Liberta-a primeiro.");
    return;
  }

  r.tableIds = [...ids];
  r.status = "reserved";
  selection.clear();
  save();
  renderAll();
}

function freeSelection() {
  // remove atribuições das reservas ligadas às mesas selecionadas
  const ids = [...selection];
  state.reservations.forEach((r) => {
    if (r.tableIds.some((id) => ids.includes(id))) {
      r.tableIds = [];
      r.status = "pending";
    }
  });
  save();
  renderAll();
}

function clearReservation(resId) {
  const r = state.reservations.find((x) => x.id === resId);
  if (!r) return;
  r.tableIds = [];
  r.status = "pending";
  save();
  renderAll();
}

function setSeated(resId, seated) {
  const r = state.reservations.find((x) => x.id === resId);
  if (!r) return;
  r.status = seated ? "seated" : "reserved";
  save();
  renderAll();
}

function deleteReservation(resId) {
  state.reservations = state.reservations.filter((r) => r.id !== resId);
  save();
  renderAll();
}

function addReservation(data) {
  state.reservations.push({
    id: "r" + ++seq + "_" + (state.reservations.length + 1),
    name: data.name.trim(),
    party: Math.max(1, parseInt(data.party, 10) || 1),
    time: data.time,
    phone: (data.phone || "").trim(),
    status: "pending",
    tableIds: [],
  });
  save();
  renderReservations();
}

/* =========================================================
   RENDER geral + eventos
   ========================================================= */
function renderAll() {
  renderFloor();
  renderToolbar();
  renderReservations();
}

function escapeHtml(s) {
  return String(s).replace(/[&<>"']/g, (c) =>
    ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c])
  );
}

// Toolbar
$("#btn-join").addEventListener("click", joinTables);
$("#btn-split").addEventListener("click", splitTables);
$("#btn-free").addEventListener("click", freeSelection);
$("#btn-clear").addEventListener("click", () => { selection.clear(); renderAll(); });

// Delegação de cliques nas listas de reservas
document.addEventListener("click", (e) => {
  const el = e.target.closest("button");
  if (!el) return;
  if (el.dataset.assign) assignReservation(el.dataset.assign);
  else if (el.dataset.del) deleteReservation(el.dataset.del);
  else if (el.dataset.seat) setSeated(el.dataset.seat, true);
  else if (el.dataset.unseat) setSeated(el.dataset.unseat, false);
  else if (el.dataset.clearRes) clearReservation(el.dataset.clearRes);
});

// Formulário de nova reserva
$("#res-form").addEventListener("submit", (e) => {
  e.preventDefault();
  const fd = new FormData(e.target);
  addReservation(Object.fromEntries(fd));
  e.target.reset();
  e.target.querySelector('[name="party"]').value = 2;
});

// Repor dados
$("#btn-reset").addEventListener("click", () => {
  if (!confirm("Repor todos os dados de exemplo? As alterações serão perdidas.")) return;
  localStorage.removeItem(STORAGE_KEY);
  state = {
    tables: structuredClone(SEED_TABLES).map((t) => ({ ...t, groupId: null })),
    reservations: structuredClone(SEED_RESERVATIONS),
  };
  selection.clear();
  renderAll();
});

// Arranque
renderAll();
