"use client";

import { useMemo, useRef, useState, type ChangeEvent } from "react";
import { signIn, signOut, useSession } from "next-auth/react";

type SpeechRecognitionAlternative = {
  transcript: string;
};

type SpeechRecognitionResult = {
  0: SpeechRecognitionAlternative;
  isFinal: boolean;
};

type SpeechRecognitionEventLike = Event & {
  resultIndex: number;
  results: ArrayLike<SpeechRecognitionResult>;
};

type SpeechRecognitionLike = {
  lang: string;
  interimResults: boolean;
  continuous: boolean;
  onresult: ((event: SpeechRecognitionEventLike) => void) | null;
  onend: (() => void) | null;
  onerror: ((event: Event) => void) | null;
  start: () => void;
  stop: () => void;
};

type SpeechRecognitionCtor = new () => SpeechRecognitionLike;

declare global {
  interface Window {
    webkitSpeechRecognition?: SpeechRecognitionCtor;
    SpeechRecognition?: SpeechRecognitionCtor;
  }
}

type CalendarIntent = {
  intent: "create_calendar_event";
  title: string;
  start_datetime: string;
  timezone: string;
  duration_minutes: number;
  attendees: string[];
  location: string | null;
  notes: string | null;
  online_meeting: boolean;
};

type WorkBlocksIntent = {
  intent: "plan_work_blocks";
  task_title: string;
  deadline: string;
  timezone: string;
  total_effort_minutes: number;
  preferred_block_minutes: number;
  cadence_type: "none" | "daily" | "weekly" | "custom";
  cadence_every_n_days: number | null;
  cadence_per_week_target_minutes: number | null;
  preferred_days: number[];
  confidence: number;
  constraints: {
    work_day_start_hour: number;
    work_day_end_hour: number;
    excluded_weekdays: number[];
    min_break_minutes: number;
    strategy: "spread" | "compact";
  };
};

type ParsedIntent = CalendarIntent | WorkBlocksIntent;

type WorkPlanBlock = {
  title: string;
  start: string;
  end: string;
  durationMinutes: number;
  notes: string | null;
};

type WorkPlan = {
  planId: string;
  source: "work_planner_v1";
  provider: "outlook" | "google";
  taskTitle: string;
  timezone: string;
  totalEffortMinutes: number;
  plannedMinutes: number;
  remainingMinutes: number;
  deadline: string;
  blocks: WorkPlanBlock[];
  diagnostics: {
    cadence_type: "none" | "daily" | "weekly" | "custom";
    weeks_detected: number;
    target_minutes_per_week: number | null;
    allocation_reason: string;
  };
  warnings: string[];
  plannerLog: string[];
};

type ContextDocument = {
  id: string;
  source_type: "text" | "pdf" | "docx" | "image";
  file_name: string;
  mime_type: string;
  size_bytes: number;
  extracted_text_preview: string;
  summary: string;
  highlights: string[];
  created_at: string;
  expires_at: string;
  used_openai: boolean;
};

type WorkClarification = {
  missing_fields: string[];
  prompt: string;
};

type ActivityItem = {
  id: string;
  label: string;
  timestamp: string;
};

async function postJson<T>(url: string, body: unknown): Promise<T> {
  const response = await fetch(url, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(body)
  });

  if (!response.ok) {
    const detail = await response.text();
    throw new Error(detail || "Requete en echec");
  }

  return (await response.json()) as T;
}

