/**
 * `PluginsPanel` — the `Paramètres > Plugins` admin surface (ticket #43, F2).
 *
 * Pure presentation; all behaviour comes from {@link usePlugins}. List of
 * installed plugins (name/publisher/version/source/state/restartRequired/
 * trust), install from archive/directory with a pre-install review step
 * (manifest summary + explicit full-trust mention), enable/disable/uninstall
 * with confirmation, and readable `pending`/`invalid`/error states.
 */

import { useState } from "react";

import type { PluginAdmin, PluginLifecycleState, PluginReview } from "@/domain";
import { Button, Panel } from "@/shared";
import { PluginConfirmDialog as ConfirmDialog } from "./PluginConfirmDialog";
import { usePluginRuntime } from "./PluginRuntimeProvider";
import { usePlugins } from "./usePlugins";

const STATE_LABEL: Record<PluginLifecycleState, string> = {
  enabled: "Activé",
  disabled: "Désactivé",
  "pending-enable": "Activation en attente",
  "pending-disable": "Désactivation en attente",
  "pending-uninstall": "Désinstallation en attente",
  invalid: "Invalide",
};

type PendingAction =
  | { kind: "disable"; plugin: PluginAdmin }
  | { kind: "uninstall"; plugin: PluginAdmin };

interface InstallFlow {
  sourceKind: "archive" | "directory";
  path: string;
  review: PluginReview;
}

