'use client';

/**
 * Global notification drawer — accessible from anywhere in the app.
 * Shows a bell button with an unread badge, and opens a Sheet
 * with recent notifications and quick actions.
 *
 * Place this component in the root layout (e.g. WorkspaceLayout or App).
 */

import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import {
  Archive,
  Bell,
  BellOff,
  Check,
  CheckCheck,
  Mail,
  MessageSquare,
  Shield,
  GitPullRequest,
  CheckCircle,
  Merge,
  AlertCircle,
  Settings,
} from 'lucide-react';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { useNotification } from '@/hooks/useNotification';
import type { NotificationResponse } from '@/client/types.gen';
import { cn } from '@/lib/utils';

const MAX_DRAWER_NOTIFICATIONS = 20;

const NOTIFICATION_TYPE_CONFIG: Record<
  string,
  { label: string; icon: React.ReactNode; color: string }
> = {
  mention: {
    label: 'Mention',
    icon: <Bell className="h-3.5 w-3.5" />,
    color: 'bg-blue-500/10 text-blue-600 border-blue-500/20',
  },
  invitation: {
    label: 'Invitation',
    icon: <Mail className="h-3.5 w-3.5" />,
    color: 'bg-purple-500/10 text-purple-600 border-purple-500/20',
  },
  role_change: {
    label: 'Role Change',
    icon: <Shield className="h-3.5 w-3.5" />,
    color: 'bg-orange-500/10 text-orange-600 border-orange-500/20',
  },
  room_created: {
    label: 'Room Created',
    icon: <MessageSquare className="h-3.5 w-3.5" />,
    color: 'bg-green-500/10 text-green-600 border-green-500/20',
  },
  room_deleted: {
    label: 'Room Deleted',
    icon: <MessageSquare className="h-3.5 w-3.5" />,
    color: 'bg-red-500/10 text-red-600 border-red-500/20',
  },
  system_announcement: {
    label: 'Announcement',
    icon: <Bell className="h-3.5 w-3.5" />,
    color: 'bg-yellow-500/10 text-yellow-700 border-yellow-500/20',
  },
  // Extended types
  issue_opened: {
    label: 'Issue Opened',
    icon: <AlertCircle className="h-3.5 w-3.5" />,
    color: 'bg-emerald-500/10 text-emerald-600 border-emerald-500/20',
  },
  issue_closed: {
    label: 'Issue Closed',
    icon: <CheckCircle className="h-3.5 w-3.5" />,
    color: 'bg-violet-500/10 text-violet-600 border-violet-500/20',
  },
  pr_review_requested: {
    label: 'Review Requested',
    icon: <GitPullRequest className="h-3.5 w-3.5" />,
    color: 'bg-amber-500/10 text-amber-600 border-amber-500/20',
  },
  pr_approved: {
    label: 'PR Approved',
    icon: <CheckCircle className="h-3.5 w-3.5" />,
    color: 'bg-green-500/10 text-green-600 border-green-500/20',
  },
  pr_merged: {
    label: 'PR Merged',
    icon: <Merge className="h-3.5 w-3.5" />,
    color: 'bg-purple-500/10 text-purple-600 border-purple-500/20',
  },
};

function formatTime(dateStr: string): string {
  const d = new Date(dateStr);
  const now = new Date();
  const diff = now.getTime() - d.getTime();
  const minutes = Math.floor(diff / 60000);
  if (minutes < 1) return 'just now';
  if (minutes < 60) return `${minutes}m ago`;
  const hours = Math.floor(minutes / 60);
  if (hours < 24) return `${hours}h ago`;
  const days = Math.floor(hours / 24);
  if (days < 7) return `${days}d ago`;
  return d.toLocaleDateString();
}

interface NotificationItemProps {
  n: NotificationResponse;
  onMarkRead: (id: string) => void;
  onArchive: (id: string) => void;
  onNavigate: (n: NotificationResponse) => void;
}

function NotificationItem({ n, onMarkRead, onArchive, onNavigate }: NotificationItemProps) {
  const config = NOTIFICATION_TYPE_CONFIG[n.notification_type] ?? {
    label: n.notification_type,
    icon: <Bell className="h-3.5 w-3.5" />,
    color: 'bg-muted text-muted-foreground border-border',
  };

  return (
    <div
      className={cn(
        'group flex items-start gap-3 px-4 py-3 hover:bg-muted/50 transition-colors cursor-pointer border-b last:border-b-0',
        !n.is_read && 'bg-primary/5',
      )}
      onClick={() => {
        if (!n.is_read) onMarkRead(n.id);
        onNavigate(n);
      }}
    >
      {/* Unread dot */}
      <div className="flex-shrink-0 pt-1">
        {!n.is_read && <div className="h-2 w-2 rounded-full bg-primary" />}
      </div>

      {/* Icon */}
      <div
        className={cn(
          'flex-shrink-0 mt-0.5 h-8 w-8 rounded-full border flex items-center justify-center',
          config.color,
        )}
      >
        {config.icon}
      </div>

      {/* Content */}
      <div className="flex-1 min-w-0">
        <p
          className={cn(
            'text-sm truncate',
            !n.is_read ? 'font-semibold' : 'font-medium',
          )}
        >
          {n.title}
        </p>
        {n.content && (
          <p className="text-xs text-muted-foreground mt-0.5 line-clamp-2">
            {n.content}
          </p>
        )}
        <div className="flex items-center gap-2 mt-1.5">
          <Badge variant="outline" className={cn('text-xs border', config.color)}>
            {config.label}
          </Badge>
          <span className="text-xs text-muted-foreground">{formatTime(n.created_at)}</span>
        </div>
      </div>

      {/* Actions */}
      <div className="flex-shrink-0 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
        {!n.is_read && (
          <Button
            size="sm"
            variant="ghost"
            className="h-7 w-7 p-0"
            onClick={(e) => {
              e.stopPropagation();
              onMarkRead(n.id);
            }}
            title="Mark as read"
          >
            <Check className="h-3.5 w-3.5" />
          </Button>
        )}
        <Button
          size="sm"
          variant="ghost"
          className="h-7 w-7 p-0 text-muted-foreground hover:text-foreground"
          onClick={(e) => {
            e.stopPropagation();
            onArchive(n.id);
          }}
          title="Archive"
        >
          <Archive className="h-3.5 w-3.5" />
        </Button>
      </div>
    </div>
  );
}

