"use client";

import { useMemo, useCallback, useEffect, useRef } from "react";
import { z } from "zod";
import { useSettings } from "@/app/lib/settings";
import {
  listBackups,
  createBackup,
  restoreBackup,
  deleteBackup,
  backupDownloadUrl,
  fetchClients,
  listBackupJobs,
  getBackupJob,
  listBackupSchedules,
  createBackupSchedule,
  updateBackupSchedule,
  deleteBackupSchedule,
  createAthenaClient,
  type BackupRecord,
  type BackupJob,
  ApiError,
} from "@/app/lib/api";
import { Badge } from "./ui/badge";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { ScrollArea } from "./ui/scroll-area";
import { toast } from "sonner";
import {
  HardDrive,
  Clock,
  Plus,
  RefreshCw,
  Loader2,
  Trash2,
  RotateCcw,
  AlertCircle,
  Database,
  Download,
  Timer,
  Play,
  Pause,
  Calendar,
  ChevronRight,
  Activity,
  Server,
} from "lucide-react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs";
import {
  DAY_OF_WEEK,
  formatBytes,
  formatDate,
  formatDuration,
  formatRelativeTime,
  selectClass,
  StatusIcon,
  statusBg,
} from "./backups/utils";
import { JobDrilldown } from "./backups/JobDrilldown";
import {
  AddClientDialog,
  CreateBackupDialog,
  DeleteBackupDialog,
  RestoreBackupDialog,
  ScheduleDialog,
} from "./backups/Dialogs";
import { useBackupsStore } from "./backups/useBackupsStore";

const addClientSchema = z.object({
  client_name: z.string().trim().min(1, "Client name is required"),
  pg_uri: z.string().trim().min(1, "PG URI is required"),
});

