"use client";

import Link from "next/link";
import {
  type ReactNode,
  useDeferredValue,
  useEffect,
  useMemo,
  useState,
} from "react";
import {
  type AdminDashboardData,
  type CatalogStatus,
  type ClientStatus,
  type Difficulty,
  type KnowledgeAdminDashboardData,
  type KnowledgeDocumentRecord,
  type ScenarioGroupMemberRecord,
  metricIds,
  metricMeta,
  type PlatformAdminRecord,
  type ScenarioTemplateRecord,
  type TagRecord,
  type TagStatus,
} from "@/lib/types";

type Props = {
  initialDashboard: AdminDashboardData;
  initialKnowledge?: KnowledgeAdminDashboardData;
  initialPlatformAdmins: PlatformAdminRecord[];
  currentSection: AdminSection;
};

type ScenarioForm = {
  templateId?: string;
  title: string;
  targetSkill: string;
  difficulty: Difficulty;
  shortBrief: string;
  employeeName: string;
  employeeRole: string;
  employeeTeam: string;
  employeeSeniority: string;
  employeeMood: string;
  openingMessage: string;
  managerGoal: string;
  successSignals: string;
  failureSignals: string;
  completionRules: string;
  maxTurns: string;
  tagIds: string[];
  metricWeights: Record<(typeof metricIds)[number], string>;
};

type GroupForm = {
  id?: string;
  name: string;
  description: string;
  status: CatalogStatus;
  companyId: string;
  accessStartDate: string;
  accessEndDate: string;
  tagIds: string[];
  scenarioTemplateIds: string[];
};

type TagForm = {
  id?: string;
  label: string;
  slug: string;
  status: TagStatus;
};

type ClientForm = {
  id?: string;
  name: string;
  slug: string;
  status: ClientStatus;
};

type AdminSection = "scenarios" | "clients" | "groups" | "knowledge";
type GroupEditorTab = "settings" | "scenarios" | "users";

const field =
  "h-9 w-full rounded-md border border-[var(--line)] bg-white px-3 text-sm text-[var(--ink)] outline-none transition focus:border-[var(--primary)] focus:ring-2 focus:ring-[rgba(23,117,186,0.08)]";
const textareaField =
  "w-full rounded-md border border-[var(--line)] bg-white px-3 py-2.5 text-sm text-[var(--ink)] outline-none transition focus:border-[var(--primary)] focus:ring-2 focus:ring-[rgba(23,117,186,0.08)]";
const primaryBtn =
  "inline-flex h-9 items-center justify-center rounded-md bg-[var(--primary)] px-3.5 text-sm font-semibold text-white transition hover:bg-[var(--primary-strong)] disabled:opacity-50";
const secondaryBtn =
  "inline-flex h-9 items-center justify-center rounded-md border border-[var(--line)] bg-white px-3.5 text-sm font-semibold text-[var(--foreground)] transition hover:border-[var(--primary)] hover:text-[var(--primary)] disabled:opacity-50";
const ghostBtn =
  "inline-flex h-9 items-center justify-center rounded-md border border-transparent px-3 text-sm font-semibold text-[var(--foreground)] transition hover:border-[var(--line)] hover:bg-white";
const quietBtn =
  "inline-flex h-8 items-center justify-center rounded-md border border-[var(--line)] bg-white px-3 text-sm font-semibold text-[var(--ink)] transition hover:border-[var(--primary)] hover:text-[var(--primary)]";
const navItemBase =
  "group block border-b border-[var(--line)] px-4 py-4 transition";
const tableHeadCell =
  "bg-[#f8fafc] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]";
const tableCell = "px-4 py-3 align-top text-sm text-[var(--ink)]";
const editorSection =
  "border-b border-[var(--line)] px-4 py-4 last:border-b-0";

function emptyScenario(): ScenarioForm {
  return {
    title: "",
    targetSkill: "",
    difficulty: "Fondamentaux",
    shortBrief: "",
    employeeName: "",
    employeeRole: "",
    employeeTeam: "",
    employeeSeniority: "",
    employeeMood: "",
    openingMessage: "",
    managerGoal: "",
    successSignals: "",
    failureSignals: "",
    completionRules: "",
    maxTurns: "8",
    tagIds: [],
    metricWeights: {
      empathy: "1",
      clarity: "1",
      questioning: "1",
      deescalation: "1",
      accountability: "1",
      action_alignment: "1",
    },
  };
}

function emptyGroup(): GroupForm {
  return {
    name: "",
    description: "",
    status: "draft",
    companyId: "",
    accessStartDate: "",
    accessEndDate: "",
    tagIds: [],
    scenarioTemplateIds: [],
  };
}

function emptyTag(): TagForm {
  return { label: "", slug: "", status: "active" };
}

function emptyClient(): ClientForm {
  return { name: "", slug: "", status: "active" };
}

function normalizeDifficulty(value: string): Difficulty {
  if (
    value === "Intermediaire" ||
    value === "IntermÃ©diaire" ||
    value === "Intermediaire"
  ) {
    return "IntermÃ©diaire" as Difficulty;
  }

  if (value === "Exigeant") {
    return "Exigeant" as Difficulty;
  }

  return "Fondamentaux" as Difficulty;
}

function difficultyFilterValue(value: Difficulty | "all") {
  if (value === "all") {
    return "all";
  }

  if (value === "Fondamentaux") {
    return "Fondamentaux";
  }

  if (value === "Exigeant") {
    return "Exigeant";
  }

  return "Intermediaire";
}

function difficultyLabel(value: Difficulty | null | undefined) {
  if (!value) {
    return "-";
  }

  if (value === "Fondamentaux") {
    return "Fondamentaux";
  }

  if (value === "Exigeant") {
    return "Exigeant";
  }

  return "Intermediaire";
}

function catalogStatusLabel(status: CatalogStatus) {
  switch (status) {
    case "draft":
      return "Brouillon";
    case "published":
      return "Actif";
    case "archived":
      return "Archive";
    default:
      return status;
  }
}

function clientStatusLabel(status: ClientStatus) {
  switch (status) {
    case "active":
      return "Actif";
    case "archived":
      return "Archive";
    default:
      return status;
  }
}

function tagStatusLabel(status: TagStatus) {
  switch (status) {
    case "active":
      return "Actif";
    case "archived":
      return "Archive";
    default:
      return status;
  }
}

function documentStatusLabel(status: KnowledgeDocumentRecord["status"]) {
  switch (status) {
    case "ready":
      return "Pret";
    case "processing":
      return "Indexation";
    case "failed":
      return "Erreur";
    default:
      return status;
  }
}

function statusTone(status: string) {
  switch (status) {
    case "published":
    case "active":
    case "ready":
      return "border-[rgba(47,138,99,0.18)] bg-[rgba(47,138,99,0.10)] text-[var(--success)]";
    case "draft":
    case "processing":
      return "border-[rgba(216,142,4,0.18)] bg-[rgba(216,142,4,0.12)] text-[var(--accent-gold)]";
    case "failed":
      return "border-[rgba(193,22,27,0.16)] bg-[rgba(193,22,27,0.10)] text-[var(--accent-red)]";
    case "archived":
    default:
      return "border-[var(--line)] bg-[#eef2f6] text-[#58636b]";
  }
}

function archivedRowTone(isArchived: boolean) {
  return isArchived ? "bg-[#f1f3f5]" : "bg-white";
}

function scenarioToForm(record: ScenarioTemplateRecord | null): ScenarioForm {
  if (!record) {
    return emptyScenario();
  }

  const scenario = record.draftScenario ?? record.publishedScenario;
  if (!scenario) {
    return {
      ...emptyScenario(),
      templateId: record.id,
      tagIds: record.tags.map((tag) => tag.id),
    };
  }

  return {
    templateId: record.id,
    title: scenario.title,
    targetSkill: scenario.targetSkill,
    difficulty: normalizeDifficulty(scenario.difficulty),
    shortBrief: scenario.shortBrief,
    employeeName: scenario.employeeProfile.name,
    employeeRole: scenario.employeeProfile.role,
    employeeTeam: scenario.employeeProfile.team,
    employeeSeniority: scenario.employeeProfile.seniority,
    employeeMood: scenario.employeeProfile.currentMood,
    openingMessage: scenario.openingMessage,
    managerGoal: scenario.managerGoal,
    successSignals: scenario.successSignals.join("\n"),
    failureSignals: scenario.failureSignals.join("\n"),
    completionRules: scenario.completionRules.join("\n"),
    maxTurns: String(scenario.maxTurns),
    tagIds: record.tags.map((tag) => tag.id),
    metricWeights: {
      empathy: String(scenario.metricWeights.empathy),
      clarity: String(scenario.metricWeights.clarity),
      questioning: String(scenario.metricWeights.questioning),
      deescalation: String(scenario.metricWeights.deescalation),
      accountability: String(scenario.metricWeights.accountability),
      action_alignment: String(scenario.metricWeights.action_alignment),
    },
  };
}

function toggle(values: string[], value: string) {
  return values.includes(value)
    ? values.filter((entry) => entry !== value)
    : [...values, value];
}

function lines(value: string) {
  return value
    .split("\n")
    .map((entry) => entry.trim())
    .filter(Boolean);
}

function toSlug(value: string) {
  return value
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "")
    .slice(0, 120);
}

function isoToDateInput(value: string | null | undefined) {
  return value ? value.slice(0, 10) : "";
}

function dateInputToAccessStart(value: string) {
  return value ? new Date(`${value}T00:00:00.000Z`).toISOString() : null;
}

function dateInputToAccessEnd(value: string) {
  return value ? new Date(`${value}T23:59:59.999Z`).toISOString() : null;
}

function splitEmails(value: string) {
  return [...new Set(
    value
      .split(/[\n,;]+/)
      .map((entry) => entry.trim().toLowerCase())
      .filter(Boolean),
  )];
}

function formatMagicLinkDate(value: string | null) {
  return value ? new Date(value).toLocaleString("fr-FR") : "Jamais";
}

function templateLabel(record: ScenarioTemplateRecord) {
  return (
    record.draftScenario?.title ??
    record.publishedScenario?.title ??
    record.slug
  );
}

function summarizeTags(tags: TagRecord[]) {
  if (tags.length === 0) {
    return "Aucun";
  }

  if (tags.length <= 2) {
    return tags.map((tag) => tag.label).join(", ");
  }

  return `${tags
    .slice(0, 2)
    .map((tag) => tag.label)
    .join(", ")} +${tags.length - 2}`;
}

function compareArchivedLast(
  leftStatus: CatalogStatus | ClientStatus,
  rightStatus: CatalogStatus | ClientStatus,
) {
  const leftArchived = leftStatus === "archived";
  const rightArchived = rightStatus === "archived";

  if (leftArchived === rightArchived) {
    return 0;
  }

  return leftArchived ? 1 : -1;
}

function toggleSelection(values: string[], value: string) {
  return values.includes(value)
    ? values.filter((entry) => entry !== value)
    : [...values, value];
}

function replaceVisibleSelection(
  current: string[],
  visible: string[],
  checked: boolean,
) {
  if (checked) {
    return [...new Set([...current, ...visible])];
  }

  return current.filter((value) => !visible.includes(value));
}

async function request<T>(url: string, body?: unknown) {
  const response = await fetch(url, {
    method: body ? "POST" : "GET",
    cache: "no-store",
    headers: body ? { "Content-Type": "application/json" } : undefined,
    body: body ? JSON.stringify(body) : undefined,
  });

  const payload = (await response.json()) as T | { error?: string };
  if (!response.ok) {
    const errorPayload = payload as { error?: string };
    throw new Error(errorPayload.error ?? "Request failed.");
  }

  return payload as T;
}

function StatusPill({
  status,
  label,
}: {
  status: string;
  label: string;
}) {
  return (
    <span
      className={`inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-semibold ${statusTone(
        status,
      )}`}
    >
      {label}
    </span>
  );
}

function LabeledField({
  label,
  children,
}: {
  label: string;
  children: ReactNode;
}) {
  return (
    <label className="grid gap-1.5">
      <span className="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
        {label}
      </span>
      {children}
    </label>
  );
}

function PaneBlock({
  title,
  description,
  children,
}: {
  title: string;
  description?: string;
  children: ReactNode;
}) {
  return (
    <section className={editorSection}>
      <div className="mb-3">
        <h3 className="text-sm font-semibold text-[var(--ink)]">{title}</h3>
        {description ? (
          <p className="mt-1 text-xs leading-6 text-[var(--foreground)]">
            {description}
          </p>
        ) : null}
      </div>
      {children}
    </section>
  );
}

