import type { CoreMemberAccountType } from "@/lib/features/members/types";
import { searchMemberAccountTypes } from "@/lib/features/members/query";
import { deleteCampaign, sendCampaign, stopCampaign, resumeCampaign, activateCampaign } from "@/lib/features/notifications/action";
import { Button, Flex, Group, Select, Stack, TextInput, Title, Pagination, Text, Drawer, Tabs, Card, Checkbox, Table, Grid, Box, Badge, SimpleGrid, Tooltip, SegmentedControl, Skeleton, Collapse } from "@mantine/core";
import { useDebouncedValue, useDisclosure } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
import { IconRefresh, IconSearch, IconPlus, IconHistory, IconTrash, IconArrowLeft, IconSettings, IconExclamationCircleFilled, IconMail, IconDeviceAnalytics, IconSend, IconEye, IconEyeOff, IconFilter, IconCalendar, IconChevronDown, IconChevronUp } from "@tabler/icons-react";
import { useCampaignSocket } from "@/hooks/useCampaignSocket";
import React, { useEffect, useState, useMemo, useRef } from "react";

// Survives remounts but not a real page load, which is exactly the lifetime we
// want: reset the filters once per hard reload and never again.
let hasHandledReload = false;

import ReactECharts from "echarts-for-react";
import { useNavigate, useSearchParams } from "react-router";
import AddNotification from "./(widgets)/addNotification";
import CampaignsTable from "./(widgets)/CampaignsTable";
import Filters, { type FilterState } from "./(widgets)/CampaignsTable/Filters";
import type { Campaign } from "./(widgets)/CampaignsTable/types";
import { RecipientsDrawer } from "./(widgets)/RecipientsDrawer";
import { ContextualLogs } from "@/components/blocks/activity-logs/ContextualLogs";
import ConfirmAlert from "@/components/blocks/ConfirmAlert/confirmAlert";

import { DatePickerInput } from '@mantine/dates';
import { listCampaigns, getCampaignAnalytics, type CampaignAnalytics } from "@/lib/features/notifications/action";



interface NotificationsClientsPageProps {
  initialCampaigns: Campaign[];
  totalCount: number;
  accountTypes?: CoreMemberAccountType[];
}

