import {
  createApiClient,
  createStatusManager,
  escapeHtml,
  getStoredApiKey,
  getStoredDisplayName,
  formatBytes,
  formatDate,
  setStoredApiKey,
  setStoredDisplayName,
} from "./common.js";

const state = {
  apiKey: getStoredApiKey(),
  displayName: getStoredDisplayName(),
  queue: [],
  current: null,
  library: [],
  status: "idle",
};

const elements = {
  status: document.getElementById("status"),
  apiKeyInput: document.getElementById("apiKey"),
  displayNameInput: document.getElementById("displayName"),
  settingsForm: document.getElementById("settingsForm"),
  uploadForm: document.getElementById("uploadForm"),
  fileInput: document.getElementById("musicFile"),
  notesInput: document.getElementById("uploadNotes"),
  permanentCheckbox: document.getElementById("permanentFile"),
  enqueueCheckbox: document.getElementById("enqueueFile"),
  currentTrack: document.getElementById("currentTrack"),
  queueList: document.getElementById("queueList"),
  queueEmpty: document.getElementById("queueEmpty"),
  libraryList: document.getElementById("libraryList"),
  libraryEmpty: document.getElementById("libraryEmpty"),
  refreshBtn: document.getElementById("refreshBtn"),
  pauseResumeBtn: document.getElementById("pauseResumeBtn"),
  playerButtons: document.querySelectorAll("[data-player-action]"),
  heroUploadBtn: document.getElementById("heroUploadBtn"),
  heroQueueBtn: document.getElementById("heroQueueBtn"),
  uploadSection: document.getElementById("uploadSection"),
  queueSection: document.getElementById("queueSection"),
  backHomeBtn: document.getElementById("backHomeBtn"),
};

let pollIntervalId = null;
let refreshPromise = null;

const { setStatus, clearStatus } = createStatusManager(elements.status);
const apiFetch = createApiClient({
  basePath: "/api",
  getApiKey: () => state.apiKey,
});

function refreshAll(options = {}) {
  if (refreshPromise) {
    return refreshPromise;
  }

  refreshPromise = performRefresh(options).finally(() => {
    refreshPromise = null;
  });
  return refreshPromise;
}

async function performRefresh({ silent = false } = {}) {
  if (!silent) {
    clearStatus();
  }

  try {
    const [queueData, libraryData] = await Promise.all([
      apiFetch("/queue"),
      apiFetch("/library"),
    ]);

    state.current = queueData.current;
    state.queue = queueData.upcoming || [];
    state.library = libraryData.tracks || [];
    state.status = queueData.status || "idle";

    renderCurrentTrack();
    renderQueue();
    renderLibrary();
    updatePauseResumeButton();
  } catch (error) {
    setStatus(`Erreur: ${error.message}`, "error", false);
  }
}

function renderCurrentTrack() {
  if (!elements.currentTrack) return;
  if (!state.current) {
    elements.currentTrack.classList.add("player-current--empty");
    elements.currentTrack.innerHTML = "En attente de lecture...";
    return;
  }

  elements.currentTrack.classList.remove("player-current--empty");
  const track = state.current;
  const permanence = track.permanent ? "Permanent" : "Temporaire";
  elements.currentTrack.innerHTML = `
    <div class="media-item__title">${escapeHtml(track.title || track.originalName)}</div>
    <div class="media-item__meta">
      ${permanence} • ${formatBytes(track.size)} • Ajouté par ${escapeHtml(
    track.uploader || "inconnu"
  )}
    </div>
    <div class="media-item__meta">Commencé à ${formatDate(track.createdAt)}</div>
  `;
}

function renderQueue() {
  if (!elements.queueList) return;
  elements.queueList.innerHTML = "";

  if (!state.queue || state.queue.length === 0) {
    elements.queueEmpty.style.display = "block";
    return;
  }

  elements.queueEmpty.style.display = "none";

  state.queue.forEach((track, index) => {
    const li = document.createElement("li");
    li.className = "media-item media-item--queue";
    const permanence = track.permanent ? "Permanent" : "Temporaire";
    li.innerHTML = `
      <div class="media-item__info">
        <div class="media-item__title">${escapeHtml(track.title || track.originalName)}</div>
        <div class="media-item__meta">
          ${permanence} • ${formatBytes(track.size)} • Ajouté par ${escapeHtml(
      track.uploader || "inconnu"
    )}
        </div>
      </div>
      <div class="media-item__actions">
        <button class="btn btn--secondary" data-action="up" data-track="${track.id}">▲</button>
        <button class="btn btn--secondary" data-action="down" data-track="${track.id}">▼</button>
        <button class="btn btn--danger" data-action="remove" data-track="${track.id}">Supprimer</button>
      </div>
    `;

    li.querySelectorAll("button").forEach((btn) => {
      btn.addEventListener("click", (event) => {
        const action = event.currentTarget.dataset.action;
        const trackId = event.currentTarget.dataset.track;
        handleQueueAction(action, trackId, index);
      });
    });

    elements.queueList.appendChild(li);
  });
}

