"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import clsx from "clsx";
import { CalendarDays, Check, CheckSquare2, ListTodo, MoreHorizontal, Palette, Pencil, Plus, RefreshCw, Trash2, X } from "lucide-react";
import { api } from "@/lib/api";
import { createTranslator } from "@/lib/i18n";
import type { GoogleTask, GoogleTaskList } from "@/lib/types";

type GoogleTaskDraft = {
  title: string;
  notes: string;
  due: string;
};

const DEFAULT_DRAFT: GoogleTaskDraft = {
  title: "",
  notes: "",
  due: "",
};

const taskListColorOptions = [
  { value: 1, label: "Blue", hex: "#60a5fa" },
  { value: 2, label: "Cyan", hex: "#22d3ee" },
  { value: 3, label: "Green", hex: "#4ade80" },
  { value: 4, label: "Purple", hex: "#a78bfa" },
  { value: 5, label: "Red", hex: "#fb7185" },
  { value: 6, label: "Yellow", hex: "#facc15" },
  { value: 7, label: "Pink", hex: "#f472b6" },
  { value: 8, label: "Gray", hex: "#94a3b8" },
  { value: 9, label: "Orange", hex: "#fb923c" },
] as const;

type GoogleTasksTabProps = {
  t: ReturnType<typeof createTranslator>;
  serviceLabel?: string;
  connectPending?: boolean;
  onConnect?: () => void;
};

