"use client";

import { useCallback, useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { AtSign, Bell, CheckCheck, Inbox, Loader2, UserCheck } from "lucide-react";
import { Button } from "@/presentation/components/ui/button";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/presentation/components/ui/popover";
import { useApiQuery } from "@/presentation/hooks/use-api-query";
import { useRepositories } from "@/di/repository-provider";
import { useT, useLocale } from "@/shared/i18n/client";
import { formatRelative } from "@/shared/lib/format-date";
import { cn } from "@/shared/lib/utils";
import type { Notification } from "@/domain/entities/notification";

const POLL_INTERVAL_MS = 60_000;

const ICON_BY_TYPE: Record<string, React.ComponentType<{ className?: string }>> = {
  ticket_assigned: UserCheck,
  ticket_mention: AtSign,
};

const PRIORITY_ICON_CLASS: Record<string, string> = {
  critical: "bg-red-50 text-red-600 dark:bg-red-950/40 dark:text-red-400",
  high: "bg-orange-50 text-orange-600 dark:bg-orange-950/40 dark:text-orange-400",
  medium: "bg-blue-50 text-blue-600 dark:bg-blue-950/40 dark:text-blue-400",
  low: "bg-gray-100 text-gray-600 dark:bg-gray-800/40 dark:text-gray-400",
};

/** Strip the host so router.push respects Next's basePath. */
function resolveActionUrl(actionUrl: string): string {
  try {
    const u = new URL(actionUrl);
    return `${u.pathname}${u.search}${u.hash}`;
  } catch {
    return actionUrl;
  }
}

export function NotificationBell() {
  const t = useT();
  const locale = useLocale();
  const router = useRouter();
  const container = useRepositories();
  const [open, setOpen] = useState(false);

  const { data: count, refetch: refetchCount } = useApiQuery(
    () => container.notificationRepository.getUnreadCount(),
    { deps: [] },
  );

  // Poll the unread count in the background.
  useEffect(() => {
    const id = window.setInterval(() => { void refetchCount(); }, POLL_INTERVAL_MS);
    return () => window.clearInterval(id);
  }, [refetchCount]);

  const { data: recent, loading, refetch: refetchRecent } = useApiQuery(
    () => container.notificationRepository.getRecent(),
    { deps: [open], enabled: open },
  );

  const handleClick = useCallback(
    async (n: Notification) => {
      setOpen(false);
      if (!n.is_read) {
        try {
          await container.notificationRepository.markRead(n.id);
          await refetchCount();
          await refetchRecent();
        } catch {
          // Non-fatal: navigation still happens even if mark-read fails.
        }
      }
      router.push(resolveActionUrl(n.action_url));
    },
    [container, router, refetchCount, refetchRecent],
  );

  const handleMarkAllRead = useCallback(async () => {
    try {
      await container.notificationRepository.markAllRead();
      await refetchCount();
      await refetchRecent();
    } catch {
      // Non-fatal.
    }
  }, [container, refetchCount, refetchRecent]);

  const total = count?.unread ?? 0;

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button variant="ghost" size="icon" className="relative" aria-label={t.notifications.title}>
          <Bell className="w-4.5 h-4.5" />
          {total > 0 && (
            <span className="absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 bg-red-500 text-white text-[10px] font-bold rounded-full inline-flex items-center justify-center">
              {t.notifications.unreadBadge(total)}
            </span>
          )}
        </Button>
      </PopoverTrigger>
      <PopoverContent align="end" className="w-80 p-0">
        <div className="flex items-center justify-between border-b border-border px-4 py-3">
          <span className="text-sm font-semibold">{t.notifications.title}</span>
          {total > 0 && (
            <button
              type="button"
              onClick={handleMarkAllRead}
              className="inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors"
            >
              <CheckCheck className="h-3.5 w-3.5" />
              {t.notifications.markAllRead}
            </button>
          )}
        </div>
        <div className="max-h-96 overflow-y-auto">
          {loading && (
            <div className="flex items-center justify-center py-6">
              <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
            </div>
          )}
          {!loading && (recent?.length ?? 0) === 0 && (
            <div className="flex flex-col items-center justify-center gap-2 py-8 text-muted-foreground">
              <Inbox className="h-5 w-5" />
              <span className="text-xs">{t.notifications.empty}</span>
            </div>
          )}
          {!loading && recent?.map((n) => {
            const Icon = ICON_BY_TYPE[n.type] ?? Bell;
            const isUnread = !n.is_read;
            return (
              <button
                key={n.id}
                type="button"
                onClick={() => handleClick(n)}
                className={cn(
                  "flex w-full items-start gap-3 px-4 py-3 text-left border-b border-border last:border-b-0 hover:bg-muted/40 transition-colors",
                  isUnread && "bg-primary/5",
                )}
              >
                <span
                  className={cn(
                    "flex h-8 w-8 shrink-0 items-center justify-center rounded-full",
                    PRIORITY_ICON_CLASS[n.priority] ?? PRIORITY_ICON_CLASS.medium,
                  )}
                >
                  <Icon className="h-4 w-4" />
                </span>
                <div className="flex-1 min-w-0">
                  <div className="flex items-center justify-between gap-2">
                    <span className="text-sm font-medium truncate">{n.title}</span>
                    {isUnread && (
                      <span className="w-2 h-2 rounded-full bg-primary shrink-0" aria-hidden />
                    )}
                  </div>
                  <p className="text-xs text-muted-foreground line-clamp-2 mt-0.5">{n.summary}</p>
                  <p className="text-[11px] text-muted-foreground mt-1">
                    {formatRelative(n.created_at, locale)}
                  </p>
                </div>
              </button>
            );
          })}
        </div>
      </PopoverContent>
    </Popover>
  );
}
