function slugify(value) {
  return value
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase()
    .replace(/đ/g, "d")
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "");
}

function escapeHtml(value = "") {
  return String(value)
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
}

async function request(url, options = {}) {
  const response = await fetch(url, { headers: { "Content-Type": "application/json" }, ...options });
  if (!response.ok) {
    const text = await response.text();
    try {
      throw new Error(JSON.parse(text).error || text);
    } catch {
      throw new Error(text);
    }
  }
  return response.json();
}

function createNotice(form) {
  const notice = document.createElement("p");
  notice.className = "admin-notice";
  form.prepend(notice);
  return (message, type = "success") => {
    notice.textContent = message;
    notice.dataset.type = type;
  };
}

async function initGameList() {
  const list = document.getElementById("admin-list");
  if (!list) return;
  const games = await request("/api/games");
  list.innerHTML = games
    .sort((a, b) => Number(a.sort) - Number(b.sort))
    .map((game) => `<article class="admin-item">
      <img src="${escapeHtml(game.image)}" alt="${escapeHtml(game.title)}" />
      <div><h3>${escapeHtml(game.title)}</h3><p>${game.active ? "Đang hiển thị" : "Đang ẩn"} · ${game.hot ? "Game hot" : "Thường"} · /game/${escapeHtml(game.slug)}</p></div>
      <div class="mini-actions">
        <a href="/game/${escapeHtml(game.slug)}" target="_blank" rel="noreferrer">Xem</a>
        <a href="/play/${escapeHtml(game.slug)}" target="_blank" rel="noreferrer">Chơi</a>
        <a href="/admin/games/new?edit=${encodeURIComponent(game.id)}">Sửa</a>
        <button type="button" data-game-delete="${escapeHtml(game.id)}">Xóa</button>
      </div>
    </article>`)
    .join("");
  list.querySelectorAll("[data-game-delete]").forEach((button) => {
    button.addEventListener("click", async () => {
      if (!confirm("Xóa game này?")) return;
      await request(`/api/games/${button.dataset.gameDelete}`, { method: "DELETE" });
      await initGameList();
    });
  });
}

async function uploadGameFiles(slug) {
  const input = document.getElementById("gameFiles");
  if (!input?.files.length) return null;
  const formData = new FormData();
  formData.append("slug", slug);
  for (const file of input.files) formData.append("files", file, file.webkitRelativePath || file.name);
  const response = await fetch("/api/games/upload", { method: "POST", body: formData });
  if (!response.ok) throw new Error((await response.json()).error || "Không upload được game.");
  return response.json();
}

async function initGameForm() {
  const form = document.getElementById("game-form");
  if (!form) return;
  const showNotice = createNotice(form);
  const fields = (id) => document.getElementById(id);
  const games = await request("/api/games");
  fields("sort").value = String(games.length + 1);
  const editId = new URLSearchParams(location.search).get("edit");
  if (editId) {
    const game = games.find((item) => item.id === editId);
    if (game) {
      fields("game-id").value = game.id;
      ["title", "slug", "subtitle", "description", "image", "url", "rating", "reviewCount", "sort"].forEach((key) => fields(key).value = game[key]);
      fields("hot").checked = game.hot;
      fields("active").value = String(game.active);
      showNotice(`Đang sửa: ${game.title}`);
    }
  }
  fields("title").addEventListener("input", (event) => {
    if (!fields("game-id").value) {
      const slug = slugify(event.target.value);
      fields("slug").value = slug;
      fields("url").value = `/assets/games/${slug}/index.html`;
    }
  });
  fields("slug").addEventListener("input", (event) => {
    event.target.value = slugify(event.target.value);
    if (!fields("game-id").value) fields("url").value = `/assets/games/${event.target.value}/index.html`;
  });
  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    const id = fields("game-id").value;
    const payload = {
      title: fields("title").value.trim(), slug: fields("slug").value.trim(), subtitle: fields("subtitle").value.trim(),
      description: fields("description").value.trim(), image: fields("image").value.trim(), url: fields("url").value.trim(),
      rating: Number(fields("rating").value || 4.5), reviewCount: Number(fields("reviewCount").value || 1),
      sort: Number(fields("sort").value || 1), hot: fields("hot").checked, active: fields("active").value === "true",
    };
    try {
      const upload = await uploadGameFiles(payload.slug);
      if (upload) payload.url = upload.url;
      await request(id ? `/api/games/${id}` : "/api/games", { method: id ? "PUT" : "POST", body: JSON.stringify(payload) });
      location.href = "/admin/games";
    } catch (error) {
      showNotice(error.message || "Không lưu được game.", "error");
    }
  });
}