interface NotificationDrawerProps {
  /** Provide the wsClient to receive real-time notification pushes */
  wsClient?: unknown;
}

export function NotificationDrawer({ wsClient }: NotificationDrawerProps) {
  const [open, setOpen] = useState(false);
  const navigate = useNavigate();

  const {
    notifications,
    unreadCount,
    markRead,
    markAllRead,
    archive,
    isLive,
  } = useNotification({
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    wsClient: wsClient as any,
    maxNotifications: MAX_DRAWER_NOTIFICATIONS,
    showToast: false,
  });

  const drawerNotifications = notifications.slice(0, MAX_DRAWER_NOTIFICATIONS);

  const handleNavigate = (n: NotificationResponse) => {
    setOpen(false);
    // Navigation based on notification type and related fields
    if (n.related_room_id) {
      // It's a room-related notification — navigate to the room
      navigate(`/project/${n.project}/room`);
    } else if (n.notification_type === 'invitation' || n.notification_type === 'project_invitation') {
      navigate('/invitations');
    } else {
      // Default: go to notifications page
      navigate('/notify');
    }
  };

  return (
    <>
      {/* Bell trigger button */}
      <button
        type="button"
        className="relative flex h-9 w-9 items-center justify-center rounded-md hover:bg-muted cursor-pointer bg-transparent border-0"
        onClick={() => setOpen(true)}
        title="Notifications"
      >
        <Bell className="h-4 w-4" />
        {unreadCount > 0 && (
          <span className="absolute -top-0.5 -right-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-red-500 text-[10px] font-bold text-white px-1">
            {unreadCount > 99 ? '99+' : unreadCount}
          </span>
        )}
        {isLive && (
          <span
            className="absolute bottom-0 right-0 h-2 w-2 rounded-full bg-green-500"
            title="Live"
          />
        )}
      </button>

      {/* Drawer sheet */}
      <Sheet open={open} onOpenChange={setOpen}>
        <SheetContent side="right" className="w-96 max-w-full flex flex-col p-0">
          <SheetHeader className="border-b px-4 py-3 flex-row items-center justify-between space-y-0">
            <div className="flex items-center gap-2">
              <SheetTitle className="m-0 text-base">Notifications</SheetTitle>
              {isLive && (
                <span className="flex items-center gap-1 text-xs text-green-600">
                  <span className="h-1.5 w-1.5 rounded-full bg-green-500" />
                  Live
                </span>
              )}
            </div>
            <div className="flex items-center gap-1">
              {unreadCount > 0 && (
                <Button
                  size="sm"
                  variant="ghost"
                  className="h-8 gap-1 text-xs"
                  onClick={() => markAllRead()}
                >
                  <CheckCheck className="h-3.5 w-3.5" />
                  Mark all read
                </Button>
              )}
              <Button
                size="sm"
                variant="ghost"
                className="h-8 w-8 p-0"
                onClick={() => navigate('/notify')}
                title="All settings"
              >
                <Settings className="h-4 w-4" />
              </Button>
            </div>
          </SheetHeader>

          {/* Unread count */}
          {unreadCount > 0 && (
            <div className="px-4 py-2 bg-primary/5 border-b">
              <span className="text-xs text-muted-foreground">
                <span className="font-semibold text-foreground">{unreadCount}</span> unread
                {unreadCount > 5 && (
                  <button
                    type="button"
                    className="ml-2 text-primary hover:underline"
                    onClick={() => markAllRead()}
                  >
                    Mark all read
                  </button>
                )}
              </span>
            </div>
          )}

          {/* Notification list */}
          <div className="flex-1 overflow-y-auto">
            {drawerNotifications.length === 0 ? (
              <div className="flex flex-col items-center justify-center h-48 text-muted-foreground">
                <BellOff className="h-10 w-10 mb-3 opacity-40" />
                <p className="font-medium text-sm">No notifications yet</p>
                <p className="text-xs mt-1">You'll see updates here when something happens.</p>
              </div>
            ) : (
              drawerNotifications.map((n) => (
                <NotificationItem
                  key={n.id}
                  n={n}
                  onMarkRead={markRead}
                  onArchive={archive}
                  onNavigate={handleNavigate}
                />
              ))
            )}
          </div>

          {/* Footer */}
          <div className="border-t p-3 flex justify-center">
            <Button
              variant="ghost"
              size="sm"
              className="text-xs"
              onClick={() => {
                setOpen(false);
                navigate('/notify');
              }}
            >
              View all notifications
            </Button>
          </div>
        </SheetContent>
      </Sheet>
    </>
  );
}