export default function HomePage() {
  const { data: session, status: sessionStatus } = useSession();
  const [text, setText] = useState("");
  const [isListening, setIsListening] = useState(false);
  const [isTranscribing, setIsTranscribing] = useState(false);
  const [isWorking, setIsWorking] = useState(false);
  const [assistantMode, setAssistantMode] = useState<"event" | "work">("event");
  const [calendarProvider, setCalendarProvider] = useState<"outlook" | "google">(
    "outlook"
  );
  const [intent, setIntent] = useState<ParsedIntent | null>(null);
  const [workPlan, setWorkPlan] = useState<WorkPlan | null>(null);
  const [contextDocument, setContextDocument] = useState<ContextDocument | null>(null);
  const [status, setStatus] = useState("Pret. Parlez ou saisissez une demande.");
  const [error, setError] = useState<string | null>(null);
  const [history, setHistory] = useState<ActivityItem[]>([]);
  const [isUploadingContext, setIsUploadingContext] = useState(false);
  const recognitionRef = useRef<SpeechRecognitionLike | null>(null);
  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const mediaStreamRef = useRef<MediaStream | null>(null);
  const audioChunksRef = useRef<BlobPart[]>([]);
  const idempotencyKeyRef = useRef<string | null>(null);
  const contextFileInputRef = useRef<HTMLInputElement | null>(null);

  const transcriptHint = useMemo(
    () =>
      assistantMode === "work"
        ? "Exemple: J'ai une deadline au 2026-04-28 18:00, prevois 6h en blocs de 90 min pour le dossier client"
        : "Exemple: Planifie une reunion le 15 novembre a 9h avec paul@exemple.com pendant 30 minutes",
    [assistantMode]
  );

  const hasSessionRefreshError = session?.error === "RefreshAccessTokenError";

  function estimateWeeksUntil(deadlineIso: string): number {
    const now = Date.now();
    const deadline = new Date(deadlineIso).getTime();
    if (!Number.isFinite(deadline) || deadline <= now) return 1;
    return Math.max(1, Math.ceil((deadline - now) / (7 * 24 * 60 * 60 * 1000)));
  }

  const cadenceLabel = useMemo(() => {
    if (!intent || intent.intent !== "plan_work_blocks") return "Aucune";
    if (intent.cadence_type === "weekly") {
      return intent.cadence_per_week_target_minutes
        ? `${intent.cadence_per_week_target_minutes} min/semaine`
        : "Hebdomadaire";
    }
    if (intent.cadence_type === "daily") return "Quotidienne";
    if (intent.cadence_type === "custom") {
      return intent.cadence_every_n_days
        ? `Tous les ${intent.cadence_every_n_days} jours`
        : "Personnalisee";
    }
    return "Aucune";
  }, [intent]);

  async function connectOutlook() {
    await signIn("azure-ad");
  }

  async function reconnectOutlook() {
    await signOut({ redirect: false });
    await signIn("azure-ad", { callbackUrl: "/" });
  }

  async function connectGoogle() {
    await signIn("google", { callbackUrl: "/" });
  }

  async function reconnectGoogleWithScopes() {
    await signOut({ redirect: false });
    await signIn("google", { callbackUrl: "/" });
  }

  function addHistory(label: string) {
    setHistory((prev) => {
      const next = [
        {
          id: crypto.randomUUID(),
          label,
          timestamp: new Date().toLocaleTimeString("fr-FR", {
            hour: "2-digit",
            minute: "2-digit"
          })
        },
        ...prev
      ];

      return next.slice(0, 5);
    });
  }

  async function handleContextFileSelected(event: ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    if (!file) return;

    setError(null);
    setIsUploadingContext(true);
    setStatus("Analyse du document en cours...");

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

      const response = await fetch("/api/context", {
        method: "POST",
        body: formData
      });

      const payload = (await response.json()) as {
        context?: ContextDocument;
        error?: string;
      };

      if (!response.ok || !payload.context) {
        throw new Error(payload.error || "Analyse document impossible.");
      }

      setContextDocument(payload.context);
      setStatus("Contexte document charge. Vous pouvez demander une planification.");
      addHistory("Document analyse");
    } catch (e) {
      setError(e instanceof Error ? e.message : "Erreur upload document.");
      setStatus("Echec analyse document.");
    } finally {
      setIsUploadingContext(false);
      if (event.target) {
        event.target.value = "";
      }
    }
  }

  async function suggestFromText() {
    if (!text.trim()) {
      setError("Ajoutez une phrase avant de continuer.");
      return;
    }

    setError(null);
    setIsWorking(true);
    setStatus("Analyse en cours...");

    try {
      const payload = await postJson<{
        intent: ParsedIntent;
        source: "openai" | "fallback";
        clarification?: WorkClarification | null;
      }>(
        "/api/intent",
        {
          text,
          mode: assistantMode,
          context: contextDocument
            ? {
                id: contextDocument.id,
                source_type: contextDocument.source_type,
                file_name: contextDocument.file_name,
                mime_type: contextDocument.mime_type,
                summary: contextDocument.summary,
                highlights: contextDocument.highlights,
                extracted_text_preview: contextDocument.extracted_text_preview
              }
            : undefined
        }
      );

      setIntent(payload.intent);

      if (payload.intent.intent === "plan_work_blocks") {
        setStatus("Calcul du planning en cours...");
        const planPayload = await postJson<{ plan: WorkPlan }>("/api/work-plan", {
          action: "propose",
          provider: calendarProvider,
          intent: payload.intent
        });

        setWorkPlan(planPayload.plan);
        idempotencyKeyRef.current = crypto.randomUUID();
        setStatus(
          payload.clarification?.prompt ||
            "Planning propose. Verifiez puis confirmez la creation des blocs."
        );
      } else {
        setWorkPlan(null);
        setStatus("Proposition prete. Verifiez puis confirmez.");
      }

      addHistory(payload.source === "fallback" ? "Analyse locale (fallback)" : "Analyse OpenAI");
    } catch (e) {
      setError(e instanceof Error ? e.message : "Erreur inconnue.");
    } finally {
      setIsWorking(false);
    }
  }

  async function recomputeWorkPlanFromIntent(nextIntent: WorkBlocksIntent) {
    setError(null);
    setIsWorking(true);
    setStatus("Recalcul du planning...");

    try {
      const payload = await postJson<{ plan: WorkPlan }>("/api/work-plan", {
        action: "propose",
        provider: calendarProvider,
        intent: nextIntent
      });
      setIntent(nextIntent);
      setWorkPlan(payload.plan);
      idempotencyKeyRef.current = crypto.randomUUID();
      setStatus("Planning recalcule. Verifiez puis confirmez.");
    } catch (e) {
      setError(e instanceof Error ? e.message : "Erreur inconnue.");
      setStatus("Echec recalcul planning.");
    } finally {
      setIsWorking(false);
    }
  }

  async function recomputeWorkPlan() {
    if (!intent || intent.intent !== "plan_work_blocks") {
      setError("Aucune intention de planification a recalculer.");
      return;
    }

    await recomputeWorkPlanFromIntent(intent);
  }

  async function applyStrategy(strategy: "spread" | "compact") {
    if (!intent || intent.intent !== "plan_work_blocks") return;

    const nextIntent: WorkBlocksIntent = {
      ...intent,
      constraints: {
        ...intent.constraints,
        strategy
      }
    };

    await recomputeWorkPlanFromIntent(nextIntent);
  }

  async function applyWeeklyCadencePreset(minutesPerWeek: number) {
    if (!intent || intent.intent !== "plan_work_blocks") return;

    const nextIntent: WorkBlocksIntent = {
      ...intent,
      cadence_type: "weekly",
      cadence_every_n_days: null,
      cadence_per_week_target_minutes: minutesPerWeek,
      total_effort_minutes: Math.max(
        intent.preferred_block_minutes,
        minutesPerWeek * estimateWeeksUntil(intent.deadline)
      ),
      confidence: Math.max(intent.confidence, 0.75)
    };

    await recomputeWorkPlanFromIntent(nextIntent);
  }

  function cancelWorkPlan() {
    setWorkPlan(null);
    if (intent?.intent === "plan_work_blocks") {
      setIntent(null);
    }
    setStatus("Planification annulee.");
  }

  async function confirmCreation() {
    if (!intent) {
      setError("Aucune proposition a confirmer.");
      return;
    }

    if (!session?.accessToken) {
      setError("Connectez-vous d'abord a Outlook ou Google.");
      return;
    }

    setError(null);
    setIsWorking(true);
    setStatus(`Creation dans ${calendarProvider}...`);

    try {
      if (intent.intent === "plan_work_blocks") {
        if (!workPlan) {
          throw new Error("Aucun plan de travail a confirmer.");
        }

        const idempotencyKey =
          idempotencyKeyRef.current ?? `${workPlan.planId}-${calendarProvider}`;
        idempotencyKeyRef.current = idempotencyKey;

        const payload = await postJson<{
          createdCount: number;
          provider: string;
          idempotent: boolean;
        }>("/api/work-plan", {
          action: "create",
          provider: calendarProvider,
          idempotencyKey,
          plan: workPlan
        });

        addHistory(
          `Blocs crees (${payload.provider})${payload.idempotent ? " [idempotent]" : ""}`
        );
        setStatus(`${payload.createdCount} blocs crees avec succes.`);
      } else {
        const payload = await postJson<{ eventId: string; provider: string }>(
          "/api/calendar",
          {
            intent,
            provider: calendarProvider
          }
        );
        addHistory(`Evenement cree (${payload.provider})`);
        setStatus("Evenement cree avec succes.");
      }
    } catch (e) {
      setError(e instanceof Error ? e.message : "Erreur inconnue.");
      setStatus(
        intent.intent === "plan_work_blocks"
          ? "Echec creation blocs de travail."
          : "Echec creation evenement."
      );
    } finally {
      setIsWorking(false);
    }
  }

  async function transcribeAudioBlob(blob: Blob) {
    const formData = new FormData();
    formData.append("audio", blob, "voice.webm");

    const response = await fetch("/api/transcribe", {
      method: "POST",
      body: formData
    });

    const payload = (await response.json()) as {
      text?: string;
      error?: string;
      details?: string;
    };
    if (!response.ok) {
      const detailSuffix = payload.details ? ` ${payload.details}` : "";
      throw new Error((payload.error || "Transcription impossible.") + detailSuffix);
    }

    setText((payload.text || "").trim());
  }

  function stopMediaRecorderAndStream() {
    if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
      mediaRecorderRef.current.stop();
    }

    if (mediaStreamRef.current) {
      mediaStreamRef.current.getTracks().forEach((track) => track.stop());
      mediaStreamRef.current = null;
    }
  }

  async function startMediaRecorderFallback() {
    if (!navigator.mediaDevices?.getUserMedia || typeof MediaRecorder === "undefined") {
      throw new Error("Enregistrement micro non supporte sur ce navigateur.");
    }

    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    mediaStreamRef.current = stream;

    const recorder = new MediaRecorder(stream);
    audioChunksRef.current = [];

    recorder.ondataavailable = (event) => {
      if (event.data.size > 0) {
        audioChunksRef.current.push(event.data);
      }
    };

    recorder.onerror = () => {
      setError("Erreur pendant l'enregistrement micro.");
      setIsListening(false);
      stopMediaRecorderAndStream();
    };

    recorder.onstop = async () => {
      try {
        setIsTranscribing(true);
        setStatus("Transcription audio en cours...");
        const audioBlob = new Blob(audioChunksRef.current, {
          type: recorder.mimeType || "audio/webm"
        });
        await transcribeAudioBlob(audioBlob);
        setStatus("Ecoute terminee. Vous pouvez proposer l'action.");
      } catch (e) {
        setError(e instanceof Error ? e.message : "Erreur transcription audio.");
        setStatus("Echec transcription audio.");
      } finally {
        setIsTranscribing(false);
        audioChunksRef.current = [];
        stopMediaRecorderAndStream();
      }
    };

    mediaRecorderRef.current = recorder;
    recorder.start();
  }

  async function toggleListening() {
    if (isListening) {
      if (recognitionRef.current) {
        recognitionRef.current.stop();
      }
      if (mediaRecorderRef.current) {
        stopMediaRecorderAndStream();
      }
      setIsListening(false);
      setStatus("Ecoute arretee.");
      return;
    }

    const SpeechRecognition =
      window.SpeechRecognition || window.webkitSpeechRecognition;

    if (SpeechRecognition) {
      const recognition = new SpeechRecognition();
      recognition.lang = "fr-FR";
      recognition.interimResults = true;
      recognition.continuous = false;

      recognition.onresult = (event) => {
        try {
          const results = Array.from(event.results || []);
          const nextText = results
            .slice(event.resultIndex)
            .map((result) => result?.[0]?.transcript || "")
            .join(" ");
          setText(nextText.trim());
        } catch {
          setError("Transcription navigateur instable. Essayez le mode audio fallback.");
          setIsListening(false);
          setStatus("Erreur pendant l'ecoute.");
          recognition.stop();
        }
      };

      recognition.onerror = () => {
        setError("Erreur micro. Verifiez les permissions puis reessayez.");
        setIsListening(false);
        setStatus("Erreur pendant l'ecoute.");
      };

      recognition.onend = () => {
        setIsListening(false);
        setStatus("Ecoute terminee. Vous pouvez proposer l'action.");
      };

      recognitionRef.current = recognition;
      setError(null);
      setIsListening(true);
      setStatus("Ecoute activee...");
      recognition.start();
      return;
    }

    try {
      setError(null);
      setIsListening(true);
      setStatus("Enregistrement audio en cours...");
      await startMediaRecorderFallback();
    } catch (e) {
      setError(
        e instanceof Error
          ? e.message
          : "Reconnaissance vocale non supportee sur ce navigateur."
      );
      setText((current) => current || transcriptHint);
      setIsListening(false);
    }
  }

  return (
    <main>
      <section className="panel" aria-label="Assistant Smart Calendar">
        <header className="header">
          <h1>Smart Calendar</h1>
          <p>Parlez, verifiez, confirmez.</p>
        </header>

        <article className="card auth-row">
          <h2>Connexion calendrier</h2>
          {hasSessionRefreshError ? (
            <p className="warn-text">
              Session expiree. Reconnectez-vous pour renouveler l'acces calendrier.
            </p>
          ) : null}
          {sessionStatus === "authenticated" ? (
            <>
              <p>
                Connecte en {session.provider === "google" ? "Google" : "Outlook"}
              </p>
              <button
                className="secondary"
                type="button"
                onClick={() => signOut()}
                disabled={isWorking}
              >
                Se deconnecter
              </button>
            </>
          ) : (
            <div className="auth-actions">
              <button
                className="secondary"
                type="button"
                onClick={connectOutlook}
                disabled={isWorking}
              >
                Connecter Outlook
              </button>
              <button
                className="secondary"
                type="button"
                onClick={connectGoogle}
                disabled={isWorking}
              >
                Connecter Google
              </button>
            </div>
          )}
        </article>

        <article className="card">
          <h2>Mode</h2>
          <div className="auth-actions">
            <button
              className={assistantMode === "event" ? "primary" : "secondary"}
              type="button"
              disabled={isWorking || isTranscribing}
              onClick={() => {
                setAssistantMode("event");
                setIntent(null);
                setWorkPlan(null);
              }}
            >
              Evenement unique
            </button>
            <button
              className={assistantMode === "work" ? "primary" : "secondary"}
              type="button"
              disabled={isWorking || isTranscribing}
              onClick={() => {
                setAssistantMode("work");
                setIntent(null);
                setWorkPlan(null);
              }}
            >
              Planifier mon travail
            </button>
          </div>
        </article>

        <article className="card">
          <h2>Contexte</h2>
          <input
            ref={contextFileInputRef}
            type="file"
            accept=".txt,.md,.pdf,.docx,image/png,image/jpeg,image/webp"
            onChange={handleContextFileSelected}
            hidden
          />
          <button
            className="secondary"
            type="button"
            disabled={isWorking || isTranscribing || isUploadingContext}
            onClick={() => contextFileInputRef.current?.click()}
          >
            {isUploadingContext ? "Analyse du document..." : "Ajouter un document"}
          </button>
          {contextDocument ? (
            <>
              <p>
                {contextDocument.file_name} ({Math.max(1, Math.round(contextDocument.size_bytes / 1024))} Ko)
              </p>
              <p>{contextDocument.summary}</p>
              {contextDocument.highlights.length ? (
                <ul>
                  {contextDocument.highlights.slice(0, 3).map((item) => (
                    <li key={item}>{item}</li>
                  ))}
                </ul>
              ) : null}
            </>
          ) : (
            <p>Aucun document ajoute.</p>
          )}
        </article>

        <label className="provider-picker" htmlFor="calendar-provider">
          Calendrier cible
          <select
            id="calendar-provider"
            value={calendarProvider}
            onChange={(event) =>
              setCalendarProvider(event.target.value as "outlook" | "google")
            }
            disabled={isWorking}
          >
            <option value="outlook">Outlook</option>
            <option value="google">Google Calendar</option>
          </select>
        </label>

        <button
          className="mic"
          type="button"
          aria-label="Basculer le micro"
          aria-pressed={isListening}
          onClick={toggleListening}
          disabled={isWorking || isTranscribing}
        >
          {isListening ? "■" : "●"}
        </button>

        <textarea
          value={text}
          onChange={(event) => setText(event.target.value)}
          placeholder={assistantMode === "work" ? transcriptHint : "Tapez une demande si besoin"}
          aria-label="Texte de commande"
          disabled={isWorking || isTranscribing}
        />

        <div className="actions">
          <button
            className="secondary"
            type="button"
            onClick={suggestFromText}
            disabled={isWorking || isTranscribing}
          >
            Proposer
          </button>
          <button
            className="primary"
            type="button"
            onClick={confirmCreation}
            disabled={
              isWorking ||
              isTranscribing ||
              !intent ||
              (intent.intent === "plan_work_blocks" && !workPlan) ||
              sessionStatus !== "authenticated"
            }
          >
            Confirmer et creer
          </button>
        </div>

        {intent?.intent === "create_calendar_event" ? (
          <article className="card">
            <h2>Resume de l'evenement</h2>
            <ul>
              <li>Titre: {intent.title}</li>
              <li>Debut: {intent.start_datetime}</li>
              <li>Fuseau: {intent.timezone}</li>
              <li>Duree: {intent.duration_minutes} min</li>
              <li>Participants: {intent.attendees.join(", ") || "Aucun"}</li>
            </ul>
          </article>
        ) : null}

        {intent?.intent === "plan_work_blocks" && workPlan ? (
          <article className="card">
            <h2>Resume du plan de travail</h2>
            <ul>
              <li>Tache: {workPlan.taskTitle}</li>
              <li>Deadline: {workPlan.deadline}</li>
              <li>Blocs proposes: {workPlan.blocks.length}</li>
              <li>Total planifie: {workPlan.plannedMinutes} min</li>
              <li>Temps restant: {workPlan.remainingMinutes} min</li>
              <li>Cadence: {cadenceLabel}</li>
            </ul>
            <p>
              Pourquoi ce plan: {workPlan.diagnostics.allocation_reason} - {workPlan.diagnostics.weeks_detected} semaines analysees
            </p>
            {workPlan.warnings.length ? (
              <p className="warn-text">{workPlan.warnings.join(" ")}</p>
            ) : null}
            {workPlan.blocks.length ? (
              <ul>
                {workPlan.blocks.map((block) => (
                  <li key={`${block.start}-${block.end}`}>
                    {new Date(block.start).toLocaleString("fr-FR", {
                      weekday: "short",
                      day: "2-digit",
                      month: "2-digit",
                      hour: "2-digit",
                      minute: "2-digit"
                    })}
                    {" -> "}
                    {new Date(block.end).toLocaleTimeString("fr-FR", {
                      hour: "2-digit",
                      minute: "2-digit"
                    })}
                    {` (${block.durationMinutes} min)`}
                  </li>
                ))}
              </ul>
            ) : null}
            <div className="actions">
              <button
                className="secondary"
                type="button"
                onClick={() => applyStrategy("spread")}
                disabled={isWorking || isTranscribing}
              >
                Reparti
              </button>
              <button
                className="secondary"
                type="button"
                onClick={() => applyStrategy("compact")}
                disabled={isWorking || isTranscribing}
              >
                Compact
              </button>
            </div>
            <div className="actions">
              <button
                className="secondary"
                type="button"
                onClick={() => applyWeeklyCadencePreset(30)}
                disabled={isWorking || isTranscribing}
              >
                30 min/semaine
              </button>
              <button
                className="secondary"
                type="button"
                onClick={() => applyWeeklyCadencePreset(60)}
                disabled={isWorking || isTranscribing}
              >
                1h/semaine
              </button>
            </div>
            <div className="actions">
              <button
                className="secondary"
                type="button"
                onClick={() => applyWeeklyCadencePreset(120)}
                disabled={isWorking || isTranscribing}
              >
                2h/semaine
              </button>
              <button
                className="secondary"
                type="button"
                onClick={recomputeWorkPlan}
                disabled={isWorking || isTranscribing}
              >
                Recalculer
              </button>
              <button
                className="secondary"
                type="button"
                onClick={cancelWorkPlan}
                disabled={isWorking || isTranscribing}
              >
                Annuler
              </button>
            </div>
          </article>
        ) : null}

        <p className={`status ${error ? "warn" : ""}`}>{error || status}</p>
        {error?.includes("Scopes Google insuffisants") ? (
          <button
            className="secondary scope-fix"
            type="button"
            onClick={reconnectGoogleWithScopes}
            disabled={isWorking}
          >
            Reconnecter Google (forcer permissions)
          </button>
        ) : null}
        {(error?.includes("Graph error (401)") ||
          error?.includes("Token Outlook") ||
          error?.includes("consentement Graph")) ? (
          <button
            className="secondary scope-fix"
            type="button"
            onClick={reconnectOutlook}
            disabled={isWorking}
          >
            Reconnecter Outlook
          </button>
        ) : null}

        <article className="card history">
          <h2>Dernieres actions</h2>
          {history.length ? (
            <ul>
              {history.map((item) => (
                <li key={item.id}>
                  {item.timestamp} - {item.label}
                </li>
              ))}
            </ul>
          ) : (
            <p>Aucune action pour le moment.</p>
          )}
        </article>
      </section>
    </main>
  );
}