export function GoogleTasksTab({ t, serviceLabel = "Task", connectPending = false, onConnect }: GoogleTasksTabProps) {
  const queryClient = useQueryClient();
  const [selectedListId, setSelectedListId] = useState("@default");
  const [draft, setDraft] = useState<GoogleTaskDraft>(DEFAULT_DRAFT);
  const [editingTask, setEditingTask] = useState<GoogleTask | null>(null);
  const [dialogOpen, setDialogOpen] = useState(false);
  const [deleteConfirmTask, setDeleteConfirmTask] = useState<GoogleTask | null>(null);
  const [newListTitle, setNewListTitle] = useState("");
  const [colorListId, setColorListId] = useState("");
  const [notice, setNotice] = useState<{ tone: "success" | "error" | "info"; message: string } | null>(null);

  const status = useQuery({
    queryKey: ["google-tasks-status"],
    queryFn: api.googleTasksStatus,
    staleTime: 30_000,
    refetchOnWindowFocus: false,
  });

  const lists = useQuery({
    queryKey: ["google-task-lists"],
    queryFn: api.googleTaskLists,
    staleTime: 30_000,
    refetchOnWindowFocus: false,
    enabled: Boolean(status.data?.connected),
  });

  const tasks = useQuery({
    queryKey: ["google-tasks", selectedListId],
    queryFn: () => api.googleTasks(selectedListId),
    staleTime: 20_000,
    refetchOnWindowFocus: false,
    enabled: Boolean(status.data?.connected && selectedListId),
  });

  const taskLists = lists.data?.lists ?? [];
  const selectedList = useMemo(
    () => taskLists.find((list) => list.id === selectedListId) ?? taskLists[0] ?? null,
    [selectedListId, taskLists]
  );
  const sortedTasks = useMemo(() => {
    const items = [...(tasks.data?.tasks ?? [])];
    return items.sort((a, b) => {
      if (a.status !== b.status) return a.status === "completed" ? 1 : -1;
      return (a.due || "9999").localeCompare(b.due || "9999") || (a.position || "").localeCompare(b.position || "");
    });
  }, [tasks.data?.tasks]);

  useEffect(() => {
    if (!selectedListId && taskLists[0]?.id) setSelectedListId(taskLists[0].id);
    if (selectedListId === "@default" && taskLists[0]?.id) setSelectedListId(taskLists[0].id);
  }, [selectedListId, taskLists]);

  const createList = useMutation({
    mutationFn: api.createGoogleTaskList,
    onSuccess: async (response) => {
      setNewListTitle("");
      setSelectedListId(response.list.id);
      setNotice({ tone: "success", message: t("googleTasks.listCreated") });
      await queryClient.invalidateQueries({ queryKey: ["google-task-lists"] });
    },
    onError: (error) => setNotice({ tone: "error", message: error instanceof Error ? error.message : t("googleTasks.createListFailed") }),
  });

  const updateListColor = useMutation({
    mutationFn: ({ listId, color, rgb }: { listId: string; color: number; rgb: string }) => api.updateGoogleTaskListColor(listId, { color, rgb }),
    onSuccess: async () => {
      setColorListId("");
      setNotice({ tone: "success", message: t("googleTasks.listColorUpdated") });
      await queryClient.invalidateQueries({ queryKey: ["google-task-lists"] });
    },
    onError: (error) => setNotice({ tone: "error", message: error instanceof Error ? error.message : t("googleTasks.listColorFailed") }),
  });

  const saveTask = useMutation({
    mutationFn: async (payload: { taskId?: string; data: GoogleTaskDraft }) => {
      const listId = selectedListId || selectedList?.id || "@default";
      if (payload.taskId) {
        return api.updateGoogleTask(payload.taskId, {
          list_id: listId,
          title: payload.data.title,
          notes: payload.data.notes,
          due: payload.data.due,
          status: editingTask?.status || "needsAction",
        });
      }
      return api.createGoogleTask({ list_id: listId, title: payload.data.title, notes: payload.data.notes, due: payload.data.due });
    },
    onSuccess: async () => {
      setDialogOpen(false);
      setEditingTask(null);
      setDraft(DEFAULT_DRAFT);
      setNotice({ tone: "success", message: t("googleTasks.saved") });
      await queryClient.invalidateQueries({ queryKey: ["google-tasks", selectedListId] });
    },
    onError: (error) => setNotice({ tone: "error", message: error instanceof Error ? error.message : t("googleTasks.saveFailed") }),
  });

  const toggleTask = useMutation({
    mutationFn: (task: GoogleTask) =>
      api.updateGoogleTask(task.id, {
        list_id: selectedListId,
        title: task.title || t("task.untitled"),
        notes: task.notes,
        due: dateFromGoogleDue(task.due),
        status: task.status === "completed" ? "needsAction" : "completed",
      }),
    onSuccess: async () => {
      await queryClient.invalidateQueries({ queryKey: ["google-tasks", selectedListId] });
    },
    onError: (error) => setNotice({ tone: "error", message: error instanceof Error ? error.message : t("googleTasks.updateFailed") }),
  });

  const deleteTask = useMutation({
    mutationFn: (task: GoogleTask) => api.deleteGoogleTask(task.id, selectedListId),
    onSuccess: async () => {
      setNotice({ tone: "success", message: t("googleTasks.deleted") });
      await queryClient.invalidateQueries({ queryKey: ["google-tasks", selectedListId] });
    },
    onError: (error) => setNotice({ tone: "error", message: error instanceof Error ? error.message : t("googleTasks.deleteFailed") }),
  });

  function openNewTask() {
    setEditingTask(null);
    setDraft(DEFAULT_DRAFT);
    setDialogOpen(true);
  }

  function openEditTask(task: GoogleTask) {
    setEditingTask(task);
    setDraft({ title: task.title, notes: task.notes, due: dateFromGoogleDue(task.due) });
    setDialogOpen(true);
  }

  const writable = Boolean(status.data?.writable);
  const needsReconnect = Boolean(status.data?.connected && !status.data?.writable);
  const needsConnect = !status.isLoading && (!status.data?.connected || needsReconnect);

  if (needsConnect) {
    return (
      <section className="min-h-0 overflow-auto p-2 lg:p-3">
        <div className="control-surface rounded-xl p-3 sm:p-3">
          <div className="mb-4">
            <p className="text-xs font-black uppercase text-[var(--accent)]">{serviceLabel}</p>
            <h2 className="text-xl font-black">{t("task.workspace")}</h2>
          </div>

          <div className="rounded-xl border border-[color-mix(in_srgb,var(--accent)_16%,white)] bg-[linear-gradient(135deg,rgba(236,253,245,0.95)_0%,rgba(240,249,255,0.95)_100%)] p-4">
            <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
              <div>
                <h3 className="text-lg font-black text-slate-900">{t("calendar.connectTitle", { service: serviceLabel })}</h3>
              </div>
              <button type="button" onClick={onConnect} disabled={connectPending || !onConnect} className="theme-button h-11 px-5 transition hover:-translate-y-0.5 disabled:opacity-50">
                {connectPending ? t("calendar.connecting") : t("calendar.connect", { service: serviceLabel })}
              </button>
            </div>
          </div>

          <div className="mt-1 rounded-lg border border-[color-mix(in_srgb,var(--accent)_18%,white)] bg-[color-mix(in_srgb,var(--accent)_8%,white)] px-4 py-3 text-sm font-semibold text-[var(--accent)]">
            {needsReconnect ? t("googleTasks.reconnectAccess") : t("googleTasks.connectAgain")}
          </div>
        </div>
      </section>
    );
  }

  return (
    <>
    <section className="grid h-full min-h-0 overflow-hidden p-2 lg:p-3">
      <div className="control-surface grid min-h-0 overflow-hidden rounded-xl p-3 sm:p-3">
        <div className="grid min-h-0 min-w-0 gap-3 overflow-hidden lg:grid-cols-[minmax(0,1fr)_300px]">
      <section className="order-1 min-h-0 min-w-0 overflow-hidden rounded-xl border border-slate-200 bg-white">
        <div className="flex flex-wrap items-center justify-between gap-3 border-b border-slate-200 px-4 py-3">
          <div className="min-w-0">
            <p className="text-xs font-black uppercase text-[var(--accent)]">{serviceLabel}</p>
            <h2 className="truncate text-xl font-black text-slate-950">{selectedList?.title || t("task.workspace")}</h2>
            <p className="text-sm font-semibold text-slate-500">{t("googleTasks.loadedCount", { count: sortedTasks.length })}</p>
          </div>
          <button
            type="button"
            onClick={openNewTask}
            disabled={!writable || !selectedListId}
            className="theme-button h-10 shrink-0 px-3 text-sm disabled:cursor-not-allowed disabled:opacity-50"
          >
            <Plus size={16} /> {t("task.newTask")}
          </button>
        </div>

        {notice ? (
          <div className={clsx("mx-4 mt-3 flex items-start justify-between gap-3 rounded-lg border px-3 py-2 text-sm font-semibold", notice.tone === "error" ? "border-rose-200 bg-rose-50 text-rose-800" : notice.tone === "success" ? "border-emerald-200 bg-emerald-50 text-emerald-800" : "border-slate-200 bg-slate-50 text-slate-700")}>
            <span className="min-w-0 break-words">{notice.message}</span>
            <button type="button" onClick={() => setNotice(null)} className="shrink-0 text-current/70 hover:text-current" title={t("common.close")} aria-label={t("common.close")}><X size={16} /></button>
          </div>
        ) : null}

        <div className="mx-4 mt-3 grid gap-2 rounded-lg border border-slate-200 bg-slate-50 p-3 lg:hidden">
          <label className="grid gap-1 text-xs font-black uppercase tracking-[0.08em] text-slate-500">
            {t("task.taskList")}
            <select
              value={selectedListId}
              onChange={(event) => setSelectedListId(event.target.value)}
              className="h-10 min-w-0 rounded-lg border border-slate-200 bg-white px-3 text-sm font-semibold normal-case tracking-normal text-slate-700 outline-none focus:border-cyan-400 focus:ring-4 focus:ring-cyan-100"
              disabled={lists.isLoading || !taskLists.length}
            >
              {!taskLists.length ? <option value="">{t("task.noTaskListsFound")}</option> : null}
              {taskLists.map((list) => (
                <option key={list.id} value={list.id}>{list.title || t("task.heading")}</option>
              ))}
            </select>
          </label>
        </div>

        <div className="grid min-h-0 gap-2 overflow-auto p-4">
          {tasks.isLoading ? <p className="rounded-lg bg-slate-50 p-4 text-sm font-semibold text-slate-500">{t("common.loading")}</p> : null}
          {!tasks.isLoading && !sortedTasks.length ? (
            <div className="grid place-items-center rounded-xl border border-dashed border-slate-200 bg-slate-50 px-4 py-12 text-center">
              <CheckSquare2 className="mb-3 text-slate-400" size={32} />
              <p className="text-sm font-bold text-slate-900">{t("task.noTasks")}</p>
            </div>
          ) : null}
          {sortedTasks.map((task) => {
            const done = task.status === "completed";
            return (
              <article key={task.id} className={clsx("min-w-0 rounded-xl border px-3 py-2.5 transition", done ? "border-emerald-200 bg-emerald-50/60" : "border-slate-200 bg-white")}>
                <div className="flex min-w-0 items-start gap-3">
                  <button
                    type="button"
                    onClick={() => void toggleTask.mutateAsync(task)}
                    disabled={!writable || toggleTask.isPending}
                    className={clsx("grid h-10 w-10 shrink-0 place-items-center rounded-lg transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-500 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", done ? "text-emerald-600" : "text-slate-400 hover:bg-slate-100")}
                    title={done ? t("task.markIncomplete") : t("task.markComplete")}
                    aria-label={done ? "Mark task incomplete" : "Mark task complete"}
                  >
                    <span className={clsx("grid h-6 w-6 place-items-center rounded-md border", done ? "border-emerald-500 bg-emerald-500 text-white" : "border-slate-300 bg-white text-transparent hover:text-slate-400")}>
                      <CheckSquare2 size={15} />
                    </span>
                  </button>
                  <div className="min-w-0 flex-1">
                    <button
                      type="button"
                      onClick={() => openEditTask(task)}
                      disabled={!writable}
                      className={clsx(
                        "rounded-md text-left text-sm font-black leading-5 transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cyan-500 focus-visible:ring-offset-2 disabled:cursor-not-allowed",
                        done ? "text-emerald-900 line-through" : "text-slate-950",
                        writable ? "hover:text-cyan-700" : "opacity-70"
                      )}
                      title={writable ? t("common.edit") : undefined}
                    >
                      {task.title || t("task.untitled")}
                    </button>
                    <div className="mt-1 flex flex-wrap gap-3 text-xs font-semibold text-slate-500">
                      {task.due ? <span className="inline-flex items-center gap-1.5"><CalendarDays size={13} /> {formatDue(task.due)}</span> : <span>{t("task.noDueDate")}</span>}
                      {task.notes ? <span className="break-words">{task.notes}</span> : null}
                    </div>
                  </div>
                  <div className="flex shrink-0 gap-1">
                    <button type="button" onClick={() => openEditTask(task)} disabled={!writable} className="grid h-8 w-8 place-items-center rounded-lg text-slate-500 hover:bg-slate-100 disabled:opacity-40" title={t("common.edit")} aria-label={t("common.edit")}><Pencil size={15} /></button>
                    <button type="button" onClick={() => setDeleteConfirmTask(task)} disabled={!writable || deleteTask.isPending} className="grid h-8 w-8 place-items-center rounded-lg text-rose-600 hover:bg-rose-50 disabled:opacity-40" title={t("common.delete")} aria-label={t("common.delete")}><Trash2 size={15} /></button>
                  </div>
                </div>
              </article>
            );
          })}
        </div>
      </section>

      <aside className="order-2 hidden min-h-0 min-w-0 overflow-auto rounded-xl border border-slate-200 bg-white p-3 lg:block">
        <div className="mb-3 flex items-center justify-between gap-2">
          <div>
            <h2 className="text-base font-black text-slate-950">{t("task.taskList")}</h2>
            <p className="text-xs font-semibold text-slate-500">{t("googleTasks.service")}</p>
          </div>
          <button
            type="button"
            onClick={() => {
              void lists.refetch();
              void tasks.refetch();
            }}
            className="grid h-9 w-9 place-items-center rounded-lg border border-slate-200 bg-white text-slate-600 hover:bg-slate-50 disabled:opacity-50"
            disabled={lists.isFetching || tasks.isFetching}
            title={t("task.refreshLists")}
            aria-label={t("task.refreshLists")}
          >
            <RefreshCw size={16} className={clsx((lists.isFetching || tasks.isFetching) && "animate-spin")} />
          </button>
        </div>

        {status.isLoading ? <p className="rounded-lg bg-slate-50 p-3 text-sm font-semibold text-slate-600">{t("googleTasks.loading")}</p> : null}
        {!status.isLoading && !status.data?.connected ? (
          <div className="grid gap-3 rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm font-semibold text-amber-900">
            <span>{t("googleTasks.connectAgain")}</span>
            <button type="button" onClick={onConnect} disabled={connectPending || !onConnect} className="theme-button h-10 w-full px-4 text-sm disabled:opacity-60">
              {connectPending ? t("calendar.connecting") : t("calendar.connect", { service: "Task" })}
            </button>
          </div>
        ) : null}
        {needsReconnect ? (
          <div className="mb-3 grid gap-3 rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm font-semibold text-amber-900">
            <span>{t("googleTasks.reconnectAccess")}</span>
            <button type="button" onClick={onConnect} disabled={connectPending || !onConnect} className="theme-button h-10 w-full px-4 text-sm disabled:opacity-60">
              {connectPending ? t("calendar.connecting") : t("calendar.connect", { service: "Task" })}
            </button>
          </div>
        ) : null}

        <div className="grid min-w-0 gap-2">
          {taskLists.map((list) => {
            const listColor = list.rgb || taskListColorOptions.find((option) => option.value === list.color)?.hex || "";
            const colorOpen = colorListId === list.id;
            return (
              <div key={list.id} className="relative min-w-0">
                <div className={clsx("flex min-w-0 items-center gap-1 rounded-lg border transition", selectedListId === list.id ? "border-cyan-300 bg-cyan-50 text-cyan-950" : "border-slate-200 bg-white text-slate-700 hover:bg-slate-50")} style={listColor ? { borderColor: selectedListId === list.id ? listColor : undefined } : undefined}>
                  <button type="button" onClick={() => setSelectedListId(list.id)} className="flex min-w-0 flex-1 items-center gap-2 px-3 py-2 text-left">
                    <span className="h-2.5 w-2.5 shrink-0 rounded-full border border-black/5" style={listColor ? { backgroundColor: listColor } : undefined} />
                    <span className="min-w-0 flex-1 break-words text-sm font-bold">{list.title || t("task.heading")}</span>
                    <ListTodo size={15} className="shrink-0" />
                  </button>
                  {writable ? (
                    <button type="button" onClick={() => setColorListId(colorOpen ? "" : list.id)} className="mr-1 grid h-8 w-8 shrink-0 place-items-center rounded-md text-slate-500 hover:bg-white hover:text-slate-900" title={t("task.listActions")} aria-label={t("task.listActions")} aria-expanded={colorOpen}>
                      <MoreHorizontal size={16} />
                    </button>
                  ) : null}
                </div>
                {colorOpen ? (
                  <div className="mt-2 rounded-lg border border-slate-200 bg-white p-3 shadow-lg">
                    <div className="mb-2 flex items-center gap-2 text-xs font-black uppercase tracking-[0.12em] text-slate-400"><Palette size={13} />{t("task.listColor")}</div>
                    <div className="grid grid-cols-5 gap-2">
                      {taskListColorOptions.map((option) => {
                        const active = listColor.toLowerCase() === option.hex.toLowerCase();
                        return <button key={option.value} type="button" onClick={() => updateListColor.mutate({ listId: list.id, color: option.value, rgb: option.hex })} disabled={updateListColor.isPending} className={clsx("grid h-8 w-8 place-items-center rounded-full border transition", active ? "border-slate-900" : "border-slate-200 hover:border-slate-400")} style={{ backgroundColor: option.hex }} aria-label={`${t("task.listColor")} ${option.label}`} title={option.label}>{active ? <Check size={14} className="text-white drop-shadow" /> : null}</button>;
                      })}
                    </div>
                  </div>
                ) : null}
              </div>
            );
          })}
        </div>

        {writable ? (
          <form
            className="mt-3 grid gap-2"
            onSubmit={(event) => {
              event.preventDefault();
              const title = newListTitle.trim();
              if (!title) return;
              void createList.mutateAsync({ title });
            }}
          >
            <input
              value={newListTitle}
              onChange={(event) => setNewListTitle(event.target.value)}
              className="min-w-0 flex-1 rounded-lg border border-slate-200 px-3 py-2 text-sm font-semibold outline-none focus:border-cyan-400 focus:ring-4 focus:ring-cyan-100"
              placeholder={t("task.newListName")}
            />
            <button
              type="submit"
              disabled={createList.isPending || !newListTitle.trim()}
              className="theme-button h-10 w-full justify-center px-3 text-sm disabled:opacity-50"
              title={t("task.newList")}
              aria-label={t("task.newList")}
            >
              <Plus size={16} /> {t("task.newList")}
            </button>
          </form>
        ) : null}
      </aside>
        </div>
      </div>
    </section>

      {deleteConfirmTask ? (
        <TaskDeleteConfirmDialog
          title="Delete task?"
          message="This removes the task from this task list."
          confirmLabel="Delete"
          busy={deleteTask.isPending}
          onClose={() => setDeleteConfirmTask(null)}
          onConfirm={async () => {
            const task = deleteConfirmTask;
            if (!task) return;
            try {
              await deleteTask.mutateAsync(task);
              setDeleteConfirmTask(null);
            } catch {
              // Mutation onError surfaces the notice; keep the dialog open for retry/cancel.
            }
          }}
        />
      ) : null}

      {dialogOpen ? (
        <div className="fixed inset-0 z-50 grid place-items-center bg-slate-950/30 p-4">
          <form
            className="w-full max-w-xl rounded-xl border border-slate-200 bg-white p-4 shadow-2xl"
            onSubmit={(event) => {
              event.preventDefault();
              if (!draft.title.trim()) {
                setNotice({ tone: "error", message: t("task.subjectRequired") });
                return;
              }
              void saveTask.mutateAsync({ taskId: editingTask?.id, data: draft });
            }}
          >
            <div className="mb-4 flex items-center justify-between gap-3">
              <h2 className="text-lg font-black text-slate-950">{editingTask ? t("task.editTask") : t("task.newTask")}</h2>
              <button type="button" onClick={() => setDialogOpen(false)} className="grid h-9 w-9 place-items-center rounded-lg text-slate-500 hover:bg-slate-100" title={t("common.close")} aria-label={t("common.close")}>
                <X size={17} />
              </button>
            </div>
            <div className="grid gap-3">
              <label className="grid gap-1 text-sm font-bold text-slate-700">
                {t("task.subject")}
                <input value={draft.title} onChange={(event) => setDraft((current) => ({ ...current, title: event.target.value }))} className="rounded-lg border border-slate-200 px-3 py-2 text-sm font-semibold outline-none focus:border-cyan-400 focus:ring-4 focus:ring-cyan-100" autoFocus />
              </label>
              <label className="grid gap-1 text-sm font-bold text-slate-700">
                {t("task.dueDate")}
                <input type="date" value={draft.due} onChange={(event) => setDraft((current) => ({ ...current, due: event.target.value }))} className="rounded-lg border border-slate-200 px-3 py-2 text-sm font-semibold outline-none focus:border-cyan-400 focus:ring-4 focus:ring-cyan-100" />
              </label>
              <label className="grid gap-1 text-sm font-bold text-slate-700">
                {t("task.detailsPlaceholder")}
                <textarea value={draft.notes} onChange={(event) => setDraft((current) => ({ ...current, notes: event.target.value }))} rows={5} className="resize-none rounded-lg border border-slate-200 px-3 py-2 text-sm font-semibold outline-none focus:border-cyan-400 focus:ring-4 focus:ring-cyan-100" />
              </label>
            </div>
            <div className="mt-4 flex justify-end gap-2">
              <button type="button" onClick={() => setDialogOpen(false)} className="rounded-lg border border-slate-200 px-4 py-2 text-sm font-black text-slate-700 hover:bg-slate-50">{t("common.cancel")}</button>
              <button type="submit" disabled={saveTask.isPending || !draft.title.trim()} className="rounded-lg bg-cyan-600 px-4 py-2 text-sm font-black text-white hover:bg-cyan-700 disabled:bg-slate-300">
                {saveTask.isPending ? t("common.saving") : t("common.save")}
              </button>
            </div>
          </form>
        </div>
      ) : null}
    </>
  );
}


