import { $ } from '../../core/dom.js';
import { api } from '../../core/api.js';
import { settingsUiState } from '../../state/app-state.js';
import { setStatus } from '../status-bar.js';

/**
 * Whether Types de projet mutations require the Chef password.
 * @returns {boolean}
 */
export function isProjectKindsProtected() {
  return !!settingsUiState.projectKindsLockConfigured;
}

/**
 * Apply lock status payload from the backend.
 * @param {{ configured?: boolean, locked?: boolean } | null | undefined} status
 */
export function applyProjectKindsLockStatus(status) {
  settingsUiState.projectKindsLockConfigured = !!(status && status.configured);
  settingsUiState.projectKindsUnlocked = !settingsUiState.projectKindsLockConfigured;
  syncProjectKindsLockUi();
}

/**
 * Fetch lock status from the backend and refresh the Types de projet chrome.
 * @returns {Promise<{ configured: boolean, locked: boolean }>}
 */
export async function refreshProjectKindsLockStatus() {
  const status = await api("/api/project-kinds/lock");
  applyProjectKindsLockStatus(status);
  return {
    configured: !!settingsUiState.projectKindsLockConfigured,
    locked: !!settingsUiState.projectKindsLockConfigured,
  };
}

/**
 * Update banner / buttons for the Types de projet password protection.
 */
export function syncProjectKindsLockUi() {
  const page = document.querySelector('[data-settings-page="projectKinds"]');
  const banner = $("projectKindsLockBanner");
  const bannerText = $("projectKindsLockBannerText");
  const unlockBtn = $("btnProjectKindsUnlock");
  const setBtn = $("btnProjectKindsSetPassword");
  const relockBtn = $("btnProjectKindsRelock");
  const addBtn = $("btnSubProjectAdd");
  const configured = isProjectKindsProtected();

  if (page instanceof HTMLElement) {
    page.classList.toggle("settings-page--project-kinds-locked", configured);
  }
  if (banner) banner.hidden = false;
  if (bannerText) {
    if (!configured) {
      bannerText.textContent =
        "Aucun mot de passe Chef de projet. Définissez-en un pour empêcher les opérateurs de modifier cette section.";
    } else {
      bannerText.textContent =
        "Section protégée. Chaque modification (ajouter, modifier, supprimer, assigner) demande le mot de passe Chef de projet.";
    }
  }
  if (unlockBtn instanceof HTMLButtonElement) unlockBtn.hidden = true;
  if (relockBtn instanceof HTMLButtonElement) relockBtn.hidden = true;
  if (setBtn instanceof HTMLButtonElement) {
    setBtn.hidden = false;
    setBtn.textContent = configured ? "Changer le mot de passe" : "Protéger cette section";
  }
  if (addBtn instanceof HTMLButtonElement) {
    addBtn.disabled = false;
    addBtn.title = configured
      ? "Ajouter un sous-type (mot de passe Chef de projet demandé)"
      : "Ajouter un sous-type de projet";
  }

  document.querySelectorAll(".kinds-subproject-edit").forEach((btn) => {
    if (!(btn instanceof HTMLButtonElement)) return;
    btn.disabled = false;
    btn.title = configured
      ? "Modifier l'affectation (mot de passe Chef de projet demandé)"
      : btn.getAttribute("data-default-title") || btn.title;
  });

  const editBtn = $("btnProfileEdit");
  const delBtn = $("btnProfileDelete");
  if (editBtn instanceof HTMLButtonElement) editBtn.disabled = false;
  if (delBtn instanceof HTMLButtonElement) delBtn.disabled = false;
}

/**
 * Close the Chef de projet password dialog and resolve any pending prompt.
 * @param {string | null} value
 */