function AssignmentView({
  label,
  items,
  selected,
  onToggle,
}: {
  label: string;
  items: { id: string; name: string }[];
  selected: string[];
  onToggle: (id: string) => void;
}) {
  return (
    <div className="border border-[var(--line)] bg-white">
      <div className="border-b border-[var(--line)] bg-[#f8fafc] px-3 py-2">
        <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
          {label}
        </p>
      </div>
      <div className="max-h-56 space-y-1 overflow-y-auto p-2">
        {items.length > 0 ? (
          items.map((item) => (
            <label
              key={item.id}
              className="flex items-center gap-3 rounded-md px-2 py-1.5 text-sm text-[var(--foreground)] hover:bg-[#f6f8fb]"
            >
              <input
                type="checkbox"
                checked={selected.includes(item.id)}
                onChange={() => onToggle(item.id)}
              />
              <span>{item.name}</span>
            </label>
          ))
        ) : (
          <p className="px-2 py-2 text-sm text-[var(--foreground)]">
            Aucun element.
          </p>
        )}
      </div>
    </div>
  );
}

function DetailPane({
  title,
  subtitle,
  status,
  onClose,
  actions,
  children,
}: {
  title: string;
  subtitle: string;
  status?: { value: string; label: string };
  onClose: () => void;
  actions?: ReactNode;
  children: ReactNode;
}) {
  return (
    <aside className="h-full border-t border-[var(--line)] bg-[#fbfcfe] xl:border-t-0 xl:border-l">
      <div className="border-b border-[var(--line)] bg-white px-4 py-4">
        <div className="flex items-start justify-between gap-3">
          <div className="min-w-0">
            <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
              Modifier
            </p>
            <h2 className="mt-1 truncate text-lg font-semibold text-[var(--ink)]">
              {title}
            </h2>
            <div className="mt-2 flex flex-wrap items-center gap-2 text-sm text-[var(--foreground)]">
              <span>{subtitle}</span>
              {status ? (
                <StatusPill status={status.value} label={status.label} />
              ) : null}
            </div>
          </div>
          <button className={ghostBtn} type="button" onClick={onClose}>
            Fermer
          </button>
        </div>
        {actions ? <div className="mt-4 flex flex-wrap gap-2">{actions}</div> : null}
      </div>
      <div className="bg-[#fbfcfe]">{children}</div>
    </aside>
  );
}