export function PluginsPanel() {
  const vm = usePlugins();
  const pluginRuntime = usePluginRuntime();
  const [pendingAction, setPendingAction] = useState<PendingAction | null>(null);
  const [installFlow, setInstallFlow] = useState<InstallFlow | null>(null);
  const [installFlowError, setInstallFlowError] = useState<string | null>(null);

  async function startInstallFromArchive() {
    setInstallFlowError(null);
    const path = await vm.pickArchiveFile();
    if (!path) return;
    const review = await vm.reviewArchive(path);
    if (!review) {
      setInstallFlowError("La revue du paquet a échoué.");
      return;
    }
    setInstallFlow({ sourceKind: "archive", path, review });
  }

  async function startInstallFromDirectory() {
    setInstallFlowError(null);
    const path = await vm.pickDirectory();
    if (!path) return;
    const review = await vm.reviewDirectory(path);
    if (!review) {
      setInstallFlowError("La revue du paquet a échoué.");
      return;
    }
    setInstallFlow({ sourceKind: "directory", path, review });
  }

  async function confirmInstall() {
    if (!installFlow) return;
    const ok =
      installFlow.sourceKind === "archive"
        ? await vm.installFromArchive(installFlow.path)
        : await vm.installFromDirectory(installFlow.path);
    if (ok) setInstallFlow(null);
  }

  async function confirmPendingAction() {
    if (!pendingAction) return;
    if (pendingAction.kind === "disable") {
      await vm.setEnabled(pendingAction.plugin.id, false);
    } else {
      await vm.uninstall(pendingAction.plugin.id);
    }
    setPendingAction(null);
  }

  return (
    <div className="flex flex-col gap-4">
      <div className="flex items-center justify-between">
        <h2 className="text-sm font-semibold text-content">Plugins</h2>
        <div className="flex gap-2">
          <Button size="sm" onClick={() => void startInstallFromArchive()} disabled={vm.busy}>
            Installer depuis une archive…
          </Button>
          <Button
            size="sm"
            variant="secondary"
            onClick={() => void startInstallFromDirectory()}
            disabled={vm.busy}
          >
            Installer depuis un dossier…
          </Button>
        </div>
      </div>

      {(vm.error || installFlowError) && (
        <p role="alert" className="text-sm text-danger">
          {vm.error ?? installFlowError}
        </p>
      )}

      {pluginRuntime.failures.length > 0 && (
        <Panel className="border-warning/40">
          <div className="flex flex-col gap-1">
            <p role="alert" className="text-sm font-medium text-warning">
              Certains plugins installés n'ont pas pu être chargés.
            </p>
            <ul className="flex flex-col gap-0.5">
              {pluginRuntime.failures.map((failure) => (
                <li key={`${failure.pluginId}:${failure.reason}`} className="text-xs text-muted">
                  <span className="font-medium text-content">{failure.pluginId}</span> :{" "}
                  {failure.reason}
                </li>
              ))}
            </ul>
          </div>
        </Panel>
      )}

      {pluginRuntime.pending.length > 0 && (
        <Panel>
          <div className="flex flex-col gap-1">
            <p className="text-sm font-medium text-content">
              Certains plugins attendent un projet actif.
            </p>
            <ul className="flex flex-col gap-0.5">
              {pluginRuntime.pending.map((pending) => (
                <li key={pending.pluginId} className="text-xs text-muted">
                  <span className="font-medium text-content">{pending.displayName}</span>
                </li>
              ))}
            </ul>
          </div>
        </Panel>
      )}

      {vm.plugins.length === 0 ? (
        <Panel>
          <p className="text-sm text-muted">Aucun plugin installé.</p>
        </Panel>
      ) : (
        <ul className="flex flex-col gap-2">
          {vm.plugins.map((p) => (
            <li key={p.id}>
              <Panel className="flex items-center justify-between gap-4">
                <div className="flex flex-col gap-0.5">
                  <div className="flex items-center gap-2">
                    <span className="text-sm font-semibold text-content">{p.displayName}</span>
                    <span className="text-xs text-faint">v{p.version}</span>
                    {p.publisher && <span className="text-xs text-faint">· {p.publisher}</span>}
                    <span className="rounded bg-raised px-1.5 py-0.5 text-[0.65rem] uppercase text-muted">
                      full-trust
                    </span>
                  </div>
                  <div className="flex items-center gap-2 text-xs text-muted">
                    <span
                      aria-label="plugin state"
                      className={
                        p.lifecycleState === "invalid" ? "text-danger" : undefined
                      }
                    >
                      {STATE_LABEL[p.lifecycleState]}
                    </span>
                    {p.restartRequired && (
                      <span className="text-warning">Redémarrage requis</span>
                    )}
                    {p.sourceLabel && <span>· {p.sourceLabel}</span>}
                  </div>
                  {p.error && (
                    <p className="text-xs text-danger" role="alert">
                      {p.error}
                    </p>
                  )}
                </div>
                <div className="flex shrink-0 items-center gap-2">
                  {p.lifecycleState === "invalid" ? (
                    <Button size="sm" variant="ghost" disabled>
                      Isolé
                    </Button>
                  ) : p.enabled ? (
                    <Button
                      size="sm"
                      variant="ghost"
                      onClick={() => setPendingAction({ kind: "disable", plugin: p })}
                      disabled={vm.busy}
                    >
                      Désactiver
                    </Button>
                  ) : (
                    <Button
                      size="sm"
                      variant="ghost"
                      onClick={() => void vm.setEnabled(p.id, true)}
                      disabled={vm.busy}
                    >
                      Activer
                    </Button>
                  )}
                  <Button
                    size="sm"
                    variant="ghost"
                    onClick={() => void vm.openPluginsFolder(p.id)}
                    disabled={vm.busy}
                  >
                    Ouvrir le dossier
                  </Button>
                  <Button
                    size="sm"
                    variant="danger"
                    onClick={() => setPendingAction({ kind: "uninstall", plugin: p })}
                    disabled={vm.busy}
                  >
                    Désinstaller
                  </Button>
                </div>
              </Panel>
            </li>
          ))}
        </ul>
      )}

      {installFlow && (
        <ConfirmDialog
          title={`Installer "${installFlow.review.displayName}" ?`}
          body={reviewSummary(installFlow.review)}
          confirmLabel={
            isInstallable(installFlow.review) ? "Installer" : "Corriger avant d'installer"
          }
          busy={vm.busy}
          danger={!isInstallable(installFlow.review)}
          onConfirm={() => {
            if (isInstallable(installFlow.review)) void confirmInstall();
            else setInstallFlow(null);
          }}
          onCancel={() => setInstallFlow(null)}
        />
      )}

      {pendingAction && (
        <ConfirmDialog
          title={
            pendingAction.kind === "disable"
              ? `Désactiver "${pendingAction.plugin.displayName}" ?`
              : `Désinstaller "${pendingAction.plugin.displayName}" ?`
          }
          body={
            pendingAction.kind === "disable"
              ? "Ses contributions seront masquées immédiatement ; un redémarrage sera peut-être nécessaire pour purger complètement le plugin."
              : "Le plugin, ses fichiers et ses contributions seront supprimés après redémarrage."
          }
          confirmLabel={pendingAction.kind === "disable" ? "Désactiver" : "Désinstaller"}
          danger={pendingAction.kind === "uninstall"}
          busy={vm.busy}
          onConfirm={() => void confirmPendingAction()}
          onCancel={() => setPendingAction(null)}
        />
      )}
    </div>
  );
}

function reviewSummary(review: PluginReview): string {
  const { contributionSummary: c } = review;
  const parts = [
    `Éditeur : ${review.publisher ?? "inconnu"}`,
    `Version : ${review.version}`,
    review.description ?? null,
    `Confiance : full-trust — ce plugin peut exécuter du code arbitraire dans IdeA.`,
    `Contributions : ${c.topLevelMenus} menu(s), ${c.menuItems} item(s), ${c.layouts} layout(s), ${c.mcpServers} serveur(s) MCP.`,
    ...(review.issues ?? []).map(
      (i) => `${i.severity === "error" ? "Erreur" : "Avertissement"} : ${i.message}`,
    ),
  ].filter((p): p is string => Boolean(p));
  return parts.join("\n");
}

function isInstallable(review: PluginReview): boolean {
  return review.installable ?? true;
}