const NotificationsClientsPage: React.FC<NotificationsClientsPageProps> = ({
  initialCampaigns,
  totalCount: initialTotalCount,
  accountTypes: initialAccountTypes
}) => {
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();

  const [campaigns, setCampaigns] = useState<Campaign[]>(initialCampaigns);
  const [totalCount, setTotalCount] = useState(initialTotalCount);
  const [accountTypes, setAccountTypes] = useState<CoreMemberAccountType[]>(
    (initialAccountTypes ?? []).filter((t: any) => t.name !== "Karma Lite")
  );

  useEffect(() => {
    if (initialAccountTypes) return;
    let cancelled = false;
    (async () => {
      try {
        const res = await searchMemberAccountTypes(1, 100);
        if (res.success && !cancelled) {
          const types = res.data?.account_types ?? [];
          setAccountTypes(types.filter((t: any) => t.name !== "Karma Lite"));
        }
      } catch (err) {
        console.error("Failed to load account types:", err);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [initialAccountTypes]);


  // NOTE: deliberately no effect syncing `initialCampaigns` into state. The
  // loader hands back a hardcoded empty list, so re-running it used to blank
  // the table (`campaigns = []`) and only the fetch effect below could refill
  // it — which it wouldn't unless a URL param happened to change. That's what
  // left the list showing empty after creating a campaign. The loader values
  // are used once, for the initial useState above.

  const { generalUpdate, generalStatusUpdate } = useCampaignSocket();

  useEffect(() => {
    if (generalUpdate) {
      setCampaigns((prev) =>
        prev.map((c) =>
          c.id === generalUpdate.campaignId
            ? { ...c, sent_count: generalUpdate.sent, total_count: generalUpdate.total }
            : c
        )
      );
    }
  }, [generalUpdate]);

  useEffect(() => {
    if (generalStatusUpdate) {
      setCampaigns((prev) =>
        prev.map((c) => {
          if (c.id === generalStatusUpdate.campaignId) {
            const updated = { ...c, status: generalStatusUpdate.status };
            if (generalStatusUpdate.status === 'SENT' || generalStatusUpdate.status === 'COMPLETED') {
              updated.updated_at = new Date().toISOString();
            }
            return updated;
          }
          return c;
        })
      );
    }
  }, [generalStatusUpdate]);

  const [loading, setLoading] = useState(false);
  const [refreshing, setRefreshing] = useState(false);
  const [sendingId, setSendingId] = useState<string | null>(null);

  const page = parseInt(searchParams.get("page") || "1", 10);
  const pageSize = searchParams.get("pageSize") || "10";
  const search = searchParams.get("search") || "";
  const status = searchParams.get("status") || null;

  const fromDate = searchParams.get("fromDate") || null;
  const toDate = searchParams.get("toDate") || null;

  const [localSearch, setLocalSearch] = useState(search);
  const [debouncedSearch] = useDebouncedValue(localSearch, 200);

  // Derived from the URL, never held separately. Previously `filterState` was
  // its own useState, so when the URL lost its `status` param the server-side
  // filter vanished while the client-side one survived — the table then filtered
  // a full page of mixed campaigns down to nothing. One source of truth avoids
  // that class of divergence entirely, and makes filters shareable + reset on
  // reload for free.
  const platformParam = searchParams.get("platform") || "";
  const filterState: FilterState = useMemo(
    () => ({
      platform: platformParam ? platformParam.split(",") : [],
      status: status ? status.split(",") : [],
    }),
    [platformParam, status],
  );

  const handleFiltersChange = (filters: FilterState) => {
    updateParams({
      status: filters.status.length > 0 ? filters.status.join(",") : null,
      platform: filters.platform.length > 0 ? filters.platform.join(",") : null,
      page: 1,
    });
  };

  // Graph + summary cards are backed by a dedicated analytics endpoint,
  // scoped to the selected date window and independent of the campaigns
  // table's own page/pageSize/search/status filters.
  const [analytics, setAnalytics] = useState<CampaignAnalytics>({
    buckets: [],
    summary: { campaignsSent: 0, sends: 0, received: 0, impressions: 0, opens: 0 },
  });
  const campaignStats = analytics.summary;
  const dailyChartData = analytics.buckets;

  const [showSends, setShowSends] = useState(true);
  const [showReceived, setShowReceived] = useState(true);
  const [showImpressions, setShowImpressions] = useState(true);
  const [showOpens, setShowOpens] = useState(true);
  const [timeRange, setTimeRange] = useState<"7d" | "30d" | "90d">("30d");
  const [graphReady, setGraphReady] = useState(false);
  const [analyticsExpanded, setAnalyticsExpanded] = useState(false);

  const [dateRange, setDateRange] = useState<[Date | null, Date | null]>([
    fromDate ? new Date(`${fromDate}T00:00:00`) : null,
    toDate ? new Date(`${toDate}T00:00:00`) : null
  ]);
  const isCustomActive = !!(dateRange[0] && dateRange[1]);

  // A hard reload starts from a clean slate. Nothing wipes the URL any more, so
  // the old cache-and-restore dance (stashing searchParams in a module variable
  // and putting them back after a navigate) is gone — it existed only to undo
  // the param loss described in refreshData below, and it cost an extra fetch
  // with the wrong params every time.
  useEffect(() => {
    const navEntries = performance.getEntriesByType("navigation");
    const isReload = navEntries.length > 0 && (navEntries[0] as PerformanceNavigationTiming).type === "reload";

    if (isReload && !hasHandledReload) {
      hasHandledReload = true;
      setSearchParams(new URLSearchParams(), { replace: true });
      setDateRange([null, null]);
      setLocalSearch("");
    }
  }, [setSearchParams]);

  // ref to imperatively open the hidden DatePickerInput popover
  const datePickerRef = useRef<HTMLButtonElement>(null);
  const [pickerOpen, setPickerOpen] = useState(false);

  const formatDate = (date: Date) => {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, "0");
    const day = String(date.getDate()).padStart(2, "0");
    return `${year}-${month}-${day}`;
  };

  const formatShort = (date: Date) =>
    date.toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "2-digit" });

  const [chartExpanded, setChartExpanded] = useState(false);
  const chartRef = useRef<any>(null);
  useEffect(() => {
    const chart = chartRef.current?.getEchartsInstance();
    if (chart) {
      setTimeout(() => { chart.resize(); }, 100);
    }
  }, [chartExpanded]);

  const formatStatNumber = (num: number) => {
    if (num >= 1000000) return (num / 1000000).toFixed(1).replace(/\.0$/, "") + "m";
    if (num >= 1000) return (num / 1000).toFixed(1).replace(/\.0$/, "") + "k";
    return num.toString();
  };

  useEffect(() => {
    if (!analyticsExpanded) return;
    let cancelled = false;
    const fetchAnalytics = async () => {
      setGraphReady(false);
      try {
        const params = dateRange[0] && dateRange[1]
          ? { fromDate: formatDate(dateRange[0]), toDate: formatDate(dateRange[1]) }
          : { range: timeRange };
        const res = await getCampaignAnalytics(params);
        if (!cancelled && res.success) {
          setAnalytics(res.data as CampaignAnalytics);
        }
      } catch (error) {
        console.error("Failed fetching campaign analytics:", error);
      } finally {
        if (!cancelled) setGraphReady(true);
      }
    };
    fetchAnalytics();
    return () => { cancelled = true; };
  }, [timeRange, dateRange, analyticsExpanded]);

  const chartData = useMemo(() => {
    const chartHeaders = ["Date"];
    if (showSends) chartHeaders.push("Sends");
    if (showReceived) chartHeaders.push("Received");
    if (showImpressions) chartHeaders.push("Impressions");
    if (showOpens) chartHeaders.push("Open count");

    const chartRows = dailyChartData.map((d) => {
      const row: (string | number)[] = [d.date];
      if (showSends) row.push(d.sends);
      if (showReceived) row.push(d.received);
      if (showImpressions) row.push(d.impressions);
      if (showOpens) row.push(d.opens);
      return row;
    });

    return [chartHeaders, ...chartRows];
  }, [dailyChartData, showSends, showReceived, showImpressions, showOpens]);

  useEffect(() => {
    if (debouncedSearch !== search) {
      updateParams({ search: debouncedSearch, page: 1 });
    }
  }, [debouncedSearch]);

  const updateParams = (newParams: Record<string, string | number | undefined | null>) => {
    const current = new URLSearchParams(searchParams);
    Object.keys(newParams).forEach(key => {
      if (newParams[key] === undefined || newParams[key] === null || newParams[key] === "") {
        current.delete(key);
      } else {
        current.set(key, String(newParams[key]));
      }
    });
    if (newParams.page === undefined && (newParams.search !== undefined || newParams.status !== undefined || newParams.fromDate !== undefined)) {
      current.set("page", "1");
    }
    setSearchParams(current);
  };

  /**
   * Refetch the current view without touching the URL.
   *
   * Every mutation used to call `navigate(".", { replace: true })` to force a
   * reload. But `navigate(".")` resolves to the pathname alone and DISCARDS the
   * search string, so search / pageSize / status / sort were all thrown away —
   * which is why a keyword search cleared itself and a pageSize of 100 snapped
   * back to the default 10 the moment you created a campaign. Bumping a key the
   * fetch effect depends on refetches the exact same view instead.
   */
  const [refreshKey, setRefreshKey] = useState(0);
  const refreshData = () => setRefreshKey((k) => k + 1);

  const sortBy = searchParams.get("sortBy") || undefined;
  const sortOrder = searchParams.get("sortOrder") || undefined;

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      try {
        const res = await listCampaigns(
          (page - 1) * Number(pageSize),
          Number(pageSize),
          {
            search,
            status: status || undefined,
            platform: platformParam || undefined,
            fromDate: fromDate || undefined,
            toDate: toDate || undefined,
            sortBy,
            sortOrder,
          }
        );
        if (res.success) {
          setCampaigns((res.data as any).items);
          setTotalCount((res.data as any).total);
        }
      } catch (error) {
        console.error("Failed fetching records:", error);
      } finally {
        setLoading(false);
        setRefreshing(false); // fetch settled → stop the Refresh button spinner
      }
    };
    fetchData();
  }, [page, pageSize, search, status, platformParam, fromDate, toDate, sortBy, sortOrder, refreshKey]);

  const [addDrawerOpened, { open: openAddDrawer, close: closeAddDrawer }] = useDisclosure(false);
  const [duplicateData, setDuplicateData] = useState<Campaign | null>(null);
  const [recipientsOpened, { open: openRecipients, close: closeRecipients }] = useDisclosure(false);
  const [selectedCampaign, setSelectedCampaign] = useState<Campaign | null>(null);
  const [historyOpened, { open: openHistory, close: closeHistory }] = useDisclosure(false);
  const [confirmOpened, { open: openConfirm, close: closeConfirm }] = useDisclosure(false);
  const [confirmConfig, setConfirmConfig] = useState<{
    title: string;
    message: string;
    onConfirm: () => void;
  }>({ title: "", message: "", onConfirm: () => { } });

  const showConfirm = (title: string, message: string, onConfirm: () => void) => {
    setConfirmConfig({ title, message, onConfirm });
    openConfirm();
  };

  const handleDelete = async (id: string) => {
    showConfirm("Delete Campaign", "Are you sure you want to delete this campaign?", async () => {
      try {
        const res = await deleteCampaign(id);
        if (res.success) {
          notifications.show({ title: "Success", message: "Campaign deleted successfully", color: "green" });
          refreshData();
        } else {
          notifications.show({ title: "Error", message: res.message || "Failed to delete campaign", color: "red" });
        }
      } catch (e) {
        notifications.show({ title: "Error", message: "An unexpected error occurred", color: "red" });
      } finally {
        closeConfirm();
      }
    });
  };

  const handleActivate = async (id: string) => {
    showConfirm("Restore Campaign", "Are you sure you want to restore this campaign?", async () => {
      try {
        const res = await activateCampaign(id);
        if (res.success) {
          notifications.show({ title: "Success", message: "Campaign restored successfully", color: "green" });
          refreshData();
        } else {
          notifications.show({ title: "Error", message: res.message || "Failed to restore campaign", color: "red" });
        }
      } catch (e) {
        notifications.show({ title: "Error", message: "An unexpected error occurred", color: "red" });
      } finally {
        closeConfirm();
      }
    });
  };

  const handleDuplicate = (campaign: Campaign) => { setDuplicateData(campaign); openAddDrawer(); };
  const handleAddNew = () => { setDuplicateData(null); openAddDrawer(); };

  const handleSendNow = async (id: string) => {
    setSendingId(id);
    try {
      const res = await sendCampaign(id);
      if (res.success) {
        notifications.show({ title: "Success", message: "Campaign sending initiated", color: "green" });
        refreshData();
      } else {
        notifications.show({ title: "Error", message: res.message || "Failed to send campaign", color: "red" });
      }
    } catch (e) {
      notifications.show({ title: "Error", message: "Failed to send campaign", color: "red" });
    } finally {
      setSendingId(null);
    }
  };

  const handleStop = async (id: string) => {
    try {
      const res = await stopCampaign(id);
      if (res.success) {
        notifications.show({ title: "Success", message: "Campaign stopped", color: "green" });
        refreshData();
      } else {
        notifications.show({ title: "Error", message: "Failed to stop campaign", color: "red" });
      }
    } catch (e) {
      notifications.show({ title: "Error", message: "Failed to stop campaign", color: "red" });
    }
  };

  const handleResume = async (id: string) => {
    setSendingId(id);
    try {
      const res = await resumeCampaign(id);
      if (res.success) {
        notifications.show({ title: "Success", message: "Campaign resumed", color: "green" });
        refreshData();
      } else {
        notifications.show({ title: "Error", message: res.message || "Failed to resume campaign", color: "red" });
      }
    } catch (e) {
      notifications.show({ title: "Error", message: "Failed to resume campaign", color: "red" });
    } finally {
      setSendingId(null);
    }
  };

  const handleViewRecipients = (campaign: Campaign) => { setSelectedCampaign(campaign); openRecipients(); };
  const handleManualRefresh = () => {
    setRefreshing(true);
    refreshData();
  };



  return (
    <Stack px={28} py={20} gap="lg">
      <Flex justify={"space-between"} align="center">
        <Title order={3}>Messaging</Title>
        <Group>
          {status === "DELETED" ? (
            <Button variant="light" color="blue" leftSection={<IconArrowLeft size={16} />} onClick={() => updateParams({ status: null, page: 1 })}>
              Back to Active
            </Button>
          ) : (
            <Button variant="light" color="red" leftSection={<IconTrash size={16} />} onClick={() => updateParams({ status: "DELETED", page: 1 })}>
              Deleted Campaigns
            </Button>
          )}
          <Button variant="light" leftSection={<IconRefresh size={16} />} onClick={handleManualRefresh} loading={refreshing}>
            Refresh
          </Button>
          <Button variant="outline" color="gray" leftSection={<IconSettings size={16} />} onClick={() => navigate("settings")}>
            Settings
          </Button>
          <AddNotification
            accountTypes={accountTypes}
            opened={addDrawerOpened}
            onClose={closeAddDrawer}
            initialData={duplicateData}
            onSuccess={refreshData}
          />
          <Button
            size="compact-lg"
            fz={12}
            variant="filled"
            color={"blue.1"}
            autoContrast
            leftSection={<IconPlus style={{ height: "12px", marginRight: "-10px" }} />}
            onClick={handleAddNew}
          >
            Create a new campaign
          </Button>
        </Group>
      </Flex>

      {/* Metrics Chart Card */}
      <Card padding="xl" radius="lg" withBorder style={chartExpanded ? { position: 'fixed', top: 0, left: 60, right: 0, bottom: 0, zIndex: 200, overflowY: 'auto', boxShadow: '0 8px 24px rgba(0,0,0,0.04)', borderRadius: 0 } : { boxShadow: '0 8px 24px rgba(0,0,0,0.04)' }}>
        <Group justify="space-between" mb={analyticsExpanded ? "lg" : 0}>
          <Group gap="xs" style={{ cursor: 'pointer' }} onClick={() => setAnalyticsExpanded((prev) => !prev)}>
            <IconDeviceAnalytics size={20} color="var(--mantine-color-blue-6)" />
            <Text fw={600} size="md">Campaign Analytics</Text>
            {analyticsExpanded ? <IconChevronUp size={16} color="gray" /> : <IconChevronDown size={16} color="gray" />}
          </Group>

          {analyticsExpanded && (
            <Group gap={0} align="center" style={{ width: 'fit-content', backgroundColor: 'var(--mantine-color-gray-1)', borderRadius: '999px', padding: '4px', position: 'relative' }}>
          <SegmentedControl
            value={isCustomActive || pickerOpen ? '__none__' : timeRange}
            onChange={(val: any) => {
              setTimeRange(val);
              setDateRange([null, null]);
              if (fromDate || toDate) {
                updateParams({ fromDate: undefined, toDate: undefined, page: 1 });
              }
            }}
            data={[
              { label: 'Week (7d)', value: '7d' },
              { label: 'Month (30d)', value: '30d' },
              { label: 'Quarter (90d)', value: '90d' },
            ]}
            radius="xl"
            size="sm"
            styles={{
              root: { backgroundColor: 'transparent', padding: 0, border: 'none', boxShadow: 'none' },
              indicator: { borderRadius: '999px', boxShadow: 'var(--mantine-shadow-xs)' },
              label: { fontWeight: 500, fontSize: '13px' },
            }}
          />

          {/* Custom button — mirrors SegmentedControl active indicator exactly */}
          <Box style={{ position: 'relative', height: '32px', display: 'flex', alignItems: 'center' }}>
            {/* Active indicator background — same style as SegmentedControl indicator */}
            {(isCustomActive || pickerOpen) && (
              <Box style={{
                position: 'absolute',
                inset: 0,
                borderRadius: '999px',
                backgroundColor: 'white',
                boxShadow: 'var(--mantine-shadow-xs)',
              }} />
            )}
            <Box
              onClick={() => datePickerRef.current?.click()}
              style={{
                position: 'relative',
                display: 'inline-flex',
                alignItems: 'center',
                gap: '6px',
                height: '32px',
                padding: (isCustomActive || pickerOpen) ? '0 28px 0 12px' : '0 12px',
                borderRadius: '999px',
                cursor: 'pointer',
                fontWeight: 500,
                fontSize: '13px',
                color: (isCustomActive || pickerOpen) ? 'var(--mantine-color-dark-6)' : 'var(--mantine-color-gray-6)',
                whiteSpace: 'nowrap',
                userSelect: 'none',
              }}
            >
              <IconCalendar size={13} style={{ opacity: 0.7, flexShrink: 0 }} />
              {isCustomActive
                ? `${formatShort(dateRange[0]!)} – ${formatShort(dateRange[1]!)}`
                : 'Custom'}
            </Box>

            {/* Clear ✕ when a custom range is active */}
            {isCustomActive && (
              <Box
                onClick={(e) => {
                  e.stopPropagation();
                  setDateRange([null, null]);
                  updateParams({ fromDate: undefined, toDate: undefined, page: 1 });
                }}
                style={{
                  position: 'absolute',
                  top: '50%',
                  right: '8px',
                  transform: 'translateY(-50%)',
                  width: '16px',
                  height: '16px',
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  borderRadius: '50%',
                  backgroundColor: 'var(--mantine-color-gray-4)',
                  color: 'white',
                  fontSize: '10px',
                  cursor: 'pointer',
                  lineHeight: 1,
                  fontWeight: 700,
                  zIndex: 1,
                }}
              >
                ×
              </Box>
            )}

            {/* Invisible DatePickerInput — only provides the calendar popover */}
            <Box style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', opacity: 0, pointerEvents: 'none', overflow: 'hidden' }}>
              <DatePickerInput
                ref={datePickerRef}
                type="range"
                value={[dateRange[0], dateRange[1]]}
                onChange={(value) => {
                  const [start, end] = value as [Date | string | null, Date | string | null];
                  const startDate = start ? new Date(`${start}T00:00:00`) : null;
                  const endDate = end ? new Date(`${end}T00:00:00`) : null;
                  setDateRange([startDate, endDate]);

                  if (start && end) {
                    const newFrom = typeof start === 'string' ? start : formatDate(start);
                    const newTo = typeof end === 'string' ? end : formatDate(end);
                    if (newFrom === fromDate && newTo === toDate) return; // already applied — skip duplicate fetch
                    updateParams({ fromDate: newFrom, toDate: newTo, page: 1 });
                  } else if (!start && !end && (fromDate || toDate)) {
                    updateParams({ fromDate: undefined, toDate: undefined, page: 1 });
                  }
                }}
                minDate={
                  dateRange[0] && !dateRange[1]
                    ? (() => { const d = new Date(dateRange[0]); d.setDate(d.getDate() - 89); return d; })()
                    : undefined
                }
                maxDate={
                  dateRange[0] && !dateRange[1]
                    ? (() => { const d = new Date(dateRange[0]); d.setDate(d.getDate() + 89); return d; })()
                    : undefined
                }
                popoverProps={{ onOpen: () => setPickerOpen(true), onClose: () => setPickerOpen(false) }}
                clearable
                size="sm"
                style={{ pointerEvents: 'all' }}
              />
            </Box>
          </Box>
          </Group>
          )}
        </Group>

        <Collapse in={analyticsExpanded}>
          <Grid gutter="xl" align="center">
          <Grid.Col span={{ base: 12, md: 3 }}>
            <Stack gap="md">
              <Group align="flex-start" gap="sm" wrap="nowrap">
                <Checkbox checked={showSends} onChange={(e) => setShowSends(e.currentTarget.checked)} color="blue" size="sm" styles={{ input: { cursor: 'pointer' } }} mt={4} />
                <Stack gap={0}>
                  <Group gap={4} align="center">
                    <Text size="sm" fw={600} style={{ color: 'var(--mantine-color-gray-7)' }}>Sends</Text>
                    <Tooltip label="Total push notifications dispatched">
                      <Text size="xs" c="dimmed" style={{ cursor: 'help' }}>ⓘ</Text>
                    </Tooltip>
                  </Group>
                  <Text size="26px" fw={800} style={{ color: '#228be6', lineHeight: 1.1 }}>{formatStatNumber(campaignStats.sends)}</Text>
                </Stack>
              </Group>
              <Group align="flex-start" gap="sm" wrap="nowrap">
                <Checkbox checked={showReceived} onChange={(e) => setShowReceived(e.currentTarget.checked)} color="orange" size="sm" styles={{ input: { cursor: 'pointer' } }} mt={4} />
                <Stack gap={0}>
                  <Group gap={4} align="center">
                    <Text size="sm" fw={600} style={{ color: 'var(--mantine-color-gray-7)' }}>Received</Text>
                    <Tooltip label="Estimated push notifications delivered to devices">
                      <Text size="xs" c="dimmed" style={{ cursor: 'help' }}>ⓘ</Text>
                    </Tooltip>
                  </Group>
                  <Text size="26px" fw={800} style={{ color: '#fd7e14', lineHeight: 1.1 }}>{formatStatNumber(campaignStats.received)}</Text>
                </Stack>
              </Group>
              <Group align="flex-start" gap="sm" wrap="nowrap">
                <Checkbox checked={showImpressions} onChange={(e) => setShowImpressions(e.currentTarget.checked)} color="pink" size="sm" styles={{ input: { cursor: 'pointer' } }} mt={4} />
                <Stack gap={0}>
                  <Group gap={4} align="center">
                    <Text size="sm" fw={600} style={{ color: 'var(--mantine-color-gray-7)' }}>Impressions</Text>
                    <Tooltip label="Total notifications visible on device lockscreens">
                      <Text size="xs" c="dimmed" style={{ cursor: 'help' }}>ⓘ</Text>
                    </Tooltip>
                  </Group>
                  <Text size="26px" fw={800} style={{ color: '#e64980', lineHeight: 1.1 }}>{formatStatNumber(campaignStats.impressions)}</Text>
                </Stack>
              </Group>
              <Group align="flex-start" gap="sm" wrap="nowrap">
                <Checkbox checked={showOpens} onChange={(e) => setShowOpens(e.currentTarget.checked)} color="cyan" size="sm" styles={{ input: { cursor: 'pointer' } }} mt={4} />
                <Stack gap={0}>
                  <Group gap={4} align="center">
                    <Text size="sm" fw={600} style={{ color: 'var(--mantine-color-gray-7)' }}>Open count</Text>
                    <Tooltip label="Total notifications tapped or viewed by members">
                      <Text size="xs" c="dimmed" style={{ cursor: 'help' }}>ⓘ</Text>
                    </Tooltip>
                  </Group>
                  <Text size="26px" fw={800} style={{ color: '#0c8599', lineHeight: 1.1 }}>{formatStatNumber(campaignStats.opens)}</Text>
                </Stack>
              </Group>
            </Stack>
          </Grid.Col>
          <Grid.Col span={{ base: 12, md: 9 }}>
            {!graphReady ? (
              <Skeleton height={320} radius="md" />
            ) : campaignStats.campaignsSent === 0 ? (
              <Stack align="center" justify="center" mih={280}>
                <IconDeviceAnalytics size={48} stroke={1.2} opacity={0.3} color="var(--mantine-color-blue-5)" />
                <Text c="dimmed" size="sm">No push notifications sent yet to map trend.</Text>
              </Stack>
            ) : chartData.length <= 1 ? (
              <Stack align="center" justify="center" mih={280}>
                <Text c="dimmed" size="sm">Selecting metrics to display...</Text>
              </Stack>
            ) : (
              <ReactECharts
                ref={chartRef}
                style={{ height: chartExpanded ? "calc(100vh - 200px)" : "320px", width: "100%", transition: "height 0.3s ease" }}
                opts={{ height: chartExpanded ? 500 : 320 }}
                option={{
                  backgroundColor: "#ffffff",
                  legend: { show: false },
                  toolbox: {
                    right: 10,
                    top: 10,
                    feature: {
                      myFullScreen: {
                        show: true,
                        title: chartExpanded ? "Exit Full Screen" : "Full Screen",
                        icon: chartExpanded
                          ? "path://M7,7 L11,7 L11,9 L9,9 L9,11 L7,11 Z M13,7 L17,7 L17,11 L15,11 L15,9 L13,9 Z M7,13 L9,13 L9,15 L11,15 L11,17 L7,17 Z M15,13 L17,13 L17,17 L13,17 L13,15 L15,15 Z"
                          : "path://M3,3 L9,3 L9,5 L5,5 L5,9 L3,9 Z M15,3 L21,3 L21,9 L19,9 L19,5 L15,5 Z M3,15 L5,15 L5,19 L9,19 L9,21 L3,21 Z M19,15 L21,15 L21,21 L15,21 L15,19 L19,19 Z",
                        onclick: () => { setChartExpanded((prev) => !prev); },
                      },
                    },
                  },
                  xAxis: {
                    type: "category",
                    data: dailyChartData.map(d => d.date),
                    axisLine: { lineStyle: { color: "#dee2e6" } },
                    axisLabel: { color: "#adb5bd", fontSize: 10 },
                  },
                  yAxis: {
                    type: "value",
                    splitLine: { lineStyle: { color: "#f1f3f5" } },
                    axisLabel: { color: "#adb5bd", fontSize: 10 },
                  },
                  series: [
                    showSends && { name: "Sends", type: "line", smooth: true, data: dailyChartData.map(d => d.sends), itemStyle: { color: "#228be6" }, lineStyle: { width: 2 }, symbolSize: 4 },
                    showReceived && { name: "Received", type: "line", smooth: true, data: dailyChartData.map(d => d.received), itemStyle: { color: "#fd7e14" }, lineStyle: { width: 2 }, symbolSize: 4 },
                    showImpressions && { name: "Impressions", type: "line", smooth: true, data: dailyChartData.map(d => d.impressions), itemStyle: { color: "#e64980" }, lineStyle: { width: 2 }, symbolSize: 4 },
                    showOpens && { name: "Open count", type: "line", smooth: true, data: dailyChartData.map(d => d.opens), itemStyle: { color: "#0c8599" }, lineStyle: { width: 2 }, symbolSize: 4 },
                  ].filter(Boolean),
                  tooltip: { trigger: "axis" },
                  grid: { left: "15%", right: "4%", bottom: "3%", containLabel: true },
                }}
                className="echarts-line-chart"
              />
            )}
          </Grid.Col>
        </Grid>
        </Collapse>
      </Card>

      {/* Campaigns Listing */}
      <Stack gap="lg">
        <Group justify="space-between" align="center" style={{ backgroundColor: 'var(--mantine-color-gray-0)', padding: '16px', borderRadius: '12px' }}>
          <TextInput
            placeholder="Search by title or name..."
            value={localSearch}
            onChange={(e) => setLocalSearch(e.currentTarget.value)}
            leftSection={<IconSearch size={18} stroke={1.5} />}
            size="sm"
            radius="md"
            variant="filled"
            style={{ flex: 1, maxWidth: 400 }}
          />
        </Group>

        <Stack gap="md">
          <CampaignsTable
            campaigns={campaigns}
            loading={loading}
            sendingId={sendingId}
            onSendNow={handleSendNow}
            onDuplicate={handleDuplicate}
            onDelete={handleDelete}
            onStop={handleStop}
            onResume={handleResume}
            onViewRecipients={handleViewRecipients}
            onActivate={handleActivate}
            filterState={filterState}
            onFiltersChange={handleFiltersChange}
            sortBy={sortBy}
            sortOrder={sortOrder as 'asc' | 'desc' | undefined}
            onSort={(column) => {
              const newOrder = sortBy === column && sortOrder === 'asc' ? 'desc' : 'asc';
              updateParams({ sortBy: column, sortOrder: newOrder, page: 1 });
            }}
          />

          <Flex justify="space-between" align="center">
            <Group gap="xs">
              <Select
                style={{ width: 80 }}
                data={['5', '10', '20', '30', '40', '50', '100']}
                value={pageSize}
                onChange={(val) => updateParams({ pageSize: val, page: 1 })}
              />
              <Text size="sm" c="dimmed">Entries per page</Text>
            </Group>
            <Pagination
              total={Math.ceil(totalCount / parseInt(pageSize || '10', 10))}
              value={page}
              onChange={(val) => updateParams({ page: val })}
            />
          </Flex>
        </Stack>
      </Stack>

      <RecipientsDrawer opened={recipientsOpened} onClose={closeRecipients} campaign={selectedCampaign} />
      <Drawer opened={historyOpened} onClose={closeHistory} title="Notification History" position="right" size="md">
        <ContextualLogs title="Recent Notification Activity" />
      </Drawer>

      <ConfirmAlert
        title={confirmConfig.title}
        titleIcon={<IconExclamationCircleFilled color="orange" />}
        message={confirmConfig.message}
        handleConfirm={confirmConfig.onConfirm}
        modalProps={{ opened: confirmOpened, onClose: closeConfirm }}
      />
    </Stack>
  );
};

export default NotificationsClientsPage;