function renderLibrary() {
  if (!elements.libraryList) return;
  elements.libraryList.innerHTML = "";

  if (!state.library || state.library.length === 0) {
    elements.libraryEmpty.style.display = "block";
    return;
  }

  elements.libraryEmpty.style.display = "none";

  state.library.forEach((track) => {
    const li = document.createElement("li");
    li.className = "media-item media-item--library";
    li.innerHTML = `
      <div class="media-item__info">
        <div class="media-item__title">${escapeHtml(track.originalName)}</div>
        <div class="media-item__meta">
          ${formatBytes(track.size)} • Ajouté le ${formatDate(track.createdAt)}
        </div>
      </div>
      <div class="media-item__actions">
        <button class="btn" data-library-action="enqueue" data-library-id="${track.id}">Ajouter</button>
        <button class="btn btn--danger" data-library-action="delete" data-library-id="${track.id}">
          Supprimer
        </button>
      </div>
    `;

    li.querySelectorAll("button").forEach((btn) => {
      btn.addEventListener("click", (event) => {
        const action = event.currentTarget.dataset.libraryAction;
        const libraryId = event.currentTarget.dataset.libraryId;
        handleLibraryAction(action, libraryId);
      });
    });

  elements.libraryList.appendChild(li);
  });
}

function updatePauseResumeButton() {
  if (!elements.pauseResumeBtn) return;
  const normalizedStatus =
    typeof state.status === "string" ? state.status.toLowerCase() : "idle";
  const isPaused = normalizedStatus === "paused";
  const isPlaying = normalizedStatus === "playing";

  if (isPaused) {
    elements.pauseResumeBtn.textContent = "Reprendre";
    elements.pauseResumeBtn.dataset.playerAction = "resume";
  } else {
    elements.pauseResumeBtn.textContent = "Pause";
    elements.pauseResumeBtn.dataset.playerAction = "pause";
  }

  const actionable = isPaused || isPlaying;
  elements.pauseResumeBtn.disabled = !actionable;
}

async function handleQueueAction(action, trackId, index) {
  try {
    if (action === "remove") {
      await apiFetch(`/queue/${trackId}`, { method: "DELETE" });
    } else if (action === "up" || action === "down") {
      const delta = action === "up" ? -1 : 1;
      const newPosition = Math.max(0, Math.min(index + delta, state.queue.length - 1));
      if (newPosition === index) return;
      await apiFetch(`/queue/${trackId}/move`, {
        method: "PATCH",
        body: { position: newPosition },
      });
    }
    await refreshAll({ silent: true });
  } catch (error) {
    setStatus(`Impossible de mettre à jour la file: ${error.message}`, "error");
  }
}

async function handleLibraryAction(action, libraryId) {
  try {
    if (action === "enqueue") {
      await apiFetch(`/library/${libraryId}/enqueue`, {
        method: "POST",
        body: { requestedBy: state.displayName || "web-ui" },
      });
    } else if (action === "delete") {
      if (!confirm("Supprimer ce fichier permanent ?")) {
        return;
      }
      await apiFetch(`/library/${libraryId}`, { method: "DELETE" });
    }
    await refreshAll({ silent: true });
  } catch (error) {
    setStatus(`Action bibliothèque impossible: ${error.message}`, "error");
  }
}

function startPolling() {
  clearInterval(pollIntervalId);
  pollIntervalId = setInterval(() => refreshAll({ silent: true }), 5000);
}

function bindEvents() {
  elements.settingsForm?.addEventListener("submit", (event) => {
    event.preventDefault();
    state.apiKey = elements.apiKeyInput.value.trim();
    state.displayName = elements.displayNameInput.value.trim();
    setStoredApiKey(state.apiKey);
    setStoredDisplayName(state.displayName);
    setStatus("Paramètres sauvegardés", "success");
    refreshAll({ silent: true });
  });

  elements.uploadForm?.addEventListener("submit", async (event) => {
    event.preventDefault();
    const file = elements.fileInput.files[0];
    if (!file) {
      setStatus("Merci de sélectionner un fichier audio", "error");
      return;
    }

    try {
      const data = new FormData();
      data.append("file", file);
      data.append("permanent", elements.permanentCheckbox.checked ? "true" : "false");
      data.append("enqueue", elements.enqueueCheckbox.checked ? "true" : "false");
      if (state.displayName) {
        data.append("uploader", state.displayName);
      }
      if (elements.notesInput.value) {
        data.append("notes", elements.notesInput.value.trim());
      }

      setStatus("Upload en cours...", "info", false);
      await apiFetch("/uploads", { method: "POST", body: data });
      elements.uploadForm.reset();
      elements.enqueueCheckbox.checked = true;
      setStatus("Fichier envoyé avec succès", "success");
      await refreshAll({ silent: true });
    } catch (error) {
      setStatus(`Échec de l'upload: ${error.message}`, "error");
    }
  });

  elements.refreshBtn?.addEventListener("click", () => refreshAll());
  elements.heroUploadBtn?.addEventListener("click", () =>
    elements.uploadSection?.scrollIntoView({ behavior: "smooth" })
  );
  elements.heroQueueBtn?.addEventListener("click", () =>
    elements.queueSection?.scrollIntoView({ behavior: "smooth" })
  );
  elements.backHomeBtn?.addEventListener("click", () => {
    window.location.href = "/";
  });

  elements.playerButtons?.forEach((button) => {
    button.addEventListener("click", async () => {
      const action = button.dataset.playerAction;
      try {
        await apiFetch(`/player/${action}`, { method: "POST" });
        await refreshAll({ silent: true });
      } catch (error) {
        setStatus(`Action player impossible: ${error.message}`, "error");
      }
    });
  });
}

function initialize() {
  elements.apiKeyInput.value = state.apiKey;
  elements.displayNameInput.value = state.displayName;
  bindEvents();
  updatePauseResumeButton();
  refreshAll();
  startPolling();
}

initialize();