export function closeProjectKindsPasswordPanel(value = null) {
  const resolver = settingsUiState.projectKindsPasswordResolver;
  settingsUiState.projectKindsPasswordResolver = null;
  settingsUiState.projectKindsPasswordMode = null;
  const panel = $("projectKindsPasswordPanel");
  const backdrop = $("projectKindsPasswordBackdrop");
  const input = $("projectKindsPasswordInput");
  const currentWrap = $("projectKindsCurrentPasswordWrap");
  const currentInput = $("projectKindsCurrentPasswordInput");
  const err = $("projectKindsPasswordError");
  if (panel) panel.hidden = true;
  if (backdrop) backdrop.hidden = true;
  if (input instanceof HTMLInputElement) input.value = "";
  if (currentInput instanceof HTMLInputElement) currentInput.value = "";
  if (currentWrap) currentWrap.hidden = true;
  if (err) {
    err.hidden = true;
    err.textContent = "";
  }
  if (typeof resolver === "function") resolver(value);
}

/**
 * Clear the in-memory Chef password reused during this app session.
 */
export function clearSessionChefPassword() {
  settingsUiState.sessionChefPassword = null;
}

/**
 * Whether an API error indicates a missing/wrong Chef password.
 * @param {unknown} error
 * @returns {boolean}
 */
export function isChefPasswordAuthError(error) {
  const msg = String(error && error.message ? error.message : error || "");
  return (
    msg.includes("Mot de passe Chef de projet") ||
    msg.includes("project_kinds_locked") ||
    msg.includes("project_kinds_bad_password")
  );
}

/**
 * Ask for the Chef password before one sensitive action.
 * When `reuseSession` is true, a previously accepted password from this
 * browser/app session is returned without showing the dialog again.
 * @param {string} [message]
 * @param {{ reuseSession?: boolean }} [options]
 * @returns {Promise<string | null>} password or null if cancelled / not required
 */
export function promptChefPasswordForAction(message, options) {
  if (!isProjectKindsProtected()) return Promise.resolve("");
  const reuseSession = !!(options && options.reuseSession);
  if (reuseSession && settingsUiState.sessionChefPassword) {
    return Promise.resolve(settingsUiState.sessionChefPassword);
  }
  return new Promise((resolve) => {
    settingsUiState.projectKindsPasswordResolver = (value) => {
      if (reuseSession && value) {
        settingsUiState.sessionChefPassword = value;
      }
      resolve(value);
    };
    openProjectKindsPasswordPanel("confirm", message);
  });
}

/**
 * Open the password dialog.
 * @param {"confirm"|"set"|"change"} mode
 * @param {string} [message]
 */
export function openProjectKindsPasswordPanel(mode, message) {
  const panel = $("projectKindsPasswordPanel");
  const backdrop = $("projectKindsPasswordBackdrop");
  const titleEl = $("projectKindsPasswordTitle");
  const msgEl = $("projectKindsPasswordMessage");
  const input = $("projectKindsPasswordInput");
  const currentWrap = $("projectKindsCurrentPasswordWrap");
  const currentInput = $("projectKindsCurrentPasswordInput");
  const okBtn = $("btnProjectKindsPasswordOk");
  const err = $("projectKindsPasswordError");
  if (!panel || !backdrop || !(input instanceof HTMLInputElement) || !okBtn) {
    if (typeof settingsUiState.projectKindsPasswordResolver === "function") {
      settingsUiState.projectKindsPasswordResolver(null);
      settingsUiState.projectKindsPasswordResolver = null;
    }
    return;
  }

  settingsUiState.projectKindsPasswordMode = mode;
  if (err) {
    err.hidden = true;
    err.textContent = "";
  }
  input.value = "";
  if (currentInput instanceof HTMLInputElement) currentInput.value = "";

  if (mode === "confirm") {
    if (titleEl) titleEl.textContent = "Mot de passe Chef de projet";
    if (msgEl) {
      msgEl.textContent =
        message ||
        "Saisissez le mot de passe Chef de projet pour confirmer cette modification.";
    }
    if (currentWrap) currentWrap.hidden = true;
    okBtn.textContent = "Confirmer";
  } else if (mode === "change") {
    if (titleEl) titleEl.textContent = "Changer le mot de passe";
    if (msgEl) msgEl.textContent = "Choisissez un nouveau mot de passe Chef de projet (4 caractères minimum).";
    if (currentWrap) currentWrap.hidden = false;
    okBtn.textContent = "Enregistrer";
  } else {
    if (titleEl) titleEl.textContent = "Protéger Types de projet";
    if (msgEl) {
      msgEl.textContent =
        "Définissez un mot de passe Chef de projet. Chaque modification de cette section le demandera ensuite.";
    }
    if (currentWrap) currentWrap.hidden = true;
    okBtn.textContent = "Protéger";
  }

  panel.hidden = false;
  backdrop.hidden = false;
  requestAnimationFrame(() => {
    if (mode === "change" && currentInput instanceof HTMLInputElement) {
      currentInput.focus();
    } else {
      input.focus();
    }
  });
}