export function AdminDashboard({
  initialDashboard,
  initialKnowledge,
  initialPlatformAdmins,
  currentSection,
}: Props) {
  const [dashboard, setDashboard] = useState(initialDashboard);
  const [knowledgeDocuments, setKnowledgeDocuments] =
    useState<KnowledgeDocumentRecord[]>(initialKnowledge?.documents ?? []);
  const [platformAdmins, setPlatformAdmins] = useState(initialPlatformAdmins);
  const [busy, setBusy] = useState<string | null>(null);
  const [message, setMessage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const [scenarioSearch, setScenarioSearch] = useState("");
  const [scenarioStatus, setScenarioStatus] =
    useState<"all" | CatalogStatus>("all");
  const [scenarioDifficulty, setScenarioDifficulty] =
    useState<"all" | Difficulty>("all");
  const [scenarioTag, setScenarioTag] = useState("all");

  const [clientSearch, setClientSearch] = useState("");
  const [clientStatus, setClientStatus] =
    useState<"all" | ClientStatus>("all");

  const [groupSearch, setGroupSearch] = useState("");
  const [groupStatus, setGroupStatus] =
    useState<"all" | CatalogStatus>("all");

  const [selectedScenarioId, setSelectedScenarioId] = useState<string | null>(
    null,
  );
  const [selectedGroupId, setSelectedGroupId] = useState<string | null>(null);
  const [selectedTagId, setSelectedTagId] = useState<string | null>(null);
  const [selectedClientId, setSelectedClientId] = useState<string | null>(null);
  const [selectedScenarioIds, setSelectedScenarioIds] = useState<string[]>([]);
  const [selectedClientIds, setSelectedClientIds] = useState<string[]>([]);
  const [selectedGroupIds, setSelectedGroupIds] = useState<string[]>([]);

  const [scenarioEditorOpen, setScenarioEditorOpen] = useState(false);
  const [clientEditorOpen, setClientEditorOpen] = useState(false);
  const [groupEditorOpen, setGroupEditorOpen] = useState(false);
  const [tagCreateOpen, setTagCreateOpen] = useState(false);
  const [groupEditorTab, setGroupEditorTab] = useState<GroupEditorTab>("settings");
  const [scenarioBulkStatus, setScenarioBulkStatus] = useState<
    "" | CatalogStatus
  >("");
  const [scenarioBulkDifficulty, setScenarioBulkDifficulty] = useState<
    "" | Difficulty
  >("");
  const [scenarioBulkTagId, setScenarioBulkTagId] = useState("all");
  const [clientBulkStatus, setClientBulkStatus] = useState<"" | ClientStatus>(
    "",
  );
  const [groupBulkStatus, setGroupBulkStatus] = useState<"" | CatalogStatus>(
    "",
  );
  const [groupBulkTagId, setGroupBulkTagId] = useState("all");

  const [scenarioForm, setScenarioForm] = useState<ScenarioForm>(
    emptyScenario(),
  );
  const [groupForm, setGroupForm] = useState<GroupForm>(emptyGroup());
  const [tagForm, setTagForm] = useState<TagForm>(emptyTag());
  const [clientForm, setClientForm] = useState<ClientForm>(emptyClient());
  const [groupScenarioAccessSearch, setGroupScenarioAccessSearch] = useState("");
  const [groupUserSearch, setGroupUserSearch] = useState("");
  const [groupInviteEmails, setGroupInviteEmails] = useState("");
  const [groupMembersCsvFile, setGroupMembersCsvFile] = useState<File | null>(
    null,
  );
  const [groupMembersUploadKey, setGroupMembersUploadKey] = useState(0);
  const [groupImportReport, setGroupImportReport] = useState<{
    addedCount: number;
    skippedDuplicates: number;
    errors: string[];
  } | null>(null);
  const [knowledgeTitle, setKnowledgeTitle] = useState("");
  const [knowledgeSourceLabel, setKnowledgeSourceLabel] = useState("");
  const [knowledgeFile, setKnowledgeFile] = useState<File | null>(null);
  const [knowledgeUploadKey, setKnowledgeUploadKey] = useState(0);

  const deferredScenarioSearch = useDeferredValue(scenarioSearch);
  const deferredClientSearch = useDeferredValue(clientSearch);
  const deferredGroupSearch = useDeferredValue(groupSearch);
  const deferredGroupScenarioAccessSearch = useDeferredValue(
    groupScenarioAccessSearch,
  );

  const selectedScenario =
    dashboard.scenarios.find((entry) => entry.id === selectedScenarioId) ?? null;
  const selectedGroup =
    dashboard.groups.find((entry) => entry.id === selectedGroupId) ?? null;
  const selectedTag =
    dashboard.tags.find((entry) => entry.id === selectedTagId) ?? null;
  const selectedClient =
    dashboard.clients.find((entry) => entry.id === selectedClientId) ?? null;

  const filteredScenarios = useMemo(
    () =>
      dashboard.scenarios.filter((entry) => {
        const scenario = entry.draftScenario ?? entry.publishedScenario;
        const text = `${entry.slug} ${scenario?.title ?? ""} ${
          scenario?.targetSkill ?? ""
        }`.toLowerCase();

        return (
          text.includes(deferredScenarioSearch.trim().toLowerCase()) &&
          (scenarioStatus === "all" || entry.status === scenarioStatus) &&
          (scenarioDifficulty === "all" ||
            scenario?.difficulty === scenarioDifficulty) &&
          (scenarioTag === "all" ||
            entry.tags.some((tag) => tag.id === scenarioTag))
        );
      }).sort((left, right) => {
        const archivedComparison = compareArchivedLast(
          left.status,
          right.status,
        );

        if (archivedComparison !== 0) {
          return archivedComparison;
        }

        return templateLabel(left).localeCompare(templateLabel(right));
      }),
    [
      dashboard.scenarios,
      deferredScenarioSearch,
      scenarioDifficulty,
      scenarioStatus,
      scenarioTag,
    ],
  );

  const filteredClients = useMemo(
    () =>
      dashboard.clients.filter((client) => {
        const text = `${client.name} ${client.slug}`.toLowerCase();
        return (
          text.includes(deferredClientSearch.trim().toLowerCase()) &&
          (clientStatus === "all" || client.status === clientStatus)
        );
      }).sort((left, right) => {
        const archivedComparison = compareArchivedLast(
          left.status,
          right.status,
        );

        if (archivedComparison !== 0) {
          return archivedComparison;
        }

        return left.name.localeCompare(right.name);
      }),
    [dashboard.clients, deferredClientSearch, clientStatus],
  );

  const filteredGroups = useMemo(
    () =>
      dashboard.groups.filter((group) => {
        const text = `${group.name} ${group.slug} ${group.companyName ?? ""} ${
          group.description ?? ""
        }`.toLowerCase();
        return (
          text.includes(deferredGroupSearch.trim().toLowerCase()) &&
          (groupStatus === "all" || group.status === groupStatus)
        );
      }).sort((left, right) => {
        const archivedComparison = compareArchivedLast(
          left.status,
          right.status,
        );

        if (archivedComparison !== 0) {
          return archivedComparison;
        }

        return left.name.localeCompare(right.name);
      }),
    [dashboard.groups, deferredGroupSearch, groupStatus],
  );

  const publishedGroupScenarios = useMemo(
    () =>
      dashboard.scenarios.filter(
        (scenario) => scenario.status === "published" && scenario.publishedScenario,
      ),
    [dashboard.scenarios],
  );

  const filteredGroupScenarioOptions = useMemo(
    () =>
      publishedGroupScenarios.filter((scenario) => {
        const text = `${templateLabel(scenario)} ${scenario.slug} ${
          scenario.publishedScenario?.targetSkill ?? ""
        }`.toLowerCase();

        return text.includes(
          deferredGroupScenarioAccessSearch.trim().toLowerCase(),
        );
      }),
    [publishedGroupScenarios, deferredGroupScenarioAccessSearch],
  );

  const filteredGroupMembers = useMemo(() => {
    const source = selectedGroup?.members ?? [];
    const query = groupUserSearch.trim().toLowerCase();

    if (!query) {
      return source;
    }

    return source.filter((member) =>
      `${member.email} ${member.fullName ?? ""}`
        .toLowerCase()
        .includes(query),
    );
  }, [groupUserSearch, selectedGroup]);

  const visibleScenarioIds = filteredScenarios.map((entry) => entry.id);
  const visibleClientIds = filteredClients.map((entry) => entry.id);
  const visibleGroupIds = filteredGroups.map((entry) => entry.id);
  const allVisibleScenariosSelected =
    visibleScenarioIds.length > 0 &&
    visibleScenarioIds.every((id) => selectedScenarioIds.includes(id));
  const allVisibleClientsSelected =
    visibleClientIds.length > 0 &&
    visibleClientIds.every((id) => selectedClientIds.includes(id));
  const allVisibleGroupsSelected =
    visibleGroupIds.length > 0 &&
    visibleGroupIds.every((id) => selectedGroupIds.includes(id));

  useEffect(() => {
    setScenarioForm(scenarioToForm(selectedScenario));
  }, [selectedScenario]);

  useEffect(() => {
    setGroupForm(
      selectedGroup
        ? {
            id: selectedGroup.id,
            name: selectedGroup.name,
            description: selectedGroup.description ?? "",
            status: selectedGroup.status,
            companyId: selectedGroup.companyId ?? "",
            accessStartDate: isoToDateInput(selectedGroup.accessStartsAt),
            accessEndDate: isoToDateInput(selectedGroup.accessEndsAt),
            tagIds: selectedGroup.tags.map((tag) => tag.id),
            scenarioTemplateIds: selectedGroup.scenarioTemplateIds,
          }
        : emptyGroup(),
    );
  }, [selectedGroup]);

  useEffect(() => {
    setTagForm(
      selectedTag
        ? {
            id: selectedTag.id,
            label: selectedTag.label,
            slug: selectedTag.slug,
            status: selectedTag.status,
          }
        : emptyTag(),
    );
  }, [selectedTag]);

  useEffect(() => {
    setClientForm(
      selectedClient
        ? {
          id: selectedClient.id,
            name: selectedClient.name,
            slug: selectedClient.slug,
            status: selectedClient.status,
          }
        : emptyClient(),
    );
  }, [selectedClient]);

  useEffect(() => {
    if (!groupEditorOpen) {
      return;
    }

    setGroupEditorTab("settings");
    setGroupScenarioAccessSearch("");
    setGroupUserSearch("");
    setGroupInviteEmails("");
    setGroupMembersCsvFile(null);
    setGroupMembersUploadKey((value) => value + 1);
    setGroupImportReport(null);
  }, [groupEditorOpen, selectedGroupId]);

  useEffect(() => {
    const validIds = new Set(dashboard.scenarios.map((entry) => entry.id));
    setSelectedScenarioIds((current) =>
      current.filter((id) => validIds.has(id)),
    );
  }, [dashboard.scenarios]);

  useEffect(() => {
    const validIds = new Set(dashboard.clients.map((entry) => entry.id));
    setSelectedClientIds((current) =>
      current.filter((id) => validIds.has(id)),
    );
  }, [dashboard.clients]);

  useEffect(() => {
    const validIds = new Set(dashboard.groups.map((entry) => entry.id));
    setSelectedGroupIds((current) =>
      current.filter((id) => validIds.has(id)),
    );
  }, [dashboard.groups]);

  async function refresh(next?: {
    scenarioId?: string | null;
    groupId?: string | null;
    tagId?: string | null;
    clientId?: string | null;
  }) {
    const payload = await request<{
      dashboard: AdminDashboardData;
      platformAdmins: PlatformAdminRecord[];
    }>("/api/admin/dashboard");

    setDashboard(payload.dashboard);
    setPlatformAdmins(payload.platformAdmins);

    if (next?.scenarioId !== undefined) {
      setSelectedScenarioId(next.scenarioId);
    }

    if (next?.groupId !== undefined) {
      setSelectedGroupId(next.groupId);
    }

    if (next?.tagId !== undefined) {
      setSelectedTagId(next.tagId);
    }

    if (next?.clientId !== undefined) {
      setSelectedClientId(next.clientId);
    }
  }

  async function refreshKnowledge() {
    const response = await fetch("/api/admin/knowledge", {
      cache: "no-store",
    });
    const payload = (await response.json()) as
      | { documents: KnowledgeDocumentRecord[] }
      | { error?: string };

    if (!response.ok || !("documents" in payload)) {
      throw new Error(
        "error" in payload && payload.error
          ? payload.error
          : "Le chargement des documents a echoue.",
      );
    }

    setKnowledgeDocuments(payload.documents);
  }

  async function run(name: string, task: () => Promise<void>, ok: string) {
    setBusy(name);
    setMessage(null);
    setError(null);

    try {
      await task();
      setMessage(ok);
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Operation failed.");
    } finally {
      setBusy(null);
    }
  }

  async function saveScenario() {
    const response = await request<{ templateId: string }>(
      "/api/admin/scenarios",
      {
        action: scenarioForm.templateId ? "saveDraft" : "create",
        payload: {
          templateId: scenarioForm.templateId,
          title: scenarioForm.title.trim(),
          targetSkill: scenarioForm.targetSkill.trim(),
          difficulty: normalizeDifficulty(scenarioForm.difficulty),
          shortBrief: scenarioForm.shortBrief.trim(),
          employeeProfile: {
            name: scenarioForm.employeeName.trim(),
            role: scenarioForm.employeeRole.trim(),
            team: scenarioForm.employeeTeam.trim(),
            seniority: scenarioForm.employeeSeniority.trim(),
            currentMood: scenarioForm.employeeMood.trim(),
          },
          openingMessage: scenarioForm.openingMessage.trim(),
          managerGoal: scenarioForm.managerGoal.trim(),
          successSignals: lines(scenarioForm.successSignals),
          failureSignals: lines(scenarioForm.failureSignals),
          completionRules: lines(scenarioForm.completionRules),
          metricWeights: Object.fromEntries(
            metricIds.map((id) => [id, Number(scenarioForm.metricWeights[id])]),
          ) as Record<(typeof metricIds)[number], number>,
          maxTurns: Number(scenarioForm.maxTurns),
          tagIds: scenarioForm.tagIds,
        },
      },
    );

    await refresh({ scenarioId: response.templateId });
  }

  async function saveGroup() {
    if (!groupForm.companyId) {
      throw new Error("Selectionnez une entreprise pour ce groupe.");
    }

    const response = await request<{ groupId: string }>("/api/admin/groups", {
      action: groupForm.id ? "update" : "create",
      payload: {
        id: groupForm.id,
        name: groupForm.name.trim(),
        description: groupForm.description.trim() || null,
        status: groupForm.status,
        companyId: groupForm.companyId,
        accessStartsAt: dateInputToAccessStart(groupForm.accessStartDate),
        accessEndsAt: dateInputToAccessEnd(groupForm.accessEndDate),
        tagIds: groupForm.tagIds,
        scenarioTemplateIds: groupForm.scenarioTemplateIds,
      },
    });

    await refresh({ groupId: response.groupId });
  }

  async function runGroupMemberAdd() {
    if (!selectedGroupId) {
      throw new Error("Sauvegardez d'abord le groupe.");
    }

    const emails = splitEmails(groupInviteEmails);

    if (emails.length === 0) {
      throw new Error("Ajoutez au moins un email.");
    }

    await request("/api/admin/group-members", {
      action: "add",
      groupId: selectedGroupId,
      emails,
    });

    await refresh({ groupId: selectedGroupId });
    setGroupInviteEmails("");
    setGroupImportReport(null);
  }

  async function runGroupMembersCsvImport() {
    if (!selectedGroupId) {
      throw new Error("Sauvegardez d'abord le groupe.");
    }

    if (!groupMembersCsvFile) {
      throw new Error("Selectionnez un fichier CSV.");
    }

    const csvContent = await groupMembersCsvFile.text();
    const response = await request<{
      addedCount: number;
      skippedDuplicates: number;
      errors: string[];
    }>("/api/admin/group-members", {
      action: "importCsv",
      groupId: selectedGroupId,
      fileName: groupMembersCsvFile.name,
      csvContent,
    });

    await refresh({ groupId: selectedGroupId });
    setGroupImportReport(response);
    setGroupMembersCsvFile(null);
    setGroupMembersUploadKey((value) => value + 1);
  }

  async function runGroupMemberRemove(companyMemberId: string) {
    if (!selectedGroupId) {
      throw new Error("Groupe introuvable.");
    }

    await request("/api/admin/group-members", {
      action: "remove",
      groupId: selectedGroupId,
      companyMemberId,
    });

    await refresh({ groupId: selectedGroupId });
  }

  function openScenarioEditor(templateId: string | null) {
    setSelectedScenarioId(templateId);
    setScenarioEditorOpen(true);
  }

  function openClientEditor(clientId: string | null) {
    setSelectedClientId(clientId);
    setClientEditorOpen(true);
  }

  function openGroupEditor(groupId: string | null) {
    setSelectedGroupId(groupId);
    setGroupEditorTab("settings");
    setGroupEditorOpen(true);
  }

  function openTagCreate() {
    setSelectedTagId(null);
    setTagForm(emptyTag());
    setTagCreateOpen(true);
  }

  async function runScenarioBulkEdit() {
    if (selectedScenarioIds.length === 0) {
      throw new Error("Selectionnez au moins un cas pratique.");
    }

    if (
      !scenarioBulkStatus &&
      !scenarioBulkDifficulty &&
      scenarioBulkTagId === "all"
    ) {
      throw new Error("Choisissez au moins une modification de masse.");
    }

    await request("/api/admin/bulk", {
      entity: "scenarios",
      ids: selectedScenarioIds,
      changes: {
        ...(scenarioBulkStatus ? { status: scenarioBulkStatus } : {}),
        ...(scenarioBulkDifficulty
          ? { difficulty: scenarioBulkDifficulty }
          : {}),
        addTagIds: scenarioBulkTagId !== "all" ? [scenarioBulkTagId] : [],
        removeTagIds: [],
      },
    });

    await refresh();
    setSelectedScenarioIds([]);
    setScenarioBulkStatus("");
    setScenarioBulkDifficulty("");
    setScenarioBulkTagId("all");
  }

  async function runScenarioBulkTagRemoval() {
    if (selectedScenarioIds.length === 0) {
      throw new Error("Selectionnez au moins un cas pratique.");
    }

    if (scenarioBulkTagId === "all") {
      throw new Error("Selectionnez un tag a retirer.");
    }

    await request("/api/admin/bulk", {
      entity: "scenarios",
      ids: selectedScenarioIds,
      changes: {
        addTagIds: [],
        removeTagIds: [scenarioBulkTagId],
      },
    });

    await refresh();
    setSelectedScenarioIds([]);
    setScenarioBulkTagId("all");
  }

  async function runClientBulkEdit() {
    if (selectedClientIds.length === 0) {
      throw new Error("Selectionnez au moins un client.");
    }

    if (!clientBulkStatus) {
      throw new Error("Choisissez un statut a appliquer.");
    }

    await request("/api/admin/bulk", {
      entity: "clients",
      ids: selectedClientIds,
      changes: {
        status: clientBulkStatus,
      },
    });

    await refresh();
    setSelectedClientIds([]);
    setClientBulkStatus("");
  }

  async function runGroupBulkEdit() {
    if (selectedGroupIds.length === 0) {
      throw new Error("Selectionnez au moins un groupe.");
    }

    if (!groupBulkStatus && groupBulkTagId === "all") {
      throw new Error("Choisissez au moins une modification de masse.");
    }

    await request("/api/admin/bulk", {
      entity: "groups",
      ids: selectedGroupIds,
      changes: {
        ...(groupBulkStatus ? { status: groupBulkStatus } : {}),
        addTagIds: groupBulkTagId !== "all" ? [groupBulkTagId] : [],
        removeTagIds: [],
      },
    });

    await refresh();
    setSelectedGroupIds([]);
    setGroupBulkStatus("");
    setGroupBulkTagId("all");
  }

  async function runGroupBulkTagRemoval() {
    if (selectedGroupIds.length === 0) {
      throw new Error("Selectionnez au moins un groupe.");
    }

    if (groupBulkTagId === "all") {
      throw new Error("Selectionnez un tag a retirer.");
    }

    await request("/api/admin/bulk", {
      entity: "groups",
      ids: selectedGroupIds,
      changes: {
        addTagIds: [],
        removeTagIds: [groupBulkTagId],
      },
    });

    await refresh();
    setSelectedGroupIds([]);
    setGroupBulkTagId("all");
  }

  const navigation = [
    {
      id: "scenarios" as const,
      title: "Cas pratiques",
      description: "Catalogue, filtres et edition laterale",
    },
    {
      id: "clients" as const,
      title: "Clients",
      description: "Comptes, acces et affectations",
    },
    {
      id: "groups" as const,
      title: "Groupes",
      description: "Groupes reutilisables et diffusion",
    },
    {
      id: "knowledge" as const,
      title: "Base de connaissances",
      description: "Documents et indexation du coach",
    },
  ];

  function renderScenarioSection() {
    return (
      <section className="bg-white">
        <div className="border-b border-[var(--line)] bg-white px-4 py-4">
          <div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:justify-between">
            <div className="min-w-0">
              <div className="flex items-center gap-3 overflow-x-auto whitespace-nowrap">
                <p className="shrink-0 text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
                  Cas pratiques
                </p>
                <p className="truncate text-sm text-[var(--foreground)]">
                  Admins actifs:{" "}
                  {platformAdmins.map((admin) => admin.fullName ?? admin.email).join(", ") ||
                    "aucun"}
                </p>
              </div>
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <button
                className={secondaryBtn}
                type="button"
                onClick={() => run("refresh", () => refresh(), "Dashboard actualise.")}
              >
                {busy === "refresh" ? "Actualisation..." : "Rafraichir"}
              </button>
              <button
                className={primaryBtn}
                type="button"
                onClick={() => openScenarioEditor(null)}
              >
                Nouveau cas pratique
              </button>
            </div>
          </div>
        </div>

        <div className="relative xl:min-h-[calc(100dvh-49px)]">
          <div className="min-w-0">
            <div className="border-b border-[var(--line)] bg-[#f8fafc] px-4 py-3">
              <div className="grid gap-2 xl:grid-cols-[260px_180px_180px_180px_minmax(0,1fr)] xl:items-center">
                <div className="flex items-center gap-3">
                  <h2 className="text-base font-semibold text-[var(--ink)]">
                    Cas pratiques
                  </h2>
                  <span className="rounded-full bg-[#eef2f6] px-2.5 py-1 text-xs font-semibold text-[#51606b]">
                    {filteredScenarios.length}
                  </span>
                </div>
                <input
                  className={field}
                  placeholder="Rechercher par nom"
                  value={scenarioSearch}
                  onChange={(event) => setScenarioSearch(event.target.value)}
                />
                <select
                  className={field}
                  value={difficultyFilterValue(scenarioDifficulty)}
                  onChange={(event) =>
                    setScenarioDifficulty(
                      event.target.value === "all"
                        ? "all"
                        : normalizeDifficulty(event.target.value),
                    )
                  }
                >
                  <option value="all">Toutes difficultes</option>
                  <option value="Fondamentaux">Fondamentaux</option>
                  <option value="Intermediaire">Intermediaire</option>
                  <option value="Exigeant">Exigeant</option>
                </select>
                <select
                  className={field}
                  value={scenarioStatus}
                  onChange={(event) =>
                    setScenarioStatus(event.target.value as "all" | CatalogStatus)
                  }
                >
                  <option value="all">Tous statuts</option>
                  <option value="draft">Brouillon</option>
                  <option value="published">Actif</option>
                  <option value="archived">Archive</option>
                </select>
                <select
                  className={field}
                  value={scenarioTag}
                  onChange={(event) => setScenarioTag(event.target.value)}
                >
                  <option value="all">Tous tags</option>
                  {dashboard.tags.map((tag) => (
                    <option key={tag.id} value={tag.id}>
                      {tag.label}
                    </option>
                  ))}
                </select>
              </div>
            </div>

            {selectedScenarioIds.length > 0 ? (
              <div className="border-b border-[var(--line)] bg-[#eef5fb] px-4 py-3">
                <div className="flex items-center gap-4 overflow-x-auto whitespace-nowrap">
                  <div className="flex shrink-0 items-center gap-3">
                    <span className="rounded-full bg-white px-2.5 py-1 text-xs font-semibold text-[var(--primary)]">
                      {selectedScenarioIds.length} selectionnes
                    </span>
                    <p className="text-sm text-[var(--foreground)]">
                      Modification de masse
                    </p>
                  </div>
                  <div className="ml-auto flex shrink-0 items-center gap-2">
                    <select
                      className={`${field} min-w-[150px]`}
                      value={scenarioBulkStatus}
                      onChange={(event) =>
                        setScenarioBulkStatus(
                          event.target.value as "" | CatalogStatus,
                        )
                      }
                    >
                      <option value="">Statut</option>
                      <option value="draft">Brouillon</option>
                      <option value="published">Actif</option>
                      <option value="archived">Archive</option>
                    </select>
                    <select
                      className={`${field} min-w-[170px]`}
                      value={difficultyFilterValue(
                        scenarioBulkDifficulty || "all",
                      )}
                      onChange={(event) =>
                        setScenarioBulkDifficulty(
                          event.target.value === "all"
                            ? ""
                            : normalizeDifficulty(event.target.value),
                        )
                      }
                    >
                      <option value="all">Difficulte</option>
                      <option value="Fondamentaux">Fondamentaux</option>
                      <option value="Intermediaire">Intermediaire</option>
                      <option value="Exigeant">Exigeant</option>
                    </select>
                    <select
                      className={`${field} min-w-[150px]`}
                      value={scenarioBulkTagId}
                      onChange={(event) => setScenarioBulkTagId(event.target.value)}
                    >
                      <option value="all">Tag</option>
                      {dashboard.tags.map((tag) => (
                        <option key={tag.id} value={tag.id}>
                          {tag.label}
                        </option>
                      ))}
                    </select>
                    <button
                      className={secondaryBtn}
                      type="button"
                      onClick={() =>
                        run(
                          "scenario-bulk-apply",
                          runScenarioBulkEdit,
                          "Modification de masse appliquee.",
                        )
                      }
                    >
                      {busy === "scenario-bulk-apply"
                        ? "Application..."
                        : "Appliquer"}
                    </button>
                    <button
                      className={secondaryBtn}
                      type="button"
                      onClick={() =>
                        run(
                          "scenario-bulk-remove-tag",
                          runScenarioBulkTagRemoval,
                          "Tag retire de la selection.",
                        )
                      }
                    >
                      {busy === "scenario-bulk-remove-tag"
                        ? "Retrait..."
                        : "Retirer tag"}
                    </button>
                    <button
                      className={ghostBtn}
                      type="button"
                      onClick={() => setSelectedScenarioIds([])}
                    >
                      Annuler
                    </button>
                  </div>
                </div>
              </div>
            ) : null}

            <div className="overflow-x-auto">
              <table className="min-w-full border-collapse">
                <thead>
                  <tr className="border-b border-[var(--line)]">
                    <th className={`${tableHeadCell} w-[54px]`}>
                      <input
                        type="checkbox"
                        aria-label="Selectionner les cas pratiques visibles"
                        checked={allVisibleScenariosSelected}
                        onChange={(event) =>
                          setSelectedScenarioIds((current) =>
                            replaceVisibleSelection(
                              current,
                              visibleScenarioIds,
                              event.target.checked,
                            ),
                          )
                        }
                      />
                    </th>
                    <th className={tableHeadCell}>Nom</th>
                    <th className={tableHeadCell}>Difficulte</th>
                    <th className={tableHeadCell}>Statut</th>
                    <th className={tableHeadCell}>Tags</th>
                    <th className={`${tableHeadCell} w-[150px] text-right`}>
                      Action
                    </th>
                  </tr>
                </thead>
                <tbody>
                  {filteredScenarios.length > 0 ? (
                    filteredScenarios.map((entry) => {
                      const scenario =
                        entry.draftScenario ?? entry.publishedScenario;
                      const selected =
                        scenarioEditorOpen && selectedScenarioId === entry.id;
                      const checked = selectedScenarioIds.includes(entry.id);
                      const baseRowTone = archivedRowTone(entry.status === "archived");

                      return (
                        <tr
                          key={entry.id}
                          className={`border-b border-[var(--line)] transition hover:bg-[#f8fbff] ${
                            selected ? "bg-[rgba(23,117,186,0.06)]" : baseRowTone
                          }`}
                          onClick={() => setSelectedScenarioId(entry.id)}
                        >
                          <td className={tableCell}>
                            <input
                              type="checkbox"
                              aria-label={`Selectionner ${templateLabel(entry)}`}
                              checked={checked}
                              onChange={() =>
                                setSelectedScenarioIds((current) =>
                                  toggleSelection(current, entry.id),
                                )
                              }
                              onClick={(event) => event.stopPropagation()}
                            />
                          </td>
                          <td
                            className={`${tableCell} ${
                              scenarioEditorOpen ? "w-[30%] max-w-0" : "w-[42%]"
                            }`}
                          >
                            <div className="min-w-0">
                              <p className="truncate font-semibold text-[var(--ink)]">
                                {templateLabel(entry)}
                              </p>
                              <p className="mt-1 truncate text-xs text-[var(--foreground)]">
                                {entry.slug}
                                {scenario?.targetSkill
                                  ? ` - ${scenario.targetSkill}`
                                  : ""}
                              </p>
                            </div>
                          </td>
                          <td className={tableCell}>
                            {difficultyLabel(scenario?.difficulty)}
                          </td>
                          <td className={tableCell}>
                            <StatusPill
                              status={entry.status}
                              label={catalogStatusLabel(entry.status)}
                            />
                          </td>
                          <td className={tableCell}>
                            <span className="text-[var(--foreground)]">
                              {summarizeTags(entry.tags)}
                            </span>
                          </td>
                          <td className={`${tableCell} text-right`}>
                            <button
                              className={quietBtn}
                              type="button"
                              onClick={(event) => {
                                event.stopPropagation();
                                openScenarioEditor(entry.id);
                              }}
                            >
                              Modifier
                            </button>
                          </td>
                        </tr>
                      );
                    })
                  ) : (
                    <tr>
                      <td
                        className="px-4 py-10 text-center text-sm text-[var(--foreground)]"
                        colSpan={6}
                      >
                        Aucun cas pratique ne correspond aux filtres.
                      </td>
                    </tr>
                  )}
                </tbody>
              </table>
            </div>
          </div>

          {scenarioEditorOpen ? (
            <div className="xl:absolute xl:inset-y-0 xl:right-0 xl:z-20 xl:w-[70%]">
              <div className="xl:h-full xl:min-h-[calc(100dvh-49px)] xl:overflow-y-auto xl:border-l xl:border-[var(--line)] xl:bg-[#fbfcfe]">
                <DetailPane
                  title={
                    selectedScenario ? templateLabel(selectedScenario) : "Nouveau cas pratique"
                  }
                  subtitle={
                    selectedScenario
                      ? `${selectedScenario.slug}`
                      : "Creation d'un nouveau cas pratique"
                  }
                  status={
                    selectedScenario
                      ? {
                          value: selectedScenario.status,
                          label: catalogStatusLabel(selectedScenario.status),
                        }
                      : undefined
                  }
                  onClose={() => setScenarioEditorOpen(false)}
                  actions={
                    <>
                      <button
                        className={primaryBtn}
                        type="button"
                        onClick={() =>
                          run(
                            "scenario-save",
                            saveScenario,
                            "Cas pratique sauvegarde.",
                          )
                        }
                      >
                        {busy === "scenario-save" ? "Sauvegarde..." : "Sauvegarder"}
                      </button>
                      <button
                        className={secondaryBtn}
                        type="button"
                        disabled={!selectedScenarioId}
                        onClick={() =>
                          run(
                            "scenario-publish",
                            async () => {
                              await request("/api/admin/scenarios", {
                                action: "publish",
                                templateId: selectedScenarioId,
                              });
                              await refresh({ scenarioId: selectedScenarioId });
                            },
                            "Cas pratique publie.",
                          )
                        }
                      >
                        {busy === "scenario-publish" ? "Publication..." : "Publier"}
                      </button>
                      <button
                        className={secondaryBtn}
                        type="button"
                        disabled={!selectedScenarioId}
                        onClick={() =>
                          run(
                            "scenario-archive",
                            async () => {
                              await request("/api/admin/scenarios", {
                                action: "archive",
                                templateId: selectedScenarioId,
                              });
                              await refresh({ scenarioId: selectedScenarioId });
                            },
                            "Cas pratique archive.",
                          )
                        }
                      >
                        {busy === "scenario-archive" ? "Archivage..." : "Archiver"}
                      </button>
                    </>
                  }
                >
              <PaneBlock title="Identite" description="Fiche generale du cas pratique.">
                <div className="grid gap-3">
                  <LabeledField label="Titre">
                    <input
                      className={field}
                      value={scenarioForm.title}
                      onChange={(event) =>
                        setScenarioForm((value) => ({
                          ...value,
                          title: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                  <div className="grid gap-3 md:grid-cols-3">
                    <LabeledField label="Difficulte">
                      <select
                        className={field}
                        value={difficultyFilterValue(scenarioForm.difficulty)}
                        onChange={(event) =>
                          setScenarioForm((value) => ({
                            ...value,
                            difficulty: normalizeDifficulty(event.target.value),
                          }))
                        }
                      >
                        <option value="Fondamentaux">Fondamentaux</option>
                        <option value="Intermediaire">Intermediaire</option>
                        <option value="Exigeant">Exigeant</option>
                      </select>
                    </LabeledField>
                    <LabeledField label="Skill cible">
                      <input
                        className={field}
                        value={scenarioForm.targetSkill}
                        onChange={(event) =>
                          setScenarioForm((value) => ({
                            ...value,
                            targetSkill: event.target.value,
                          }))
                        }
                      />
                    </LabeledField>
                    <LabeledField label="Nombre de tours">
                      <input
                        className={field}
                        type="number"
                        min={1}
                        max={20}
                        value={scenarioForm.maxTurns}
                        onChange={(event) =>
                          setScenarioForm((value) => ({
                            ...value,
                            maxTurns: event.target.value,
                          }))
                        }
                      />
                    </LabeledField>
                  </div>
                  <LabeledField label="Brief">
                    <textarea
                      className={textareaField}
                      rows={4}
                      value={scenarioForm.shortBrief}
                      onChange={(event) =>
                        setScenarioForm((value) => ({
                          ...value,
                          shortBrief: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                </div>
              </PaneBlock>
              <PaneBlock
                title="Collaborateur"
                description="Profil de la personne simulee dans le cas pratique."
              >
                <div className="grid gap-3">
                  <div className="grid gap-3 md:grid-cols-2">
                    <LabeledField label="Nom">
                      <input
                        className={field}
                        value={scenarioForm.employeeName}
                        onChange={(event) =>
                          setScenarioForm((value) => ({
                            ...value,
                            employeeName: event.target.value,
                          }))
                        }
                      />
                    </LabeledField>
                    <LabeledField label="Role">
                      <input
                        className={field}
                        value={scenarioForm.employeeRole}
                        onChange={(event) =>
                          setScenarioForm((value) => ({
                            ...value,
                            employeeRole: event.target.value,
                          }))
                        }
                      />
                    </LabeledField>
                  </div>
                  <div className="grid gap-3 md:grid-cols-2">
                    <LabeledField label="Equipe">
                      <input
                        className={field}
                        value={scenarioForm.employeeTeam}
                        onChange={(event) =>
                          setScenarioForm((value) => ({
                            ...value,
                            employeeTeam: event.target.value,
                          }))
                        }
                      />
                    </LabeledField>
                    <LabeledField label="Anciennete">
                      <input
                        className={field}
                        value={scenarioForm.employeeSeniority}
                        onChange={(event) =>
                          setScenarioForm((value) => ({
                            ...value,
                            employeeSeniority: event.target.value,
                          }))
                        }
                      />
                    </LabeledField>
                  </div>
                  <LabeledField label="Humeur actuelle">
                    <textarea
                      className={textareaField}
                      rows={3}
                      value={scenarioForm.employeeMood}
                      onChange={(event) =>
                        setScenarioForm((value) => ({
                          ...value,
                          employeeMood: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                </div>
              </PaneBlock>

              <PaneBlock
                title="Dialogue et cadrage"
                description="Message d'ouverture et reussite du scenario."
              >
                <div className="grid gap-3">
                  <LabeledField label="Message d'ouverture">
                    <textarea
                      className={textareaField}
                      rows={4}
                      value={scenarioForm.openingMessage}
                      onChange={(event) =>
                        setScenarioForm((value) => ({
                          ...value,
                          openingMessage: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                  <LabeledField label="Objectif manager">
                    <textarea
                      className={textareaField}
                      rows={4}
                      value={scenarioForm.managerGoal}
                      onChange={(event) =>
                        setScenarioForm((value) => ({
                          ...value,
                          managerGoal: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                  <LabeledField label="Success signals">
                    <textarea
                      className={textareaField}
                      rows={5}
                      value={scenarioForm.successSignals}
                      onChange={(event) =>
                        setScenarioForm((value) => ({
                          ...value,
                          successSignals: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                  <LabeledField label="Failure signals">
                    <textarea
                      className={textareaField}
                      rows={5}
                      value={scenarioForm.failureSignals}
                      onChange={(event) =>
                        setScenarioForm((value) => ({
                          ...value,
                          failureSignals: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                  <LabeledField label="Completion rules">
                    <textarea
                      className={textareaField}
                      rows={5}
                      value={scenarioForm.completionRules}
                      onChange={(event) =>
                        setScenarioForm((value) => ({
                          ...value,
                          completionRules: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                </div>
              </PaneBlock>

              <PaneBlock title="Tags et metriques">
                <div className="grid gap-4">
                  <div>
                    <div className="mb-2 flex flex-wrap items-center justify-between gap-2">
                      <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
                        Tags
                      </p>
                      <button
                        className={quietBtn}
                        type="button"
                        onClick={openTagCreate}
                      >
                        Creer un tag
                      </button>
                    </div>
                    <div className="flex flex-wrap gap-2">
                      {dashboard.tags.map((tag) => {
                        const active = scenarioForm.tagIds.includes(tag.id);
                        return (
                          <button
                            key={tag.id}
                            className={
                              active
                                ? "rounded-full bg-[var(--primary)] px-3 py-1.5 text-xs font-semibold text-white"
                                : "rounded-full border border-[var(--line)] bg-white px-3 py-1.5 text-xs font-semibold text-[var(--foreground)]"
                            }
                            type="button"
                            onClick={() =>
                              setScenarioForm((value) => ({
                                ...value,
                                tagIds: toggle(value.tagIds, tag.id),
                              }))
                            }
                          >
                            {tag.label}
                          </button>
                        );
                      })}
                    </div>
                    {tagCreateOpen ? (
                      <div className="mt-3 border border-[var(--line)] bg-[#f8fafc] p-3">
                        <div className="grid gap-3 md:grid-cols-[minmax(0,1fr)_180px_auto_auto] md:items-end">
                          <LabeledField label="Nouveau tag">
                            <input
                              className={field}
                              value={tagForm.label}
                              placeholder="Nom du tag"
                              onChange={(event) =>
                                setTagForm((value) => ({
                                  ...value,
                                  label: event.target.value,
                                  slug: toSlug(event.target.value),
                                  status: "active",
                                }))
                              }
                            />
                          </LabeledField>
                          <LabeledField label="Slug">
                            <input
                              className={field}
                              value={tagForm.slug}
                              placeholder="slug-tag"
                              onChange={(event) =>
                                setTagForm((value) => ({
                                  ...value,
                                  slug: toSlug(event.target.value),
                                }))
                              }
                            />
                          </LabeledField>
                          <button
                            className={primaryBtn}
                            type="button"
                            disabled={!tagForm.label.trim() || !tagForm.slug.trim()}
                            onClick={() =>
                              run(
                                "scenario-tag-create",
                                async () => {
                                  const response = await request<{ tagId: string }>(
                                    "/api/admin/tags",
                                    {
                                      action: "create",
                                      payload: {
                                        label: tagForm.label.trim(),
                                        slug: toSlug(tagForm.slug.trim()),
                                        status: "active",
                                      },
                                    },
                                  );
                                  await refresh();
                                  setScenarioForm((value) => ({
                                    ...value,
                                    tagIds: [...new Set([...value.tagIds, response.tagId])],
                                  }));
                                  setTagForm(emptyTag());
                                  setTagCreateOpen(false);
                                },
                                "Tag cree et ajoute au cas pratique.",
                              )
                            }
                          >
                            {busy === "scenario-tag-create" ? "Creation..." : "Ajouter"}
                          </button>
                          <button
                            className={secondaryBtn}
                            type="button"
                            onClick={() => {
                              setTagForm(emptyTag());
                              setTagCreateOpen(false);
                            }}
                          >
                            Annuler
                          </button>
                        </div>
                      </div>
                    ) : null}
                  </div>
                  <div className="overflow-x-auto rounded-md border border-[var(--line)] bg-white">
                    <div className="grid min-w-[780px] grid-cols-6">
                      {metricIds.map((id) => (
                        <div
                          key={`${id}-label`}
                          className="border-b border-r border-[var(--line)] px-3 py-3 text-center text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280] last:border-r-0"
                        >
                          {metricMeta[id].label}
                        </div>
                      ))}
                      {metricIds.map((id) => (
                        <div
                          key={id}
                          className="border-r border-[var(--line)] p-3 last:border-r-0"
                        >
                          <input
                            className={`${field} text-center`}
                            type="number"
                            min={0}
                            max={3}
                            step="0.05"
                            value={scenarioForm.metricWeights[id]}
                            onChange={(event) =>
                              setScenarioForm((value) => ({
                                ...value,
                                metricWeights: {
                                  ...value.metricWeights,
                                  [id]: event.target.value,
                                },
                              }))
                            }
                          />
                        </div>
                      ))}
                    </div>
                  </div>
                </div>
              </PaneBlock>
                </DetailPane>
              </div>
            </div>
          ) : null}
        </div>

        {false ? (
          <div className="border-t border-[var(--line)]">
          <div className="grid xl:grid-cols-[280px_minmax(0,1fr)]">
            <div className="border-b border-[var(--line)] bg-[#f8fafc] px-4 py-4 xl:border-b-0 xl:border-r">
              <div className="flex items-center justify-between gap-3">
                <div>
                  <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
                    Taxonomie
                  </p>
                  <h2 className="mt-1 text-base font-semibold text-[var(--ink)]">
                    Tags
                  </h2>
                </div>
                <button
                  className={quietBtn}
                  type="button"
                  onClick={() => setSelectedTagId(null)}
                >
                  Nouveau tag
                </button>
              </div>
              <div className="mt-4 space-y-1">
                {dashboard.tags.map((tag) => (
                  <button
                    key={tag.id}
                    className={`block w-full border px-3 py-2 text-left text-sm transition ${
                      selectedTagId === tag.id
                        ? "border-[rgba(23,117,186,0.22)] bg-[rgba(23,117,186,0.08)]"
                        : "border-[var(--line)] bg-white hover:bg-[#f6f8fb]"
                    }`}
                    type="button"
                    onClick={() => setSelectedTagId(tag.id)}
                  >
                    <div className="flex items-center justify-between gap-3">
                      <span className="font-semibold text-[var(--ink)]">
                        {tag.label}
                      </span>
                      <StatusPill
                        status={tag.status}
                        label={tagStatusLabel(tag.status)}
                      />
                    </div>
                    <p className="mt-1 text-xs text-[var(--foreground)]">
                      {tag.scenarioCount} cas · {tag.groupCount} groupes
                    </p>
                  </button>
                ))}
              </div>
            </div>

            <div className="px-4 py-4">
              <div className="max-w-xl">
                <div className="mb-4">
                  <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
                    Edition
                  </p>
                  <h3 className="mt-1 text-base font-semibold text-[var(--ink)]">
                    {selectedTag?.label ?? "Nouveau tag"}
                  </h3>
                </div>
                <div className="grid gap-3">
                  <LabeledField label="Libelle">
                    <input
                      className={field}
                      value={tagForm.label}
                      onChange={(event) =>
                        setTagForm((value) => ({
                          ...value,
                          label: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                  <LabeledField label="Slug">
                    <input
                      className={field}
                      value={tagForm.slug}
                      onChange={(event) =>
                        setTagForm((value) => ({
                          ...value,
                          slug: toSlug(event.target.value),
                        }))
                      }
                    />
                  </LabeledField>
                  <LabeledField label="Statut">
                    <select
                      className={field}
                      value={tagForm.status}
                      onChange={(event) =>
                        setTagForm((value) => ({
                          ...value,
                          status: event.target.value as TagStatus,
                        }))
                      }
                    >
                      <option value="active">Actif</option>
                      <option value="archived">Archive</option>
                    </select>
                  </LabeledField>
                  <div className="flex flex-wrap gap-2 pt-1">
                    <button
                      className={primaryBtn}
                      type="button"
                      onClick={() =>
                        run(
                          "tag-save",
                          async () => {
                            const response = await request<{ tagId: string }>(
                              "/api/admin/tags",
                              {
                                action: tagForm.id ? "update" : "create",
                                payload: tagForm,
                              },
                            );
                            await refresh({ tagId: response.tagId });
                          },
                          "Tag sauvegarde.",
                        )
                      }
                    >
                      {busy === "tag-save" ? "Sauvegarde..." : "Sauvegarder"}
                    </button>
                    <button
                      className={secondaryBtn}
                      type="button"
                      disabled={!selectedTagId}
                      onClick={() =>
                        run(
                          "tag-delete",
                          async () => {
                            await request("/api/admin/tags", {
                              action: "delete",
                              tagId: selectedTagId,
                            });
                            await refresh({ tagId: null });
                          },
                          "Tag supprime.",
                        )
                      }
                    >
                      {busy === "tag-delete" ? "Suppression..." : "Supprimer"}
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>
          </div>
        ) : null}
      </section>
    );
  }

  function renderClientSection() {
    return (
      <section className="bg-white">
        <div className="border-b border-[var(--line)] bg-white px-4 py-4">
          <div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:justify-between">
            <div className="min-w-0">
              <div className="flex items-center gap-3 overflow-x-auto whitespace-nowrap">
                <p className="shrink-0 text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
                  Clients
                </p>
                <p className="truncate text-sm text-[var(--foreground)]">
                  Gestion des entites clientes. Les acces sont desormais geres depuis Groupes.
                </p>
              </div>
            </div>
            <button
              className={primaryBtn}
              type="button"
              onClick={() => openClientEditor(null)}
            >
              Nouveau client
            </button>
          </div>
        </div>

        <div className="relative xl:min-h-[calc(100dvh-49px)]">
          <div className="min-w-0">
            <div className="border-b border-[var(--line)] bg-[#f8fafc] px-4 py-3">
              <div className="grid gap-2 xl:grid-cols-[260px_180px_minmax(0,1fr)] xl:items-center">
                <div className="flex items-center gap-3">
                  <h2 className="text-base font-semibold text-[var(--ink)]">
                    Clients
                  </h2>
                  <span className="rounded-full bg-[#eef2f6] px-2.5 py-1 text-xs font-semibold text-[#51606b]">
                    {filteredClients.length}
                  </span>
                </div>
                <input
                  className={field}
                  placeholder="Rechercher un client"
                  value={clientSearch}
                  onChange={(event) => setClientSearch(event.target.value)}
                />
                <select
                  className={field}
                  value={clientStatus}
                  onChange={(event) =>
                    setClientStatus(event.target.value as "all" | ClientStatus)
                  }
                >
                  <option value="all">Tous statuts</option>
                  <option value="active">Actif</option>
                  <option value="archived">Archive</option>
                </select>
              </div>
            </div>

            {selectedClientIds.length > 0 ? (
              <div className="border-b border-[var(--line)] bg-[#eef5fb] px-4 py-3">
                <div className="flex items-center gap-4 overflow-x-auto whitespace-nowrap">
                  <div className="flex shrink-0 items-center gap-3">
                    <span className="rounded-full bg-white px-2.5 py-1 text-xs font-semibold text-[var(--primary)]">
                      {selectedClientIds.length} selectionnes
                    </span>
                    <p className="text-sm text-[var(--foreground)]">
                      Modification de masse
                    </p>
                  </div>
                  <div className="ml-auto flex shrink-0 items-center gap-2">
                    <select
                      className={`${field} min-w-[160px]`}
                      value={clientBulkStatus}
                      onChange={(event) =>
                        setClientBulkStatus(
                          event.target.value as "" | ClientStatus,
                        )
                      }
                    >
                      <option value="">Statut</option>
                      <option value="active">Actif</option>
                      <option value="archived">Archive</option>
                    </select>
                    <button
                      className={secondaryBtn}
                      type="button"
                      onClick={() =>
                        run(
                          "client-bulk-apply",
                          runClientBulkEdit,
                          "Modification de masse appliquee.",
                        )
                      }
                    >
                      {busy === "client-bulk-apply"
                        ? "Application..."
                        : "Appliquer"}
                    </button>
                    <button
                      className={ghostBtn}
                      type="button"
                      onClick={() => setSelectedClientIds([])}
                    >
                      Annuler
                    </button>
                  </div>
                </div>
              </div>
            ) : null}

            <div className="overflow-x-auto">
              <table className="min-w-full border-collapse">
                <thead>
                  <tr className="border-b border-[var(--line)]">
                    <th className={`${tableHeadCell} w-[54px]`}>
                      <input
                        type="checkbox"
                        aria-label="Selectionner les clients visibles"
                        checked={allVisibleClientsSelected}
                        onChange={(event) =>
                          setSelectedClientIds((current) =>
                            replaceVisibleSelection(
                              current,
                              visibleClientIds,
                              event.target.checked,
                            ),
                          )
                        }
                      />
                    </th>
                    <th className={tableHeadCell}>Nom</th>
                    <th className={tableHeadCell}>Slug</th>
                    <th className={tableHeadCell}>Statut</th>
                    <th className={`${tableHeadCell} w-[150px] text-right`}>
                      Action
                    </th>
                  </tr>
                </thead>
                <tbody>
                  {filteredClients.length > 0 ? (
                    filteredClients.map((client) => {
                      const selected =
                        clientEditorOpen && selectedClientId === client.id;
                      const checked = selectedClientIds.includes(client.id);
                      const baseRowTone = archivedRowTone(client.status === "archived");

                      return (
                        <tr
                          key={client.id}
                          className={`border-b border-[var(--line)] transition hover:bg-[#f8fbff] ${
                            selected ? "bg-[rgba(23,117,186,0.06)]" : baseRowTone
                          }`}
                          onClick={() => setSelectedClientId(client.id)}
                        >
                          <td className={tableCell}>
                            <input
                              type="checkbox"
                              aria-label={`Selectionner ${client.name}`}
                              checked={checked}
                              onChange={() =>
                                setSelectedClientIds((current) =>
                                  toggleSelection(current, client.id),
                                )
                              }
                              onClick={(event) => event.stopPropagation()}
                            />
                          </td>
                          <td
                            className={`${tableCell} ${
                              clientEditorOpen ? "w-[30%] max-w-0" : "w-[34%]"
                            }`}
                          >
                            <span className="block truncate font-semibold text-[var(--ink)]">
                              {client.name}
                            </span>
                          </td>
                          <td className={tableCell}>
                            <span className="block truncate text-[var(--foreground)]">
                              {client.slug}
                            </span>
                          </td>
                          <td className={tableCell}>
                            <StatusPill
                              status={client.status}
                              label={clientStatusLabel(client.status)}
                            />
                          </td>
                          <td className={`${tableCell} text-right`}>
                            <button
                              className={quietBtn}
                              type="button"
                              onClick={(event) => {
                                event.stopPropagation();
                                openClientEditor(client.id);
                              }}
                            >
                              Modifier
                            </button>
                          </td>
                        </tr>
                      );
                    })
                  ) : (
                    <tr>
                      <td
                        className="px-4 py-10 text-center text-sm text-[var(--foreground)]"
                        colSpan={5}
                      >
                        Aucun client ne correspond aux filtres.
                      </td>
                    </tr>
                  )}
                </tbody>
              </table>
            </div>
          </div>

          {clientEditorOpen ? (
            <div className="xl:absolute xl:inset-y-0 xl:right-0 xl:z-20 xl:w-[70%]">
              <div className="xl:h-full xl:min-h-[calc(100dvh-49px)] xl:overflow-y-auto xl:border-l xl:border-[var(--line)] xl:bg-[#fbfcfe]">
                <DetailPane
                  title={selectedClient ? selectedClient.name : "Nouveau client"}
                  subtitle={
                    selectedClient
                      ? selectedClient.slug
                      : "Creation d'un nouveau client"
                  }
                  status={
                    selectedClient
                      ? {
                          value: selectedClient.status,
                          label: clientStatusLabel(selectedClient.status),
                        }
                      : undefined
                  }
                  onClose={() => setClientEditorOpen(false)}
                  actions={
                    <>
                      <button
                        className={primaryBtn}
                        type="button"
                        onClick={() =>
                          run(
                            "client-save",
                            async () => {
                              const response = await request<{ clientId: string }>(
                                "/api/admin/clients",
                                {
                                  action: clientForm.id ? "update" : "create",
                                  payload: clientForm,
                                },
                              );
                              await refresh({ clientId: response.clientId });
                            },
                            "Client sauvegarde.",
                          )
                        }
                      >
                        {busy === "client-save" ? "Sauvegarde..." : "Sauvegarder"}
                      </button>
                      <button
                        className={secondaryBtn}
                        type="button"
                        disabled={!selectedClientId}
                        onClick={() =>
                          run(
                            "client-archive",
                            async () => {
                              await request("/api/admin/clients", {
                                action: "archive",
                                clientId: selectedClientId,
                              });
                              await refresh({ clientId: selectedClientId });
                            },
                            "Client archive.",
                          )
                        }
                      >
                        {busy === "client-archive" ? "Archivage..." : "Archiver"}
                      </button>
                    </>
                  }
                >
              <PaneBlock title="Identite">
                <div className="grid gap-3">
                  <LabeledField label="Nom client">
                    <input
                      className={field}
                      value={clientForm.name}
                      onChange={(event) =>
                        setClientForm((value) => ({
                          ...value,
                          name: event.target.value,
                        }))
                      }
                    />
                  </LabeledField>
                  <LabeledField label="Slug">
                    <input
                      className={field}
                      value={clientForm.slug}
                      onChange={(event) =>
                        setClientForm((value) => ({
                          ...value,
                          slug: toSlug(event.target.value),
                        }))
                      }
                    />
                  </LabeledField>
                  <LabeledField label="Statut">
                    <select
                      className={field}
                      value={clientForm.status}
                      onChange={(event) =>
                        setClientForm((value) => ({
                          ...value,
                          status: event.target.value as ClientStatus,
                        }))
                      }
                    >
                      <option value="active">Actif</option>
                      <option value="archived">Archive</option>
                    </select>
                  </LabeledField>
                </div>
              </PaneBlock>

              <PaneBlock title="Acces">
                <p className="text-sm leading-7 text-[var(--foreground)]">
                  La diffusion des cas pratiques et la gestion des utilisateurs
                  se font maintenant depuis la section Groupes. Cette fiche
                  client conserve uniquement l&apos;identite et le statut.
                </p>
              </PaneBlock>
                </DetailPane>
              </div>
            </div>
          ) : null}
        </div>
      </section>
    );
  }

  function renderGroupSettingsTab() {
    return (
      <>
        <PaneBlock
          title="Parametre groupe"
          description="Le slug est genere automatiquement cote serveur a partir du nom."
        >
          <div className="grid gap-3">
            <LabeledField label="Nom">
              <input
                className={field}
                value={groupForm.name}
                onChange={(event) =>
                  setGroupForm((value) => ({
                    ...value,
                    name: event.target.value,
                  }))
                }
              />
            </LabeledField>
            <LabeledField label="Description">
              <textarea
                className={textareaField}
                rows={4}
                value={groupForm.description}
                onChange={(event) =>
                  setGroupForm((value) => ({
                    ...value,
                    description: event.target.value,
                  }))
                }
              />
            </LabeledField>
            <div className="grid gap-3 xl:grid-cols-2">
              <LabeledField label="Entreprise">
                <select
                  className={field}
                  value={groupForm.companyId}
                  onChange={(event) =>
                    setGroupForm((value) => ({
                      ...value,
                      companyId: event.target.value,
                    }))
                  }
                >
                  <option value="">Selectionner une entreprise</option>
                  {dashboard.companies.map((company) => (
                    <option key={company.id} value={company.id}>
                      {company.name}
                    </option>
                  ))}
                </select>
              </LabeledField>
              <LabeledField label="Statut">
                <select
                  className={field}
                  value={groupForm.status}
                  onChange={(event) =>
                    setGroupForm((value) => ({
                      ...value,
                      status: event.target.value as CatalogStatus,
                    }))
                  }
                >
                  <option value="draft">Brouillon</option>
                  <option value="published">Actif</option>
                  <option value="archived">Archive</option>
                </select>
              </LabeledField>
            </div>
            <div className="grid gap-3 xl:grid-cols-2">
              <LabeledField label="Acces a partir du">
                <input
                  className={field}
                  type="date"
                  value={groupForm.accessStartDate}
                  onChange={(event) =>
                    setGroupForm((value) => ({
                      ...value,
                      accessStartDate: event.target.value,
                    }))
                  }
                />
              </LabeledField>
              <LabeledField label="Acces jusqu'au">
                <input
                  className={field}
                  type="date"
                  value={groupForm.accessEndDate}
                  onChange={(event) =>
                    setGroupForm((value) => ({
                      ...value,
                      accessEndDate: event.target.value,
                    }))
                  }
                />
              </LabeledField>
            </div>
          </div>
        </PaneBlock>

        <PaneBlock title="Etiquettes">
          <AssignmentView
            label="Tags du groupe"
            items={dashboard.tags.map((tag) => ({
              id: tag.id,
              name: tag.label,
            }))}
            selected={groupForm.tagIds}
            onToggle={(id) =>
              setGroupForm((value) => ({
                ...value,
                tagIds: toggle(value.tagIds, id),
              }))
            }
          />
        </PaneBlock>
      </>
    );
  }

  function renderGroupScenariosTab() {
    return (
      <PaneBlock
        title="Acces cas pratiques"
        description="Seuls les cas pratiques publies sont deployables dans un groupe."
      >
        <div className="grid gap-3">
          <div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:justify-between">
            <div className="flex items-center gap-3">
              <span className="rounded-full bg-[#eef2f6] px-2.5 py-1 text-xs font-semibold text-[#51606b]">
                {groupForm.scenarioTemplateIds.length} actif(s)
              </span>
              <span className="text-sm text-[var(--foreground)]">
                {publishedGroupScenarios.length} cas pratiques publies disponibles
              </span>
            </div>
            <input
              className={`${field} xl:max-w-[320px]`}
              placeholder="Rechercher un cas pratique"
              value={groupScenarioAccessSearch}
              onChange={(event) => setGroupScenarioAccessSearch(event.target.value)}
            />
          </div>

          <div className="overflow-x-auto border border-[var(--line)] bg-white">
            <table className="min-w-full border-collapse">
              <thead>
                <tr className="border-b border-[var(--line)]">
                  <th className={`${tableHeadCell} w-[54px]`}>Actif</th>
                  <th className={tableHeadCell}>Nom</th>
                  <th className={tableHeadCell}>Difficulte</th>
                  <th className={tableHeadCell}>Tags</th>
                </tr>
              </thead>
              <tbody>
                {filteredGroupScenarioOptions.length > 0 ? (
                  filteredGroupScenarioOptions.map((scenario) => {
                    const active = groupForm.scenarioTemplateIds.includes(
                      scenario.id,
                    );

                    return (
                      <tr
                        key={scenario.id}
                        className={`border-b border-[var(--line)] ${
                          active ? "bg-[rgba(23,117,186,0.05)]" : "bg-white"
                        }`}
                      >
                        <td className={tableCell}>
                          <input
                            type="checkbox"
                            checked={active}
                            onChange={() =>
                              setGroupForm((value) => ({
                                ...value,
                                scenarioTemplateIds: toggle(
                                  value.scenarioTemplateIds,
                                  scenario.id,
                                ),
                              }))
                            }
                          />
                        </td>
                        <td className={tableCell}>
                          <div className="min-w-0">
                            <p className="truncate font-semibold text-[var(--ink)]">
                              {templateLabel(scenario)}
                            </p>
                            <p className="mt-1 truncate text-xs text-[var(--foreground)]">
                              {scenario.slug}
                            </p>
                          </div>
                        </td>
                        <td className={tableCell}>
                          {difficultyLabel(scenario.publishedScenario?.difficulty)}
                        </td>
                        <td className={tableCell}>
                          {summarizeTags(scenario.tags)}
                        </td>
                      </tr>
                    );
                  })
                ) : (
                  <tr>
                    <td
                      className="px-4 py-10 text-center text-sm text-[var(--foreground)]"
                      colSpan={4}
                    >
                      Aucun cas pratique publie ne correspond a la recherche.
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>
        </div>
      </PaneBlock>
    );
  }

  function renderGroupUsersTable(members: ScenarioGroupMemberRecord[]) {
    return (
      <div className="overflow-x-auto border border-[var(--line)] bg-white">
        <table className="min-w-full border-collapse">
          <thead>
            <tr className="border-b border-[var(--line)]">
              <th className={tableHeadCell}>Email</th>
              <th className={tableHeadCell}>Nom</th>
              <th className={tableHeadCell}>Statut</th>
              <th className={tableHeadCell}>Dernier magic link</th>
              <th className={`${tableHeadCell} w-[130px] text-right`}>
                Action
              </th>
            </tr>
          </thead>
          <tbody>
            {members.length > 0 ? (
              members.map((member) => (
                <tr
                  key={member.companyMemberId}
                  className="border-b border-[var(--line)] bg-white"
                >
                  <td className={tableCell}>
                    <span className="font-medium text-[var(--ink)]">
                      {member.email}
                    </span>
                  </td>
                  <td className={tableCell}>{member.fullName ?? "-"}</td>
                  <td className={tableCell}>{member.status}</td>
                  <td className={tableCell}>
                    {formatMagicLinkDate(member.magicLinkLastSentAt)}
                  </td>
                  <td className={`${tableCell} text-right`}>
                    <button
                      className={quietBtn}
                      type="button"
                      onClick={() =>
                        run(
                          "group-member-remove",
                          () => runGroupMemberRemove(member.companyMemberId),
                          "Utilisateur retire du groupe.",
                        )
                      }
                    >
                      Retirer
                    </button>
                  </td>
                </tr>
              ))
            ) : (
              <tr>
                <td
                  className="px-4 py-10 text-center text-sm text-[var(--foreground)]"
                  colSpan={5}
                >
                  Aucun utilisateur ne correspond a la recherche.
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    );
  }

  function renderGroupUsersTab() {
    if (!selectedGroupId) {
      return (
        <PaneBlock title="Utilisateurs">
          <p className="text-sm leading-7 text-[var(--foreground)]">
            Sauvegardez d&apos;abord le groupe pour gerer ses utilisateurs.
          </p>
        </PaneBlock>
      );
    }

    return (
      <div className="grid gap-4 xl:grid-cols-[minmax(0,1fr)_340px]">
        <PaneBlock
          title="Utilisateurs du groupe"
          description="Les membres du groupe deviennent eligibles au magic link existant de la plateforme."
        >
          <div className="grid gap-3">
            <div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:justify-between">
              <span className="rounded-full bg-[#eef2f6] px-2.5 py-1 text-xs font-semibold text-[#51606b]">
                {selectedGroup?.memberCount ?? 0} utilisateur(s)
              </span>
              <input
                className={`${field} xl:max-w-[320px]`}
                placeholder="Rechercher un email"
                value={groupUserSearch}
                onChange={(event) => setGroupUserSearch(event.target.value)}
              />
            </div>

            {renderGroupUsersTable(filteredGroupMembers)}
          </div>
        </PaneBlock>

        <div className="grid gap-4">
          <PaneBlock
            title="Ajouter des emails"
            description="Un ou plusieurs emails, separes par ligne, virgule ou point-virgule."
          >
            <div className="grid gap-3">
              <textarea
                className={textareaField}
                rows={8}
                placeholder="prenom.nom@entreprise.com"
                value={groupInviteEmails}
                onChange={(event) => setGroupInviteEmails(event.target.value)}
              />
              <button
                className={primaryBtn}
                type="button"
                onClick={() =>
                  run(
                    "group-member-add",
                    runGroupMemberAdd,
                    "Utilisateurs ajoutes au groupe.",
                  )
                }
              >
                {busy === "group-member-add" ? "Ajout..." : "Ajouter au groupe"}
              </button>
            </div>
          </PaneBlock>

          <PaneBlock
            title="Importer CSV"
            description="Le CSV accepte un header email ou une premiere colonne email."
          >
            <div className="grid gap-3">
              <input
                key={groupMembersUploadKey}
                className={`${field} py-1.5`}
                type="file"
                accept=".csv,text/csv"
                onChange={(event) =>
                  setGroupMembersCsvFile(event.target.files?.[0] ?? null)
                }
              />
              <button
                className={secondaryBtn}
                type="button"
                disabled={!groupMembersCsvFile}
                onClick={() =>
                  run(
                    "group-members-import",
                    runGroupMembersCsvImport,
                    "Import CSV termine.",
                  )
                }
              >
                {busy === "group-members-import" ? "Import..." : "Importer le CSV"}
              </button>
              {groupImportReport ? (
                <div className="rounded-md border border-[var(--line)] bg-white px-3 py-3 text-sm text-[var(--foreground)]">
                  <p>
                    {groupImportReport.addedCount} email(s) ajoutes,{" "}
                    {groupImportReport.skippedDuplicates} doublon(s) ignores.
                  </p>
                  {groupImportReport.errors.length > 0 ? (
                    <div className="mt-2 space-y-1 text-xs text-[var(--accent-red)]">
                      {groupImportReport.errors.map((issue) => (
                        <p key={issue}>{issue}</p>
                      ))}
                    </div>
                  ) : null}
                </div>
              ) : null}
            </div>
          </PaneBlock>
        </div>
      </div>
    );
  }

  function renderGroupSection() {
    const tabs: { id: GroupEditorTab; title: string; description: string }[] = [
      {
        id: "settings",
        title: "Parametre groupe",
        description: "Identite, entreprise, statut et fenetre d'acces.",
      },
      {
        id: "scenarios",
        title: "Acces cas pratiques",
        description: "Selection des cas pratiques publies actifs dans ce groupe.",
      },
      {
        id: "users",
        title: "Utilisateurs",
        description: "Ajout manuel, import CSV et gestion des membres du groupe.",
      },
    ];

    return (
      <section className="bg-white">
        <div className="border-b border-[var(--line)] bg-white px-4 py-4">
          <div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:justify-between">
            <div className="min-w-0">
              <div className="flex items-center gap-3 overflow-x-auto whitespace-nowrap">
                <p className="shrink-0 text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
                  Groupes
                </p>
                <p className="truncate text-sm text-[var(--foreground)]">
                  Organisez les cas pratiques publies en groupes reutilisables.
                </p>
              </div>
            </div>
            <button
              className={primaryBtn}
              type="button"
              onClick={() => openGroupEditor(null)}
            >
              Nouveau groupe
            </button>
          </div>
        </div>

        <div className="relative xl:min-h-[calc(100dvh-49px)]">
          <div className="min-w-0">
            <div className="border-b border-[var(--line)] bg-[#f8fafc] px-4 py-3">
              <div className="grid gap-2 xl:grid-cols-[260px_180px_minmax(0,1fr)] xl:items-center">
                <div className="flex items-center gap-3">
                  <h2 className="text-base font-semibold text-[var(--ink)]">
                    Groupes
                  </h2>
                  <span className="rounded-full bg-[#eef2f6] px-2.5 py-1 text-xs font-semibold text-[#51606b]">
                    {filteredGroups.length}
                  </span>
                </div>
                <input
                  className={field}
                  placeholder="Rechercher un groupe"
                  value={groupSearch}
                  onChange={(event) => setGroupSearch(event.target.value)}
                />
                <select
                  className={field}
                  value={groupStatus}
                  onChange={(event) =>
                    setGroupStatus(event.target.value as "all" | CatalogStatus)
                  }
                >
                  <option value="all">Tous statuts</option>
                  <option value="draft">Brouillon</option>
                  <option value="published">Actif</option>
                  <option value="archived">Archive</option>
                </select>
              </div>
            </div>

            {selectedGroupIds.length > 0 ? (
              <div className="border-b border-[var(--line)] bg-[#eef5fb] px-4 py-3">
                <div className="flex items-center gap-4 overflow-x-auto whitespace-nowrap">
                  <div className="flex shrink-0 items-center gap-3">
                    <span className="rounded-full bg-white px-2.5 py-1 text-xs font-semibold text-[var(--primary)]">
                      {selectedGroupIds.length} selectionnes
                    </span>
                    <p className="text-sm text-[var(--foreground)]">
                      Modification de masse
                    </p>
                  </div>
                  <div className="ml-auto flex shrink-0 items-center gap-2">
                    <select
                      className={`${field} min-w-[150px]`}
                      value={groupBulkStatus}
                      onChange={(event) =>
                        setGroupBulkStatus(
                          event.target.value as "" | CatalogStatus,
                        )
                      }
                    >
                      <option value="">Statut</option>
                      <option value="draft">Brouillon</option>
                      <option value="published">Actif</option>
                      <option value="archived">Archive</option>
                    </select>
                    <select
                      className={`${field} min-w-[150px]`}
                      value={groupBulkTagId}
                      onChange={(event) => setGroupBulkTagId(event.target.value)}
                    >
                      <option value="all">Tag</option>
                      {dashboard.tags.map((tag) => (
                        <option key={tag.id} value={tag.id}>
                          {tag.label}
                        </option>
                      ))}
                    </select>
                    <button
                      className={secondaryBtn}
                      type="button"
                      onClick={() =>
                        run(
                          "group-bulk-apply",
                          runGroupBulkEdit,
                          "Modification de masse appliquee.",
                        )
                      }
                    >
                      {busy === "group-bulk-apply"
                        ? "Application..."
                        : "Appliquer"}
                    </button>
                    <button
                      className={secondaryBtn}
                      type="button"
                      onClick={() =>
                        run(
                          "group-bulk-remove-tag",
                          runGroupBulkTagRemoval,
                          "Tag retire de la selection.",
                        )
                      }
                    >
                      {busy === "group-bulk-remove-tag"
                        ? "Retrait..."
                        : "Retirer tag"}
                    </button>
                    <button
                      className={ghostBtn}
                      type="button"
                      onClick={() => setSelectedGroupIds([])}
                    >
                      Annuler
                    </button>
                  </div>
                </div>
              </div>
            ) : null}

            <div className="overflow-x-auto">
              <table className="min-w-full border-collapse">
                <thead>
                  <tr className="border-b border-[var(--line)]">
                    <th className={`${tableHeadCell} w-[54px]`}>
                      <input
                        type="checkbox"
                        aria-label="Selectionner les groupes visibles"
                        checked={allVisibleGroupsSelected}
                        onChange={(event) =>
                          setSelectedGroupIds((current) =>
                            replaceVisibleSelection(
                              current,
                              visibleGroupIds,
                              event.target.checked,
                            ),
                          )
                        }
                      />
                    </th>
                    <th className={tableHeadCell}>Nom</th>
                    <th className={tableHeadCell}>Entreprise</th>
                    <th className={tableHeadCell}>Statut</th>
                    <th className={tableHeadCell}>Utilisateurs</th>
                    <th className={tableHeadCell}>Cas pratiques</th>
                    <th className={`${tableHeadCell} w-[150px] text-right`}>
                      Action
                    </th>
                  </tr>
                </thead>
                <tbody>
                  {filteredGroups.length > 0 ? (
                    filteredGroups.map((group) => {
                      const selected =
                        groupEditorOpen && selectedGroupId === group.id;
                      const checked = selectedGroupIds.includes(group.id);
                      const baseRowTone = archivedRowTone(group.status === "archived");

                      return (
                        <tr
                          key={group.id}
                          className={`border-b border-[var(--line)] transition hover:bg-[#f8fbff] ${
                            selected ? "bg-[rgba(23,117,186,0.06)]" : baseRowTone
                          }`}
                          onClick={() => setSelectedGroupId(group.id)}
                        >
                          <td className={tableCell}>
                            <input
                              type="checkbox"
                              aria-label={`Selectionner ${group.name}`}
                              checked={checked}
                              onChange={() =>
                                setSelectedGroupIds((current) =>
                                  toggleSelection(current, group.id),
                                )
                              }
                              onClick={(event) => event.stopPropagation()}
                            />
                          </td>
                          <td
                            className={`${tableCell} ${
                              groupEditorOpen ? "w-[30%] max-w-0" : "w-[38%]"
                            }`}
                          >
                            <div>
                              <p className="truncate font-semibold text-[var(--ink)]">
                                {group.name}
                              </p>
                              <p className="mt-1 truncate text-xs text-[var(--foreground)]">
                                {group.slug}
                              </p>
                            </div>
                          </td>
                          <td className={tableCell}>
                            <span className="block truncate text-[var(--foreground)]">
                              {group.companyName ?? "Aucune entreprise"}
                            </span>
                          </td>
                          <td className={tableCell}>
                            <StatusPill
                              status={group.status}
                              label={catalogStatusLabel(group.status)}
                            />
                          </td>
                          <td className={tableCell}>{group.memberCount}</td>
                          <td className={tableCell}>
                            {group.scenarioTemplateIds.length}
                          </td>
                          <td className={`${tableCell} text-right`}>
                            <button
                              className={quietBtn}
                              type="button"
                              onClick={(event) => {
                                event.stopPropagation();
                                openGroupEditor(group.id);
                              }}
                            >
                              Modifier
                            </button>
                          </td>
                        </tr>
                      );
                    })
                  ) : (
                    <tr>
                      <td
                        className="px-4 py-10 text-center text-sm text-[var(--foreground)]"
                        colSpan={7}
                      >
                        Aucun groupe ne correspond aux filtres.
                      </td>
                    </tr>
                  )}
                </tbody>
              </table>
            </div>
          </div>

          {groupEditorOpen ? (
            <div className="xl:absolute xl:inset-y-0 xl:right-0 xl:z-20 xl:w-full">
              <div className="xl:h-full xl:min-h-[calc(100dvh-49px)] xl:overflow-y-auto xl:border-l xl:border-[var(--line)] xl:bg-[#fbfcfe]">
                <DetailPane
                  title={selectedGroup ? selectedGroup.name : "Nouveau groupe"}
                  subtitle={
                    selectedGroup
                      ? `${selectedGroup.companyName ?? "Entreprise a configurer"} - ${selectedGroup.memberCount} utilisateur(s)`
                      : "Creation d'un nouveau groupe"
                  }
                  status={
                    selectedGroup
                      ? {
                          value: selectedGroup.status,
                          label: catalogStatusLabel(selectedGroup.status),
                        }
                      : undefined
                  }
                  onClose={() => setGroupEditorOpen(false)}
                  actions={
                    <>
                      <button
                        className={primaryBtn}
                        type="button"
                        onClick={() =>
                          run(
                            "group-save",
                            saveGroup,
                            "Groupe sauvegarde.",
                          )
                        }
                      >
                        {busy === "group-save" ? "Sauvegarde..." : "Sauvegarder"}
                      </button>
                      <button
                        className={secondaryBtn}
                        type="button"
                        disabled={!selectedGroupId}
                        onClick={() =>
                          run(
                            "group-archive",
                            async () => {
                              await request("/api/admin/groups", {
                                action: "archive",
                                groupId: selectedGroupId,
                              });
                              await refresh({ groupId: selectedGroupId });
                            },
                            "Groupe archive.",
                          )
                        }
                      >
                        {busy === "group-archive" ? "Archivage..." : "Archiver"}
                      </button>
                    </>
                  }
                >
                  <div className="grid xl:grid-cols-[240px_minmax(0,1fr)] xl:items-start">
                    <aside className="border-b border-[var(--line)] bg-[#f8fafc] xl:h-full xl:border-b-0 xl:border-r">
                      <nav className="grid">
                        {tabs.map((tab) => {
                          const active = groupEditorTab === tab.id;

                          return (
                            <button
                              key={tab.id}
                              className={`border-b border-[var(--line)] px-4 py-4 text-left transition ${
                                active ? "bg-white" : "hover:bg-white"
                              }`}
                              type="button"
                              onClick={() => setGroupEditorTab(tab.id)}
                            >
                              <p className="text-sm font-semibold text-[var(--ink)]">
                                {tab.title}
                              </p>
                              <p className="mt-1 text-xs leading-6 text-[var(--foreground)]">
                                {tab.description}
                              </p>
                            </button>
                          );
                        })}
                      </nav>
                    </aside>

                    <div className="min-w-0">
                      {groupEditorTab === "settings" ? renderGroupSettingsTab() : null}
                      {groupEditorTab === "scenarios" ? renderGroupScenariosTab() : null}
                      {groupEditorTab === "users" ? renderGroupUsersTab() : null}
                    </div>
                  </div>
                </DetailPane>
              </div>
            </div>
          ) : null}
        </div>
      </section>
    );
  }

  function renderKnowledgeSection() {
    return (
      <section className="bg-white">
        <div className="border-b border-[var(--line)] bg-white px-4 py-4">
          <div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:justify-between">
            <div className="min-w-0">
              <div className="flex items-center gap-3 overflow-x-auto whitespace-nowrap">
                <p className="shrink-0 text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
                  Base de connaissances
                </p>
                <p className="truncate text-sm text-[var(--foreground)]">
                  Importez des fichiers puis surveillez leur indexation.
                </p>
              </div>
            </div>
            <button
              className={secondaryBtn}
              type="button"
              onClick={() =>
                run(
                  "knowledge-refresh",
                  refreshKnowledge,
                  "Documents recharges.",
                )
              }
            >
              {busy === "knowledge-refresh"
                ? "Actualisation..."
                : "Rafraichir"}
            </button>
          </div>
        </div>

        <div className="grid xl:grid-cols-[minmax(0,1fr)_360px]">
          <div className="min-w-0">
            <div className="overflow-x-auto">
              <table className="min-w-full border-collapse">
                <thead>
                  <tr className="border-b border-[var(--line)]">
                    <th className={tableHeadCell}>Document</th>
                    <th className={tableHeadCell}>Statut</th>
                    <th className={tableHeadCell}>Chunks</th>
                    <th className={tableHeadCell}>Taille</th>
                    <th className={tableHeadCell}>Maj</th>
                  </tr>
                </thead>
                <tbody>
                  {knowledgeDocuments.length > 0 ? (
                    knowledgeDocuments.map((document) => (
                      <tr
                        key={document.id}
                        className="border-b border-[var(--line)] bg-white"
                      >
                        <td className={tableCell}>
                          <div>
                            <p className="font-semibold text-[var(--ink)]">
                              {document.title}
                            </p>
                            <p className="mt-1 text-xs text-[var(--foreground)]">
                              {document.fileName}
                              {document.sourceLabel
                                ? ` - ${document.sourceLabel}`
                                : ""}
                            </p>
                            {document.errorMessage ? (
                              <p className="mt-2 text-xs text-[var(--accent-red)]">
                                {document.errorMessage}
                              </p>
                            ) : null}
                          </div>
                        </td>
                        <td className={tableCell}>
                          <StatusPill
                            status={document.status}
                            label={documentStatusLabel(document.status)}
                          />
                        </td>
                        <td className={tableCell}>{document.chunkCount}</td>
                        <td className={tableCell}>
                          {Math.max(1, Math.round(document.fileSize / 1024))} KB
                        </td>
                        <td className={tableCell}>
                          {new Date(document.updatedAt).toLocaleString("fr-FR")}
                        </td>
                      </tr>
                    ))
                  ) : (
                    <tr>
                      <td
                        className="px-4 py-10 text-center text-sm text-[var(--foreground)]"
                        colSpan={5}
                      >
                        Aucun document importe.
                      </td>
                    </tr>
                  )}
                </tbody>
              </table>
            </div>
          </div>

          <aside className="border-t border-[var(--line)] bg-[#fbfcfe] xl:border-t-0 xl:border-l">
            <div className="border-b border-[var(--line)] bg-white px-4 py-4">
              <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
                Import
              </p>
              <h2 className="mt-1 text-lg font-semibold text-[var(--ink)]">
                Nouveau document
              </h2>
              <p className="mt-2 text-sm text-[var(--foreground)]">
                Formats supportes: pdf, txt, md.
              </p>
            </div>
            <div className="grid gap-3 px-4 py-4">
              <LabeledField label="Titre affiche">
                <input
                  className={field}
                  value={knowledgeTitle}
                  onChange={(event) => setKnowledgeTitle(event.target.value)}
                />
              </LabeledField>
              <LabeledField label="Source">
                <input
                  className={field}
                  value={knowledgeSourceLabel}
                  onChange={(event) =>
                    setKnowledgeSourceLabel(event.target.value)
                  }
                />
              </LabeledField>
              <LabeledField label="Fichier">
                <input
                  key={knowledgeUploadKey}
                  className={`${field} py-1.5`}
                  type="file"
                  accept=".pdf,.txt,.md,text/plain,text/markdown,application/pdf"
                  onChange={(event) =>
                    setKnowledgeFile(event.target.files?.[0] ?? null)
                  }
                />
              </LabeledField>
              <button
                className={primaryBtn}
                disabled={!knowledgeFile}
                type="button"
                onClick={() =>
                  run(
                    "knowledge-upload",
                    async () => {
                      if (!knowledgeFile) {
                        throw new Error("Selectionnez un fichier a importer.");
                      }

                      const formData = new FormData();
                      formData.append("file", knowledgeFile);

                      if (knowledgeTitle.trim()) {
                        formData.append("title", knowledgeTitle.trim());
                      }

                      if (knowledgeSourceLabel.trim()) {
                        formData.append(
                          "sourceLabel",
                          knowledgeSourceLabel.trim(),
                        );
                      }

                      const response = await fetch("/api/admin/knowledge", {
                        method: "POST",
                        body: formData,
                      });
                      const payload = (await response.json()) as
                        | { document: KnowledgeDocumentRecord }
                        | { error?: string };

                      if (!response.ok || !("document" in payload)) {
                        throw new Error(
                          "error" in payload && payload.error
                            ? payload.error
                            : "L'import du document a echoue.",
                        );
                      }

                      await refreshKnowledge();
                      setKnowledgeTitle("");
                      setKnowledgeSourceLabel("");
                      setKnowledgeFile(null);
                      setKnowledgeUploadKey((value) => value + 1);
                    },
                    "Document importe et indexe.",
                  )
                }
              >
                {busy === "knowledge-upload"
                  ? "Import en cours..."
                  : "Importer et indexer"}
              </button>
            </div>
          </aside>
        </div>
      </section>
    );
  }

  return (
    <div className="grid xl:grid-cols-[248px_minmax(0,1fr)]">
      <aside className="border-b border-[var(--line)] bg-[#f7f8fa] xl:min-h-screen xl:border-b-0 xl:border-r">
        <div className="border-b border-[var(--line)] px-4 py-4 xl:pt-5">
          <p className="text-[10px] font-semibold uppercase tracking-[0.18em] text-[#6b7280]">
            Platform Console
          </p>
          <p className="mt-1 text-2xl font-semibold tracking-[-0.04em] text-[var(--ink)]">
            Evolia
          </p>
        </div>

        <div className="border-b border-[var(--line)] px-4 py-4">
          <p className="text-[11px] font-semibold uppercase tracking-[0.14em] text-[#6b7280]">
            Workspace
          </p>
          <h2 className="mt-1 text-lg font-semibold text-[var(--ink)]">
            Admin dashboard
          </h2>
          <p className="mt-2 text-sm leading-7 text-[var(--foreground)]">
            Navigation compacte inspiree d&apos;un explorateur de fichiers.
          </p>
          <button
            className={`${secondaryBtn} mt-4 w-full`}
            type="button"
            onClick={() =>
              currentSection === "knowledge"
                ? run(
                    "knowledge-refresh",
                    refreshKnowledge,
                    "Documents recharges.",
                  )
                : run("refresh", () => refresh(), "Dashboard actualise.")
            }
          >
            {busy === "refresh" || busy === "knowledge-refresh"
              ? "Actualisation..."
              : "Rafraichir"}
          </button>
        </div>

        <nav>
          {navigation.map((item) => {
            const active = currentSection === item.id;
            return (
              <Link
                key={item.id}
                href={`/admin/${item.id}`}
                className={`${navItemBase} ${
                  active
                    ? "border-l-[3px] border-l-[var(--primary)] bg-white"
                    : "border-l-[3px] border-l-transparent hover:bg-white"
                }`}
              >
                <p className="text-sm font-semibold text-[var(--ink)]">
                  {item.title}
                </p>
                <p className="mt-1 text-xs leading-6 text-[var(--foreground)]">
                  {item.description}
                </p>
              </Link>
            );
          })}
        </nav>
      </aside>

      <div className="min-w-0 bg-white xl:pt-[49px]">
        {(message || error) && (
          <div
            className={`border-b px-4 py-3 text-sm font-medium ${
              error
                ? "border-[rgba(193,22,27,0.16)] bg-[rgba(193,22,27,0.07)] text-[var(--accent-red)]"
                : "border-[rgba(47,138,99,0.18)] bg-[rgba(47,138,99,0.07)] text-[var(--success)]"
            }`}
          >
            {error ?? message}
          </div>
        )}
        {currentSection === "scenarios" && renderScenarioSection()}
        {currentSection === "clients" && renderClientSection()}
        {currentSection === "groups" && renderGroupSection()}
        {currentSection === "knowledge" && renderKnowledgeSection()}
      </div>
    </div>
  );
}
