import { useEffect, useState } from "react";
import { Play, Pause, X, Gauge } from "lucide-react";

import { cn } from "@/lib/utils";
import {
  SPEED_OPTIONS,
  type Speed,
  useDemoEnd,
  useDemoState,
  useDemoTick,
} from "@/lib/demo";
import { Gem } from "@/components/brand/Gem";
import { DemoEmailSlide } from "./DemoEmailSlide";

/**
 * Horloge virtuelle de démo — visible top-right de _app, uniquement
 * quand `org.demoMode = true`.
 *
 * Anatomie :
 *  ┌─────────────────────────────────────┐
 *  │ vendredi 18 mai 2026                │
 *  │ ◆────●─────────────  J+5 / →prochain│
 *  │ [▶]  1x 2x 5x   [↻]  [×]            │
 *  └─────────────────────────────────────┘
 *
 * - Date pleine, font display, mise à jour live à chaque frame
 * - Rail rubis-glow avec une pastille qui glisse de virtualNow vers le
 *   prochain event (proportion calculée backend → SPA)
 * - Play/Pause + sélecteur de vitesse 1x/2x/5x
 * - Bouton fermer = `/demo/end`
 *
 * Quand un event est déclenché, la slide-over droite s'ouvre avec
 * l'email capturé. L'horloge est en pause tant que tous les events
 * en attente n'ont pas été acquittés (clic "Continuer").
 */

const FR_DATE = new Intl.DateTimeFormat("fr-FR", {
  weekday: "long",
  day: "numeric",
  month: "long",
  year: "numeric",
});

export function DemoClock() {
  const { data: state } = useDemoState();
  const endMutation = useDemoEnd();

  const enabled = state?.demoMode === true;
  const tick = useDemoTick({
    enabled,
    initialVirtualNow: state?.virtualNow,
  });

  // Re-sync local virtualNow quand le backend change (start/reset)
  useEffect(() => {
    if (state?.virtualNow) tick.resetTo(state.virtualNow);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state?.virtualNow, enabled]);

  if (!enabled) return null;

  const dateStr = FR_DATE.format(tick.virtualNow);

  // Progression vers le prochain event (0..1) — sert au rail visuel.
  const progress = computeProgress({
    virtualNow: tick.virtualNow,
    nextEventAt: state?.nextEventAt ?? null,
  });

  const hasPending = tick.pendingEvents.length > 0;

  return (
    <>
      <div
        className={cn(
          "fixed top-4 right-4 z-30 w-[300px]",
          "rounded-card border border-rubis-glow bg-white shadow-card",
          "px-4 py-3",
        )}
      >
        {/* En-tête : date + tag DÉMO */}
        <div className="flex items-start justify-between mb-2">
          <div>
            <p className="font-display text-[14.5px] font-bold leading-tight text-ink capitalize tabular-nums">
              {dateStr}
            </p>
            <p className="text-[10.5px] uppercase tracking-[0.12em] text-rubis font-semibold mt-0.5">
              Mode démo · horloge virtuelle
            </p>
          </div>
          <button
            type="button"
            onClick={() => endMutation.mutate()}
            className="size-6 flex items-center justify-center rounded-full text-ink-3 hover:text-rubis-deep hover:bg-rubis-glow/40 transition-colors"
            aria-label="Quitter le mode démo"
            title="Quitter le mode démo"
          >
            <X size={14} />
          </button>
        </div>

        {/* Rail rubis-glow avec pastille qui glisse */}
        <div className="relative h-2 mb-3 mt-1">
          <div className="absolute inset-x-0 top-1/2 -translate-y-1/2 h-px bg-line" />
          <div
            className="absolute top-1/2 -translate-y-1/2 h-px bg-rubis transition-[width] duration-300"
            style={{ width: `${progress * 100}%` }}
          />
          <span
            aria-hidden="true"
            className="absolute -top-1 size-3 rotate-45 bg-rubis shadow-rubis transition-[left] duration-300"
            style={{ left: `calc(${progress * 100}% - 6px)` }}
          />
          <Gem
            size={10}
            aria-hidden="true"
            className="absolute -top-1 -left-0.5"
          />
        </div>

        {/* Controls */}
        <div className="flex items-center gap-2">
          <button
            type="button"
            onClick={() => (tick.playing ? tick.pause() : tick.play())}
            disabled={hasPending}
            className={cn(
              "size-9 flex items-center justify-center rounded-default",
              "bg-rubis text-white shadow-rubis hover:bg-rubis-deep transition-colors",
              "disabled:bg-line disabled:text-ink-3 disabled:shadow-none disabled:cursor-not-allowed",
              "focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-rubis-glow",
            )}
            aria-label={tick.playing ? "Pause" : "Lecture"}
          >
            {tick.playing ? <Pause size={14} /> : <Play size={14} className="ml-0.5" />}
          </button>

          <SpeedSelector value={tick.speed} onChange={tick.setSpeed} />

          <p className="ml-auto text-[10.5px] text-ink-3 italic tabular-nums">
            {state?.nextEventAt
              ? `→ ${shortNextLabel(tick.virtualNow, state.nextEventAt)}`
              : "aucun event en file"}
          </p>
        </div>
      </div>

      {/* Slide-over : empile les events fired à acquitter un par un */}
      {hasPending && (
        <DemoEmailSlide
          event={tick.pendingEvents[0]!}
          remaining={tick.pendingEvents.length - 1}
          virtualNow={tick.virtualNow}
          onContinue={tick.acknowledge}
        />
      )}
    </>
  );
}

function SpeedSelector({
  value,
  onChange,
}: {
  value: Speed;
  onChange: (s: Speed) => void;
}) {
  return (
    <div
      role="radiogroup"
      aria-label="Vitesse"
      className="inline-flex items-center gap-1 rounded-default border border-line bg-cream-2/40 px-1.5 py-0.5"
    >
      <Gauge size={11} className="text-ink-3" aria-hidden="true" />
      {SPEED_OPTIONS.map((s) => {
        const active = s === value;
        return (
          <button
            key={s}
            type="button"
            role="radio"
            aria-checked={active}
            onClick={() => onChange(s)}
            className={cn(
              "h-6 px-1.5 rounded-sharp text-[11px] font-semibold tabular-nums transition-colors",
              active
                ? "bg-rubis text-white"
                : "text-ink-2 hover:bg-cream-2",
            )}
          >
            {s}x
          </button>
        );
      })}
    </div>
  );
}

function computeProgress({
  virtualNow,
  nextEventAt,
}: {
  virtualNow: Date;
  nextEventAt: string | null;
}): number {
  if (!nextEventAt) return 0;
  const next = new Date(nextEventAt).getTime();
  // On affiche la progression sur une fenêtre de 30 jours autour du prochain event
  // (évite que la pastille soit collée à 0% ou 100% en permanence).
  const start = next - 30 * 86400000;
  const now = virtualNow.getTime();
  if (now <= start) return 0;
  if (now >= next) return 1;
  return (now - start) / (next - start);
}

function shortNextLabel(now: Date, iso: string): string {
  const next = new Date(iso).getTime();
  const diffMs = next - now.getTime();
  if (diffMs <= 0) return "imminent";
  const days = Math.round(diffMs / 86400000);
  if (days <= 0) return "aujourd'hui";
  return `dans ${days} j`;
}