/**
 * Submit the password dialog for confirm / set / change.
 * @returns {Promise<void>}
 */
export async function submitProjectKindsPasswordPanel() {
  const mode = settingsUiState.projectKindsPasswordMode || "confirm";
  const input = $("projectKindsPasswordInput");
  const currentInput = $("projectKindsCurrentPasswordInput");
  const err = $("projectKindsPasswordError");
  const password = input instanceof HTMLInputElement ? input.value : "";
  const currentPassword =
    currentInput instanceof HTMLInputElement ? currentInput.value : "";

  const showError = (message) => {
    if (!err) {
      setStatus(message, true);
      return;
    }
    err.hidden = false;
    err.textContent = message;
  };

  const okBtn = $("btnProjectKindsPasswordOk");
  if (okBtn instanceof HTMLButtonElement) okBtn.disabled = true;

  try {
    if (mode === "confirm") {
      if (!password) {
        showError("Mot de passe requis.");
        return;
      }
      // Validate immediately so wrong passwords never open Ajouter / assign flows.
      await api("/api/project-kinds/lock/verify", {
        method: "POST",
        body: JSON.stringify({ password }),
      });
      closeProjectKindsPasswordPanel(password);
      return;
    }
    const body = { password };
    if (mode === "change") body.current_password = currentPassword;
    const status = await api("/api/project-kinds/lock/set", {
      method: "POST",
      body: JSON.stringify(body),
    });
    applyProjectKindsLockStatus(status);
    clearSessionChefPassword();
    closeProjectKindsPasswordPanel(null);
    setStatus(
      mode === "change"
        ? "Mot de passe Chef de projet mis à jour."
        : "Types de projet protégé par mot de passe."
    );
  } catch (e) {
    showError(String(e && e.message ? e.message : e));
  } finally {
    if (okBtn instanceof HTMLButtonElement) okBtn.disabled = false;
  }
}

/**
 * Attach chef_password onto a JSON body when protected.
 * @param {Record<string, unknown>} body
 * @param {string} [password]
 * @returns {Record<string, unknown>}
 */
export function withChefPassword(body, password) {
  const next = body && typeof body === "object" ? { ...body } : {};
  if (password) next.chef_password = password;
  return next;
}

/**
 * Wire banner buttons and password dialog once.
 */
export function initProjectKindsLockUi() {
  $("btnProjectKindsSetPassword")?.addEventListener("click", () => {
    if (settingsUiState.projectKindsLockConfigured) {
      openProjectKindsPasswordPanel("change");
    } else {
      openProjectKindsPasswordPanel("set");
    }
  });
  $("btnProjectKindsPasswordCancel")?.addEventListener("click", () => {
    closeProjectKindsPasswordPanel(null);
  });
  $("projectKindsPasswordBackdrop")?.addEventListener("click", () => {
    closeProjectKindsPasswordPanel(null);
  });
  $("btnProjectKindsPasswordOk")?.addEventListener("click", () => {
    void submitProjectKindsPasswordPanel();
  });
  $("projectKindsPasswordInput")?.addEventListener("keydown", (ev) => {
    if (ev.key === "Enter") {
      ev.preventDefault();
      void submitProjectKindsPasswordPanel();
    }
  });
  $("projectKindsCurrentPasswordInput")?.addEventListener("keydown", (ev) => {
    if (ev.key === "Enter") {
      ev.preventDefault();
      $("projectKindsPasswordInput")?.focus?.();
    }
  });
  syncProjectKindsLockUi();
}