async function initPostList() {
  const list = document.getElementById("post-list");
  if (!list) return;
  const posts = await request("/api/posts");
  list.innerHTML = posts
    .sort((a, b) => new Date(b.updatedAt || b.createdAt) - new Date(a.updatedAt || a.createdAt))
    .map((post) => `<article class="admin-item">
      <img src="${escapeHtml(post.image || "/assets/images/hero-bau-cua.png")}" alt="${escapeHtml(post.title)}" />
      <div><h3>${escapeHtml(post.title)}</h3><p>${post.active ? "Đã xuất bản" : "Bản nháp"} · /bai-viet/${escapeHtml(post.slug)}</p></div>
      <div class="mini-actions">
        ${post.active ? `<a href="/bai-viet/${escapeHtml(post.slug)}" target="_blank" rel="noreferrer">Xem</a>` : ""}
        <a href="/admin/posts/new?edit=${encodeURIComponent(post.id)}">Sửa</a>
        <button type="button" data-post-delete="${escapeHtml(post.id)}">Xóa</button>
      </div>
    </article>`)
    .join("") || "<p>Chưa có bài viết.</p>";
  list.querySelectorAll("[data-post-delete]").forEach((button) => {
    button.addEventListener("click", async () => {
      if (!confirm("Xóa bài viết này?")) return;
      await request(`/api/posts/${button.dataset.postDelete}`, { method: "DELETE" });
      await initPostList();
    });
  });
}

async function initPostForm() {
  const form = document.getElementById("post-form");
  if (!form) return;
  const showNotice = createNotice(form);
  const field = (id) => document.getElementById(id);
  const editor = field("post-editor");
  const html = field("post-content");
  const setMode = (mode) => {
    const visual = mode === "visual";
    if (visual) editor.innerHTML = html.value;
    else html.value = editor.innerHTML.trim();
    editor.hidden = !visual;
    html.hidden = visual;
    document.querySelector(".editor-toolbar").hidden = !visual;
    document.querySelectorAll("[data-editor-mode]").forEach((button) => button.classList.toggle("active", button.dataset.editorMode === mode));
  };
  document.querySelectorAll("[data-editor-mode]").forEach((button) => button.addEventListener("click", () => setMode(button.dataset.editorMode)));
  document.querySelectorAll("[data-command]").forEach((button) => button.addEventListener("click", () => {
    let value = button.dataset.value || null;
    if (button.dataset.command === "createLink") value = prompt("Nhập đường dẫn liên kết:", "https://");
    if (button.dataset.command === "insertImage") value = prompt("Nhập đường dẫn ảnh:", "/assets/images/");
    if ((button.dataset.command === "createLink" || button.dataset.command === "insertImage") && !value) return;
    editor.focus();
    document.execCommand(button.dataset.command, false, value);
  }));
  const editId = new URLSearchParams(location.search).get("edit");
  if (editId) {
    const posts = await request("/api/posts");
    const post = posts.find((item) => item.id === editId);
    if (post) {
      field("post-id").value = post.id;
      ["title", "slug", "excerpt", "description", "image"].forEach((key) => field(`post-${key}`).value = post[key] || "");
      field("post-active").value = String(post.active);
      html.value = post.content;
      showNotice(`Đang sửa: ${post.title}`);
    }
  }
  setMode("visual");
  field("post-title").addEventListener("input", (event) => {
    if (!field("post-id").value) field("post-slug").value = slugify(event.target.value);
  });
  field("post-slug").addEventListener("input", (event) => event.target.value = slugify(event.target.value));
  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    html.value = editor.hidden ? html.value : editor.innerHTML.trim();
    const id = field("post-id").value;
    const payload = {
      title: field("post-title").value.trim(), slug: field("post-slug").value.trim(), excerpt: field("post-excerpt").value.trim(),
      description: field("post-description").value.trim(), image: field("post-image").value.trim(), content: html.value.trim(),
      active: field("post-active").value === "true",
    };
    try {
      await request(id ? `/api/posts/${id}` : "/api/posts", { method: id ? "PUT" : "POST", body: JSON.stringify(payload) });
      location.href = "/admin/posts";
    } catch (error) {
      showNotice(error.message || "Không lưu được bài viết.", "error");
    }
  });
}

initGameList().catch(console.error);
initGameForm().catch(console.error);
initPostList().catch(console.error);
initPostForm().catch(console.error);
