'use client';
import { FunctionComponent, useState } from 'react';
import Skeleton from '@mui/material/Skeleton';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { useLocale, useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import AppButton from '@/components/common/AppButton';
import { AppIcon } from '@/components/common';
import { NOTIFICATIONS_PAGE_SIZE } from '@/services/notifications/constants';
import {
  notificationDeepLink,
  useMarkAllRead,
  useMarkNotificationRead,
  useNotifications,
} from '@/services/notifications';
import type { AppNotification } from '@/services/notifications/types';
import { formatRelativeTime, formatShamsiDate } from '@/utils';
import NotificationRow from './NotificationRow';

export interface NotificationCenterProps {
  role: 'customer' | 'nurse';
}

interface NotificationGroup {
  key: string;
  label: string;
  items: AppNotification[];
}

/**
 * Buckets notifications into امروز/دیروز/این هفته, then per-day Shamsi headers for anything older —
 * emitted **in list order** (the server's unread-first-then-newest ordering is preserved; §5 "keep the
 * mark-read UX as is"), so a bucket can recur if an older unread item is pinned above newer read ones.
 * Compares already-formatted date strings (not raw ms diffs) so a day boundary is calendar-exact.
 */
function groupByDay(items: AppNotification[], locale: string, todayLabel: string, yesterdayLabel: string, thisWeekLabel: string): NotificationGroup[] {
  const now = new Date();
  const todayStr = formatShamsiDate(now, locale);
  const yesterday = new Date(now);
  yesterday.setDate(yesterday.getDate() - 1);
  const yesterdayStr = formatShamsiDate(yesterday, locale);
  const thisWeekStrs = new Set<string>();
  for (let i = 2; i < 7; i += 1) {
    const d = new Date(now);
    d.setDate(d.getDate() - i);
    thisWeekStrs.add(formatShamsiDate(d, locale));
  }

  const groups: NotificationGroup[] = [];
  for (const item of items) {
    const dayStr = formatShamsiDate(item.createdAt, locale);
    const bucket =
      dayStr === todayStr
        ? { key: 'today', label: todayLabel }
        : dayStr === yesterdayStr
          ? { key: 'yesterday', label: yesterdayLabel }
          : thisWeekStrs.has(dayStr)
            ? { key: 'this_week', label: thisWeekLabel }
            : { key: dayStr, label: dayStr };

    const last = groups[groups.length - 1];
    if (last && last.key === bucket.key) last.items.push(item);
    else groups.push({ ...bucket, items: [item] });
  }
  return groups;
}

/**
 * The notification center — a paged, **unread-first** list, day-grouped (امروز/دیروز/این هفته, then Shamsi
 * dates) with relative timestamps decaying to Shamsi. Each row **marks itself read on open** (optimistic);
 * a row whose `data` deep-links renders interactive with a trailing chevron, a row with nothing to open
 * renders as a plain, non-rippling surface. A "mark all read" action clears the badge at once. Empty /
 * loading-skeleton / error→retry states. Shared by the customer and nurse notification pages (role decides
 * only the deep-link shell).
 * @component NotificationCenter
 */
const NotificationCenter: FunctionComponent<NotificationCenterProps> = ({ role }) => {
  const t = useTranslations('notifications');
  const locale = useLocale();
  const router = useRouter();
  const [limit, setLimit] = useState(NOTIFICATIONS_PAGE_SIZE);

  const { data, isLoading, isError, refetch, isFetching } = useNotifications(limit);
  const markRead = useMarkNotificationRead();
  const markAll = useMarkAllRead();

  const items = data?.items ?? [];
  const total = data?.total ?? 0;
  const hasUnread = items.some((n) => !n.isRead);
  const groups = groupByDay(items, locale, t('group_today'), t('group_yesterday'), t('group_this_week'));

  const openNotification = (notification: AppNotification) => {
    if (!notification.isRead) markRead.mutate(notification.id);
    const target = notificationDeepLink(notification, role);
    if (target) router.push(`/${locale}${target}`);
  };

  return (
    <Stack sx={{ gap: 2, maxWidth: 640, mx: 'auto', width: '100%' }}>
      <Stack direction="row" sx={{ alignItems: 'center', justifyContent: 'space-between' }}>
        <Typography variant="h6" sx={{ fontWeight: 800 }}>
          {t('title')}
        </Typography>
        {hasUnread ? (
          <AppButton
            variant="text"
            color="primary"
            onClick={() => markAll.mutate()}
            disabled={markAll.isPending}
          >
            {t('mark_all_read')}
          </AppButton>
        ) : null}
      </Stack>

      {isLoading ? (
        <Stack sx={{ gap: 1 }}>
          {[0, 1, 2, 3].map((i) => (
            <Skeleton key={i} variant="rounded" height={72} />
          ))}
        </Stack>
      ) : isError ? (
        <Stack sx={{ gap: 1.5, alignItems: 'center', py: 4 }}>
          <AppIcon icon="error" size={32} color="var(--bal-error)" />
          <Typography variant="body2" sx={{ color: 'var(--bal-text-secondary)' }}>
            {t('error_body')}
          </Typography>
          <AppButton variant="outlined" color="primary" onClick={() => refetch()}>
            {t('retry')}
          </AppButton>
        </Stack>
      ) : items.length === 0 ? (
        <Stack sx={{ gap: 1, alignItems: 'center', py: 6 }}>
          <AppIcon icon="verified" size={36} color="var(--bal-success)" />
          <Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
            {t('empty_title')}
          </Typography>
          <Typography variant="body2" sx={{ color: 'var(--bal-text-secondary)' }}>
            {t('empty_body')}
          </Typography>
        </Stack>
      ) : (
        <Stack sx={{ gap: 2 }}>
          {groups.map((group) => (
            <Stack key={`${group.key}-${group.items[0].id}`} sx={{ gap: 1 }}>
              <Typography variant="caption" sx={{ fontWeight: 700, color: 'var(--bal-text-secondary)' }}>
                {group.label}
              </Typography>
              <Stack sx={{ gap: 1 }}>
                {group.items.map((notification) => {
                  const target = notificationDeepLink(notification, role);
                  return (
                    <NotificationRow
                      key={notification.id}
                      notification={notification}
                      timeLabel={formatRelativeTime(notification.createdAt, locale, formatShamsiDate)}
                      navigable={target != null}
                      onOpen={() => openNotification(notification)}
                    />
                  );
                })}
              </Stack>
            </Stack>
          ))}
          {total > items.length ? (
            <AppButton
              variant="text"
              color="primary"
              onClick={() => setLimit((current) => current + NOTIFICATIONS_PAGE_SIZE)}
              disabled={isFetching}
              sx={{ alignSelf: 'center' }}
            >
              {t('load_more')}
            </AppButton>
          ) : null}
        </Stack>
      )}
    </Stack>
  );
};

export default NotificationCenter;
