// src/lib/onboarding/activation/steps.ts — définition canonique des étapes + helpers purs.

import {
  ACTIVATION_STEP_IDS,
  type ActivationFlags,
  type ActivationSnapshot,
  type ActivationStepDef,
  type ActivationStepId,
} from "./types";

export const ACTIVATION_STEPS: readonly ActivationStepDef[] = [
  { id: "create-site", required: true, href: "/projects" },
  { id: "connect-gsc", required: false, href: "/gsc" },
  { id: "add-keywords", required: true, href: "/keywords/reservoir" },
  { id: "enrich-keywords", required: false, href: "/keywords/reservoir" },
  { id: "target-country", required: true, href: "/keywords/recherche" },
  { id: "invite-teammate", required: false, href: "/settings/team" },
];

/**
 * Étapes portées par le wizard plein écran, dans son ordre d'affichage.
 * Search Console vient tôt : c'est la seule source de données réelles qui ne
 * demande aucune saisie. Elle n'est pour autant jamais bloquante — un site neuf
 * n'a pas de données, et la passer est alors le chemin normal.
 */
export const WIZARD_STEP_IDS = [
  "create-site",
  "connect-gsc",
  "add-keywords",
  "enrich-keywords",
  "target-country",
] as const satisfies readonly ActivationStepId[];

export type WizardStepId = (typeof WIZARD_STEP_IDS)[number];

/**
 * Ordre d'affichage de la checklist : les étapes requises d'abord, les latérales
 * ensuite, l'ordre canonique étant préservé à l'intérieur de chaque groupe.
 *
 * Deux ordres coexistent volontairement, et l'un ne remplace pas l'autre :
 * `ACTIVATION_STEPS` porte l'ordre du parcours guidé, où deux étapes
 * facultatives s'intercalent avant des étapes requises — Search Console juste
 * après la création du site, puis l'enrichissement avant le ciblage pays — parce
 * que c'est l'enchaînement naturel du wizard ; la checklist, elle, ne doit
 * jamais proposer une étape facultative avant une étape requise non faite.
 */
export function checklistSteps(): readonly ActivationStepDef[] {
  return [
    ...ACTIVATION_STEPS.filter((s) => s.required),
    ...ACTIVATION_STEPS.filter((s) => !s.required),
  ];
}

/**
 * Le wizard peut-il ouvrir l'étape « créer le site » ?
 *
 * Trois refus, un seul accord :
 *   - snapshot `null` (dérivation en échec) : on ne sait RIEN, et un formulaire
 *     de création affiché à l'aveugle est un cul-de-sac potentiel ;
 *   - `canCreateSite` faux : `createSiteAction` lèverait `Forbidden`. Proposer
 *     le formulaire à un membre simple, c'est lui promettre une action qu'il ne
 *     peut pas mener ;
 *   - `create-site` déjà vrai : le site existe, l'étape n'a plus d'objet — c'est
 *     ce qui évite au rechargement dur qui suit la création de reboucler sur le
 *     même écran.
 */
export function canEnterSiteStep(snapshot: ActivationSnapshot | null): boolean {
  return Boolean(snapshot?.canCreateSite && !snapshot.flags["create-site"]);
}

/**
 * Le wizard peut-il ouvrir l'étape « Search Console » ?
 *
 * Deux conditions, et AUCUNE n'est un droit : l'étape est facultative
 * (`connect-gsc` est `required: false`), donc son refus ne bloque jamais
 * l'activation — il retire juste un écran qui n'aurait rien à proposer.
 *   - un site accessible : le mapping GSC se fait SUR un site ; sans site, le
 *     sélecteur n'a pas de cible et `connect-gsc` reste faux par construction
 *     (cf. `deriveActivationFlags`, branche `siteId === null`) ;
 *   - `connect-gsc` encore faux : la propriété est déjà mappée sinon, et
 *     l'étape rebouclerait sur elle-même après le rechargement dur qui suit le
 *     mapping.
 * Un snapshot `null` (dérivation en échec) n'ouvre rien : proposer Search
 * Console à l'aveugle ferait payer un appel Google pour un écran peut-être
 * inutile.
 */
export function canEnterGscStep(snapshot: ActivationSnapshot | null): boolean {
  return Boolean(snapshot?.hasAccessibleSite && !snapshot.flags["connect-gsc"]);
}

/**
 * Le wizard peut-il ouvrir l'étape « peupler les mots-clés » ?
 *
 * Mêmes deux conditions que Search Console, pour des raisons différentes :
 *   - un site accessible : les mots-clés se rattachent À un site ; sans site,
 *     `add-keywords` reste faux par construction (cf. `deriveActivationFlags`,
 *     branche `siteId === null`) et l'import n'aurait pas de cible ;
 *   - `add-keywords` encore faux : le réservoir est déjà peuplé sinon, et
 *     l'étape rebouclerait sur elle-même après le rechargement dur qui suit un
 *     ajout.
 * Contrairement à Search Console, cette étape est REQUISE : la refuser ici ne
 * la coche pas pour autant — elle attend simplement dans la checklist
 * d'activation, et le wizard la reproposera au prochain passage.
 */
export function canEnterKeywordsStep(
  snapshot: ActivationSnapshot | null,
): boolean {
  return Boolean(
    snapshot?.hasAccessibleSite && !snapshot.flags["add-keywords"],
  );
}

export function requiredComplete(flags: ActivationFlags): boolean {
  return ACTIVATION_STEPS.every((s) => !s.required || flags[s.id]);
}

export function doneCount(flags: ActivationFlags): number {
  return ACTIVATION_STEP_IDS.filter((id) => flags[id]).length;
}

/**
 * Étape suggérée : la première requise non faite, et seulement si toutes les
 * requises sont faites, la première latérale non faite.
 */
export function firstIncompleteStep(
  flags: ActivationFlags,
): ActivationStepId | null {
  return checklistSteps().find((s) => !flags[s.id])?.id ?? null;
}