function TaskDeleteConfirmDialog({
  title,
  message,
  confirmLabel,
  busy,
  onClose,
  onConfirm,
}: {
  title: string;
  message: string;
  confirmLabel: string;
  busy: boolean;
  onClose: () => void;
  onConfirm: () => void | Promise<void>;
}) {
  const dialogRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const previous = document.activeElement instanceof HTMLElement ? document.activeElement : null;
    const firstButton = dialogRef.current?.querySelector<HTMLButtonElement>("button");
    firstButton?.focus();
    function onKeyDown(event: KeyboardEvent) {
      if (event.key === "Escape") onClose();
    }
    window.addEventListener("keydown", onKeyDown);
    return () => {
      window.removeEventListener("keydown", onKeyDown);
      previous?.focus();
    };
  }, [onClose]);

  return (
    <div className="fixed inset-0 z-[10001] grid place-items-center bg-slate-950/35 p-4 backdrop-blur-sm">
      <div ref={dialogRef} role="dialog" aria-modal="true" aria-label={title} className="w-full max-w-md rounded-xl border border-slate-200 bg-white p-5 shadow-soft">
        <h3 className="text-lg font-black text-slate-900">{title}</h3>
        <p className="mt-2 text-sm leading-6 text-slate-600">{message}</p>
        <div className="mt-5 flex flex-wrap justify-end gap-2">
          <button type="button" onClick={onClose} className="theme-button-soft h-10 px-4 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--accent)] focus-visible:ring-offset-2" disabled={busy}>Cancel</button>
          <button type="button" onClick={() => void onConfirm()} className="h-10 rounded-lg bg-red-600 px-4 text-sm font-bold text-white hover:bg-red-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-300 focus-visible:ring-offset-2" disabled={busy}>
            {busy ? "Working…" : confirmLabel}
          </button>
        </div>
      </div>
    </div>
  );
}
function dateFromGoogleDue(value: string) {
  return value ? value.slice(0, 10) : "";
}

function formatDue(value: string) {
  if (!value) return "";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value.slice(0, 10);
  return date.toLocaleDateString(undefined, { year: "numeric", month: "short", day: "numeric" });
}