export default function BackupsPage() {
  const { baseUrl, apiKey, localBackupApiKey } = useSettings();
  const ctx = useMemo(
    () => ({ baseUrl, apiKey, localBackupApiKey }),
    [baseUrl, apiKey, localBackupApiKey],
  );

  const {
    backups,
    loading,
    error,
    clients,
    filterClient,
    createOpen,
    createClient,
    createLabel,
    createPgUri,
    createUseCustomUri,
    creating,
    restoreTarget,
    restoreClient,
    restorePgUri,
    restoreUseCustomUri,
    restoring,
    deleteTarget,
    deleting,
    schedules,
    schedulesLoading,
    scheduleOpen,
    schedClient,
    schedFrequency,
    schedTime,
    schedDay,
    schedDayOfMonth,
    schedLabel,
    creatingSchedule,
    jobs,
    jobsLoading,
    drilldownJob,
    drilldownLogs,
    addClientOpen,
    newClientName,
    newClientPgUri,
    addingClient,
    setState,
    resetCreateForm,
    prepareRestoreForm,
    prepareScheduleForm,
    closeDrilldown,
    resetAddClientForm,
  } = useBackupsStore();

  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const loadBackups = useCallback(async () => {
    setState({ loading: true, error: null });
    try {
      const results = await listBackups(ctx, filterClient || undefined);
      setState({ backups: results });
    } catch (err) {
      const msg =
        err instanceof ApiError ? err.message : "Failed to load backups";
      setState({ error: msg });
    } finally {
      setState({ loading: false });
    }
  }, [ctx, filterClient, setState]);

  const loadJobs = useCallback(async () => {
    setState({ jobsLoading: true });
    try {
      const result = await listBackupJobs(ctx, { limit: 50 });
      setState({ jobs: result });
    } catch {
      // silent
    } finally {
      setState({ jobsLoading: false });
    }
  }, [ctx, setState]);

  const loadSchedules = useCallback(async () => {
    setState({ schedulesLoading: true });
    try {
      const result = await listBackupSchedules(ctx);
      setState({ schedules: result });
    } catch {
      // silent
    } finally {
      setState({ schedulesLoading: false });
    }
  }, [ctx, setState]);

  useEffect(() => {
    fetchClients(ctx)
      .then((resolvedClients) => setState({ clients: resolvedClients }))
      .catch(() => {});
    loadBackups();
    loadJobs();
    loadSchedules();
  }, [ctx, loadBackups, loadJobs, loadSchedules, setState]);

  useEffect(() => {
    const hasRunning = jobs.some(
      (j) => j.status === "running" || j.status === "pending",
    );

    if (hasRunning) {
      if (!pollRef.current) {
        pollRef.current = setInterval(() => {
          loadJobs();
          if (
            drilldownJob &&
            (drilldownJob.status === "running" ||
              drilldownJob.status === "pending")
          ) {
            getBackupJob(ctx, drilldownJob.id)
              .then(({ job, logs }) => {
                setState({ drilldownJob: job, drilldownLogs: logs });
              })
              .catch(() => {});
          }
        }, 3000);
      }
    } else if (pollRef.current) {
      clearInterval(pollRef.current);
      pollRef.current = null;
    }

    return () => {
      if (pollRef.current) clearInterval(pollRef.current);
      pollRef.current = null;
    };
  }, [jobs, ctx, drilldownJob, loadJobs, setState]);

  const handleCreate = async () => {
    if (!createUseCustomUri && !createClient) {
      toast.error("Please select a client or enter a PG URI.");
      return;
    }
    if (createUseCustomUri && !createPgUri.trim()) {
      toast.error("Enter a Postgres URI.");
      return;
    }

    setState({ creating: true });
    try {
      await createBackup(ctx, {
        client_name: createUseCustomUri
          ? createClient || "custom"
          : createClient,
        label: createLabel || undefined,
        ...(createUseCustomUri && createPgUri ? { pg_uri: createPgUri } : {}),
      } as Parameters<typeof createBackup>[1]);
      toast.success("Backup job started.");
      setState({
        createOpen: false,
        createLabel: "",
        createPgUri: "",
      });
      await Promise.all([loadBackups(), loadJobs()]);
    } catch (err) {
      const msg =
        err instanceof ApiError ? err.message : "Failed to create backup";
      toast.error(msg);
    } finally {
      setState({ creating: false });
    }
  };

  const handleRestore = async () => {
    if (!restoreTarget) return;
    if (!restoreUseCustomUri && !restoreClient) return;
    if (restoreUseCustomUri && !restorePgUri.trim()) return;

    setState({ restoring: true });
    try {
      await restoreBackup(
        ctx,
        restoreTarget.key,
        restoreUseCustomUri ? "custom" : restoreClient,
      );
      toast.success("Restore job started.");
      setState({ restoreTarget: null });
      await loadJobs();
    } catch (err) {
      const msg =
        err instanceof ApiError ? err.message : "Failed to restore backup";
      toast.error(msg);
    } finally {
      setState({ restoring: false });
    }
  };

  const handleDelete = async () => {
    if (!deleteTarget) return;
    setState({ deleting: true });
    try {
      await deleteBackup(ctx, deleteTarget.key);
      toast.success("Backup deleted.");
      setState({ deleteTarget: null });
      await loadBackups();
    } catch (err) {
      const msg =
        err instanceof ApiError ? err.message : "Failed to delete backup";
      toast.error(msg);
    } finally {
      setState({ deleting: false });
    }
  };

  const openCreate = () => {
    resetCreateForm(clients);
  };

  const openRestore = (backup: BackupRecord) => {
    prepareRestoreForm(backup);
  };

  const handleAddSchedule = async () => {
    if (!schedClient) {
      toast.error("Select a client for the schedule.");
      return;
    }
    setState({ creatingSchedule: true });
    try {
      await createBackupSchedule(ctx, {
        client_name: schedClient,
        frequency: schedFrequency,
        time: schedTime,
        day_of_week: schedFrequency === "weekly" ? schedDay : undefined,
        day_of_month:
          schedFrequency === "monthly" ? schedDayOfMonth : undefined,
        label: schedLabel || undefined,
      });
      toast.success("Backup schedule created.");
      setState({ scheduleOpen: false, schedLabel: "" });
      await loadSchedules();
    } catch (err) {
      const msg =
        err instanceof ApiError ? err.message : "Failed to create schedule";
      toast.error(msg);
    } finally {
      setState({ creatingSchedule: false });
    }
  };

  const toggleSchedule = async (id: number, enabled: boolean) => {
    try {
      await updateBackupSchedule(ctx, id, { enabled: !enabled });
      setState({
        schedules: schedules.map((s) =>
          s.id === id ? { ...s, enabled: !enabled } : s,
        ),
      });
    } catch (err) {
      const msg =
        err instanceof ApiError ? err.message : "Failed to toggle schedule";
      toast.error(msg);
    }
  };

  const removeSchedule = async (id: number) => {
    try {
      await deleteBackupSchedule(ctx, id);
      setState({ schedules: schedules.filter((s) => s.id !== id) });
      toast.success("Schedule removed.");
    } catch (err) {
      const msg =
        err instanceof ApiError ? err.message : "Failed to remove schedule";
      toast.error(msg);
    }
  };

  const openDrilldown = async (job: BackupJob) => {
    setState({ drilldownJob: job });
    try {
      const { job: resolvedJob, logs } = await getBackupJob(ctx, job.id);
      setState({ drilldownJob: resolvedJob, drilldownLogs: logs });
    } catch {
      // keep current data
    }
  };

  const handleAddClient = async () => {
    const existingNames = new Set(
      clients.map((name) => name.trim().toLowerCase()),
    );

    const parsed = addClientSchema
      .superRefine((value, ctx) => {
        if (existingNames.has(value.client_name.toLowerCase())) {
          ctx.addIssue({
            code: z.ZodIssueCode.custom,
            path: ["client_name"],
            message: `A client named '${value.client_name}' already exists.`,
          });
        }
      })
      .safeParse({
        client_name: newClientName,
        pg_uri: newClientPgUri,
      });

    if (!parsed.success) {
      toast.error(parsed.error.issues[0]?.message ?? "Invalid client payload.");
      return;
    }

    setState({ addingClient: true });
    try {
      await createAthenaClient(ctx, {
        client_name: parsed.data.client_name,
        pg_uri: parsed.data.pg_uri,
      });
      toast.success(`Client "${parsed.data.client_name}" created.`);
      resetAddClientForm();
      const updated = await fetchClients(ctx);
      setState({ clients: updated });
    } catch (err) {
      const msg =
        err instanceof ApiError ? err.message : "Failed to create client";
      toast.error(msg);
    } finally {
      setState({ addingClient: false });
    }
  };

  return (
    <div className="flex flex-1 flex-col min-h-0">
      <div className="flex items-center gap-3 border-b border-border px-6 py-3">
        <HardDrive className="h-4 w-4 text-primary" />
        <h2 className="text-sm font-semibold text-foreground">
          Database Backups
        </h2>
        {schedules.filter((s) => s.enabled).length > 0 && (
          <Badge variant="secondary" className="text-tiny tabular-nums">
            {schedules.filter((s) => s.enabled).length} active schedule
            {schedules.filter((s) => s.enabled).length !== 1 ? "s" : ""}
          </Badge>
        )}
        {jobs.filter((j) => j.status === "running").length > 0 && (
          <Badge className="text-tiny tabular-nums bg-primary-muted text-primary border border-primary-border">
            {jobs.filter((j) => j.status === "running").length} running
          </Badge>
        )}
        <div className="ml-auto flex items-center gap-2">
          <Button
            variant="outline"
            size="sm"
            className="h-7 text-caption"
            onClick={() => setState({ addClientOpen: true })}
          >
            <Server className="h-3 w-3" /> Add Client
          </Button>
        </div>
      </div>

      <Tabs defaultValue="backups" className="flex flex-col flex-1 min-h-0">
        <div className="border-b border-border px-6">
          <TabsList className="h-9">
            <TabsTrigger value="backups" className="text-xs">
              Backups
            </TabsTrigger>
            <TabsTrigger value="jobs" className="text-xs">
              <Activity className="mr-1 h-3 w-3" />
              Jobs
              {jobs.length > 0 && (
                <Badge
                  variant="secondary"
                  className="ml-1.5 text-2xs px-1 py-0 tabular-nums"
                >
                  {jobs.length}
                </Badge>
              )}
            </TabsTrigger>
            <TabsTrigger value="schedules" className="text-xs">
              <Timer className="mr-1 h-3 w-3" />
              Schedules
              {schedules.length > 0 && (
                <Badge
                  variant="secondary"
                  className="ml-1.5 text-2xs px-1 py-0 tabular-nums"
                >
                  {schedules.length}
                </Badge>
              )}
            </TabsTrigger>
          </TabsList>
        </div>

        <TabsContent value="backups" className="flex-1 m-0 overflow-hidden">
          <ScrollArea className="h-full">
            <div className="mx-auto max-w-3xl p-6 space-y-5">
              <div className="flex items-center justify-between gap-3">
                <div className="flex items-center gap-2">
                  {clients.length > 0 ? (
                    <select
                      value={filterClient}
                      onChange={(e) =>
                        setState({ filterClient: e.target.value })
                      }
                      className={`${selectClass} w-50`}
                    >
                      <option value="">All clients</option>
                      {clients.map((c) => (
                        <option key={c} value={c}>
                          {c}
                        </option>
                      ))}
                    </select>
                  ) : (
                    <Input
                      placeholder="Filter by client..."
                      value={filterClient}
                      onChange={(e) =>
                        setState({ filterClient: e.target.value })
                      }
                      className="h-9 w-50 text-xs"
                    />
                  )}
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={loadBackups}
                    disabled={loading}
                    className="h-9"
                  >
                    {loading ? (
                      <Loader2 className="h-3 w-3 animate-spin" />
                    ) : (
                      <RefreshCw className="h-3 w-3" />
                    )}
                  </Button>
                </div>
                <Button
                  size="sm"
                  onClick={openCreate}
                  disabled={creating}
                  className="h-9"
                >
                  <Plus className="h-3 w-3" /> New backup
                </Button>
              </div>

              {error && (
                <div className="flex items-center gap-2 rounded-lg border border-destructive-border bg-destructive-subtle p-3 text-xs text-destructive">
                  <AlertCircle className="h-3.5 w-3.5 shrink-0" />
                  <span className="wrap-break-word">{error}</span>
                </div>
              )}

              {!loading && !error && backups.length === 0 && (
                <div className="flex flex-col items-center justify-center py-16 text-center">
                  <div className="h-12 w-12 rounded-full bg-muted flex items-center justify-center mb-4">
                    <Clock className="h-6 w-6 text-muted-foreground-dim" />
                  </div>
                  <p className="text-sm font-medium text-muted-foreground">
                    No backups yet
                  </p>
                  <p className="text-xs text-muted-foreground-subtle mt-1 max-w-sm">
                    Click &quot;New backup&quot; to create your first database
                    backup.
                  </p>
                </div>
              )}

              {backups.length > 0 && (
                <div className="space-y-2">
                  {backups.map((b) => (
                    <div
                      key={b.key}
                      className="flex items-center gap-3 rounded-lg border border-border bg-card p-4 hover:border-border-subtle transition-colors"
                    >
                      <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-muted">
                        <Database className="h-4 w-4 text-muted-foreground" />
                      </div>
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2">
                          <p className="text-xs font-medium text-foreground truncate">
                            {b.label ?? b.id}
                          </p>
                          <Badge
                            variant="outline"
                            className="text-tiny px-1.5 py-0 shrink-0"
                          >
                            {b.client_name}
                          </Badge>
                        </div>
                        <div className="flex items-center gap-2 mt-0.5">
                          <span className="text-caption text-muted-foreground">
                            {formatRelativeTime(b.created_at)}
                          </span>
                          <span className="text-caption text-muted-foreground/40">
                            .
                          </span>
                          <span className="text-caption text-muted-foreground tabular-nums">
                            {formatBytes(b.size_bytes)}
                          </span>
                        </div>
                      </div>
                      <div className="flex items-center gap-1.5 shrink-0">
                        <a
                          href={backupDownloadUrl(ctx, b.key)}
                          target="_blank"
                          rel="noopener noreferrer"
                          className="inline-flex items-center justify-center rounded-lg border border-border bg-background h-8 w-8 text-foreground hover:bg-accent transition-colors"
                          title="Download"
                        >
                          <Download className="h-3.5 w-3.5" />
                        </a>
                        <Button
                          variant="outline"
                          size="sm"
                          className="h-8 text-caption"
                          onClick={() => openRestore(b)}
                        >
                          <RotateCcw className="h-3 w-3" /> Restore
                        </Button>
                        <Button
                          variant="ghost"
                          size="sm"
                          className="h-8 w-8 p-0 text-muted-foreground hover:text-destructive"
                          onClick={() => setState({ deleteTarget: b })}
                        >
                          <Trash2 className="h-3.5 w-3.5" />
                        </Button>
                      </div>
                    </div>
                  ))}
                </div>
              )}
            </div>
          </ScrollArea>
        </TabsContent>

        <TabsContent value="jobs" className="flex-1 m-0 overflow-hidden">
          <ScrollArea className="h-full">
            <div className="mx-auto max-w-3xl p-6 space-y-5">
              {drilldownJob ? (
                <JobDrilldown
                  job={drilldownJob}
                  logs={drilldownLogs}
                  onBack={closeDrilldown}
                />
              ) : (
                <>
                  <div className="flex items-center justify-between">
                    <div>
                      <h3 className="text-sm font-medium text-foreground">
                        Backup and Restore Jobs
                      </h3>
                      <p className="text-xs text-muted-foreground mt-0.5">
                        Track all backup and restore operations. Click to drill
                        down into details and logs.
                      </p>
                    </div>
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={loadJobs}
                      disabled={jobsLoading}
                      className="h-8"
                    >
                      {jobsLoading ? (
                        <Loader2 className="h-3 w-3 animate-spin" />
                      ) : (
                        <RefreshCw className="h-3 w-3" />
                      )}
                    </Button>
                  </div>

                  {jobs.length === 0 && (
                    <div className="flex flex-col items-center justify-center py-16 text-center">
                      <div className="h-12 w-12 rounded-full bg-muted flex items-center justify-center mb-4">
                        <Activity className="h-6 w-6 text-muted-foreground-dim" />
                      </div>
                      <p className="text-sm font-medium text-muted-foreground">
                        No jobs yet
                      </p>
                      <p className="text-xs text-muted-foreground-subtle mt-1">
                        Jobs will appear here when you create or restore a
                        backup.
                      </p>
                    </div>
                  )}

                  <div className="space-y-2">
                    {jobs.map((job) => (
                      <button
                        key={job.id}
                        onClick={() => openDrilldown(job)}
                        className="w-full text-left rounded-lg border border-border bg-card p-4 space-y-2 hover:border-primary-border transition-colors group"
                      >
                        <div className="flex items-center gap-3">
                          <StatusIcon status={job.status} />
                          <div className="flex-1 min-w-0">
                            <div className="flex items-center gap-2 flex-wrap">
                              <span className="text-xs font-medium text-foreground capitalize">
                                {job.job_type}
                              </span>
                              {job.label && (
                                <span className="text-xs text-muted-foreground truncate">
                                  {job.label}
                                </span>
                              )}
                              {job.client_name && (
                                <Badge
                                  variant="outline"
                                  className="text-tiny px-1.5 py-0"
                                >
                                  {job.client_name}
                                </Badge>
                              )}
                              <Badge
                                className={`text-tiny px-1.5 py-0 border ${statusBg[job.status] ?? ""}`}
                              >
                                {job.status}
                              </Badge>
                            </div>
                            <div className="flex items-center gap-3 mt-1 text-caption text-muted-foreground">
                              <span>{formatRelativeTime(job.started_at)}</span>
                              <span className="tabular-nums">
                                {formatDuration(
                                  job.started_at,
                                  job.completed_at,
                                )}
                              </span>
                              {job.size_bytes && (
                                <span className="tabular-nums">
                                  {formatBytes(job.size_bytes)}
                                </span>
                              )}
                            </div>
                          </div>
                          <ChevronRight className="h-4 w-4 text-muted-foreground-dim group-hover:text-foreground transition-colors shrink-0" />
                        </div>

                        {job.status === "running" && (
                          <div className="space-y-1">
                            <div className="flex items-center justify-between text-caption">
                              <span className="text-muted-foreground">
                                {job.progress_stage ?? "Processing"}
                              </span>
                              <span className="text-foreground tabular-nums">
                                {job.progress_pct ?? 0}%
                              </span>
                            </div>
                            <div className="h-1.5 w-full rounded-full bg-muted overflow-hidden">
                              <div
                                className="h-full rounded-full bg-primary transition-all duration-500"
                                style={{
                                  width: `${Math.max(job.progress_pct ?? 0, 5)}%`,
                                }}
                              />
                            </div>
                          </div>
                        )}

                        {job.error_message && (
                          <p className="text-caption text-destructive truncate">
                            {job.error_message}
                          </p>
                        )}
                      </button>
                    ))}
                  </div>
                </>
              )}
            </div>
          </ScrollArea>
        </TabsContent>

        <TabsContent value="schedules" className="flex-1 m-0 overflow-hidden">
          <ScrollArea className="h-full">
            <div className="mx-auto max-w-3xl p-6 space-y-5">
              <div className="flex items-center justify-between">
                <div>
                  <h3 className="text-sm font-medium text-foreground">
                    Backup Schedules
                  </h3>
                  <p className="text-xs text-muted-foreground mt-0.5">
                    Recurring backup jobs saved to the server with cron
                    expressions.
                  </p>
                </div>
                <Button
                  size="sm"
                  onClick={() => prepareScheduleForm(clients)}
                  className="h-9"
                >
                  <Plus className="h-3 w-3" /> New schedule
                </Button>
              </div>

              {schedulesLoading && (
                <div className="flex items-center justify-center py-8">
                  <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
                </div>
              )}

              {!schedulesLoading && schedules.length === 0 && (
                <div className="flex flex-col items-center justify-center py-16 text-center">
                  <div className="h-12 w-12 rounded-full bg-muted flex items-center justify-center mb-4">
                    <Timer className="h-6 w-6 text-muted-foreground-dim" />
                  </div>
                  <p className="text-sm font-medium text-muted-foreground">
                    No schedules
                  </p>
                  <p className="text-xs text-muted-foreground-subtle mt-1 max-w-sm">
                    Create a schedule to automatically back up your databases.
                  </p>
                </div>
              )}

              {schedules.map((s) => (
                <div
                  key={s.id}
                  className={`rounded-lg border bg-card p-4 space-y-2 transition-all ${
                    s.enabled
                      ? "border-border"
                      : "border-border-muted opacity-60"
                  }`}
                >
                  <div className="flex items-center gap-3">
                    <div
                      className={`flex h-9 w-9 shrink-0 items-center justify-center rounded-lg ${
                        s.enabled ? "bg-primary-muted" : "bg-muted"
                      }`}
                    >
                      <Calendar
                        className={`h-4 w-4 ${
                          s.enabled ? "text-primary" : "text-muted-foreground"
                        }`}
                      />
                    </div>
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-2 flex-wrap">
                        <span className="text-xs font-medium text-foreground">
                          {s.label || s.client_name}
                        </span>
                        <Badge
                          variant="outline"
                          className="text-tiny px-1.5 py-0"
                        >
                          {s.client_name}
                        </Badge>
                        <Badge
                          className={`text-tiny px-1.5 py-0 border ${
                            s.enabled
                              ? "bg-success-muted text-success border-success-border"
                              : "bg-muted text-muted-foreground border-border"
                          }`}
                        >
                          {s.enabled ? "Active" : "Paused"}
                        </Badge>
                      </div>
                      <div className="flex items-center gap-2 mt-0.5 text-caption text-muted-foreground">
                        <span className="capitalize">{s.frequency}</span>
                        <span>at {s.time_of_day?.slice(0, 5) ?? "02:00"}</span>
                        {s.frequency === "weekly" && s.day_of_week != null && (
                          <span>on {DAY_OF_WEEK[s.day_of_week]}</span>
                        )}
                        {s.frequency === "monthly" &&
                          s.day_of_month != null && (
                            <span>on day {s.day_of_month}</span>
                          )}
                        <span className="text-muted-foreground/40">.</span>
                        <span className="font-mono">{s.cron_expression}</span>
                      </div>
                    </div>
                    <div className="flex items-center gap-2 shrink-0">
                      <Button
                        variant="ghost"
                        size="sm"
                        className="h-8 w-8 p-0"
                        onClick={() => toggleSchedule(s.id, s.enabled)}
                        title={s.enabled ? "Pause" : "Resume"}
                      >
                        {s.enabled ? (
                          <Pause className="h-3.5 w-3.5" />
                        ) : (
                          <Play className="h-3.5 w-3.5" />
                        )}
                      </Button>
                      <Button
                        variant="ghost"
                        size="sm"
                        className="h-8 w-8 p-0 text-muted-foreground hover:text-destructive"
                        onClick={() => removeSchedule(s.id)}
                      >
                        <Trash2 className="h-3.5 w-3.5" />
                      </Button>
                    </div>
                  </div>
                  <div className="grid grid-cols-2 gap-2 text-caption text-muted-foreground">
                    {s.last_run_at && (
                      <span>Last run: {formatRelativeTime(s.last_run_at)}</span>
                    )}
                    {s.next_run_at && s.enabled && (
                      <span>Next run: {formatDate(s.next_run_at)}</span>
                    )}
                  </div>
                </div>
              ))}
            </div>
          </ScrollArea>
        </TabsContent>
      </Tabs>

      <CreateBackupDialog
        open={createOpen}
        onOpenChange={(open) => setState({ createOpen: open })}
        clients={clients}
        createClient={createClient}
        setCreateClient={(value) => setState({ createClient: value })}
        createLabel={createLabel}
        setCreateLabel={(value) => setState({ createLabel: value })}
        createPgUri={createPgUri}
        setCreatePgUri={(value) => setState({ createPgUri: value })}
        createUseCustomUri={createUseCustomUri}
        setCreateUseCustomUri={(value) =>
          setState({ createUseCustomUri: value })
        }
        creating={creating}
        onCreate={handleCreate}
      />

      <RestoreBackupDialog
        target={restoreTarget}
        onOpenChange={(open) => !open && setState({ restoreTarget: null })}
        clients={clients}
        restoreClient={restoreClient}
        setRestoreClient={(value) => setState({ restoreClient: value })}
        restorePgUri={restorePgUri}
        setRestorePgUri={(value) => setState({ restorePgUri: value })}
        restoreUseCustomUri={restoreUseCustomUri}
        setRestoreUseCustomUri={(value) =>
          setState({ restoreUseCustomUri: value })
        }
        restoring={restoring}
        onRestore={handleRestore}
      />

      <DeleteBackupDialog
        target={deleteTarget}
        deleting={deleting}
        onOpenChange={(open) => !open && setState({ deleteTarget: null })}
        onDelete={handleDelete}
      />

      <ScheduleDialog
        open={scheduleOpen}
        onOpenChange={(open) => setState({ scheduleOpen: open })}
        clients={clients}
        schedClient={schedClient}
        setSchedClient={(value) => setState({ schedClient: value })}
        schedFrequency={schedFrequency}
        setSchedFrequency={(value) => setState({ schedFrequency: value })}
        schedTime={schedTime}
        setSchedTime={(value) => setState({ schedTime: value })}
        schedDay={schedDay}
        setSchedDay={(value) => setState({ schedDay: value })}
        schedDayOfMonth={schedDayOfMonth}
        setSchedDayOfMonth={(value) => setState({ schedDayOfMonth: value })}
        schedLabel={schedLabel}
        setSchedLabel={(value) => setState({ schedLabel: value })}
        creatingSchedule={creatingSchedule}
        onCreate={handleAddSchedule}
      />

      <AddClientDialog
        open={addClientOpen}
        onOpenChange={(open) => setState({ addClientOpen: open })}
        newClientName={newClientName}
        setNewClientName={(value) => setState({ newClientName: value })}
        newClientPgUri={newClientPgUri}
        setNewClientPgUri={(value) => setState({ newClientPgUri: value })}
        addingClient={addingClient}
        onAddClient={handleAddClient}
      />
    </div>
  );
}
