import type { Database } from "@xtablo/shared-types";
import { Avatar, AvatarFallback, AvatarImage } from "@xtablo/ui/components/avatar";
import { Badge } from "@xtablo/ui/components/badge";
import { Button } from "@xtablo/ui/components/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@xtablo/ui/components/dropdown-menu";
import { TypographyMuted, TypographySmall } from "@xtablo/ui/components/typography";
import {
  BellIcon,
  CalendarCheckIcon,
  CalendarIcon,
  CheckCheckIcon,
  FileTextIcon,
  KanbanIcon,
  LayoutDashboardIcon,
  LogOutIcon,
  MailIcon,
  SearchIcon,
  SettingsIcon,
  UserPlusIcon,
  XIcon,
} from "lucide-react";
import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { Link, useLocation, useNavigate, useSearchParams } from "react-router-dom";
import { useLogout } from "../hooks/auth";
import { useNotifications, useNotificationsSubscription } from "../hooks/notifications";
import {
  useAcceptTabloInvite,
  useCancelTabloInvite,
  useReceivedTabloInvites,
} from "../hooks/tablo_invites";
import { useUser } from "../providers/UserStoreProvider";

type Notification = Database["public"]["Tables"]["notifications"]["Row"];

function getNotificationIcon(entityType: string) {
  switch (entityType) {
    case "tablos":
      return <LayoutDashboardIcon className="w-4 h-4" />;
    case "tasks":
      return <KanbanIcon className="w-4 h-4" />;
    case "events":
      return <CalendarIcon className="w-4 h-4" />;
    case "notes":
      return <FileTextIcon className="w-4 h-4" />;
    case "tablo_access":
      return <UserPlusIcon className="w-4 h-4" />;
    case "tablo_invites":
      return <MailIcon className="w-4 h-4" />;
    default:
      return <BellIcon className="w-4 h-4" />;
  }
}

function getNotificationLink(notification: Notification): string {
  const { entity_type, entity_id, metadata } = notification;
  switch (entity_type) {
    case "tablos":
      return `/tablos/${entity_id}`;
    case "tasks":
      if (metadata && typeof metadata === "object" && "tablo_id" in metadata) {
        return `/tablos/${metadata.tablo_id}`;
      }
      return "/";
    case "events":
      if (metadata && typeof metadata === "object" && "tablo_id" in metadata) {
        return `/tablos/${metadata.tablo_id}`;
      }
      return "/planning?tab=events";
    case "notes":
      return `/notes/${entity_id}`;
    case "tablo_access":
    case "tablo_invites":
      if (metadata && typeof metadata === "object" && "tablo_id" in metadata) {
        return `/tablos/${metadata.tablo_id}`;
      }
      return "/";
    default:
      return "/";
  }
}

function formatRelativeTime(dateString: string): string {
  const date = new Date(dateString);
  const now = new Date();
  const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);

  if (diffInSeconds < 60) return "Just now";

  const diffInMinutes = Math.floor(diffInSeconds / 60);
  if (diffInMinutes < 60) return `${diffInMinutes}m ago`;

  const diffInHours = Math.floor(diffInMinutes / 60);
  if (diffInHours < 24) return `${diffInHours}h ago`;

  const diffInDays = Math.floor(diffInHours / 24);
  if (diffInDays < 7) return `${diffInDays}d ago`;

  return date.toLocaleDateString();
}

function NotificationItem({
  notification,
  onMarkAsRead,
}: {
  notification: Notification;
  onMarkAsRead: (id: string) => void;
}) {
  const { i18n } = useTranslation();
  const link = getNotificationLink(notification);

  const getMessage = () => {
    const locale = i18n.language.startsWith("fr") ? "fr" : "en";
    return (
      (notification.message as Record<string, string>)[locale] ||
      (notification.message as Record<string, string>)["en"] ||
      ""
    );
  };

  return (
    <Link to={link} onClick={() => onMarkAsRead(notification.id)}>
      <DropdownMenuItem className="cursor-pointer p-3 focus:bg-gray-100 hover:bg-gray-100 text-gray-800">
        <div className="flex gap-3 w-full">
          <div className="shrink-0 mt-1">
            <div className="p-2 rounded-full bg-blue-100 text-blue-600">
              {getNotificationIcon(notification.entity_type)}
            </div>
          </div>
          <div className="flex-1 min-w-0">
            <TypographySmall className="font-medium text-gray-900 line-clamp-2">
              {getMessage()}
            </TypographySmall>
            <TypographyMuted className="text-xs mt-1 text-gray-500">
              {formatRelativeTime(notification.created_at)}
            </TypographyMuted>
          </div>
          <Button
            variant="ghost"
            size="icon"
            className="shrink-0 h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity hover:bg-gray-200 text-gray-500 hover:text-gray-900"
            onClick={(e) => {
              e.preventDefault();
              e.stopPropagation();
              onMarkAsRead(notification.id);
            }}
          >
            <XIcon className="h-3 w-3" />
          </Button>
        </div>
      </DropdownMenuItem>
    </Link>
  );
}

function NotificationDropdown() {
  const { t } = useTranslation("navigation");
  const { notifications, unreadCount, isLoading, markAsRead, markAllAsRead } = useNotifications();
  const { setupSubscription } = useNotificationsSubscription();

  useEffect(() => {
    const cleanup = setupSubscription();
    return cleanup;
  }, []);

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button
          variant="ghost"
          size="icon"
          className="relative w-10 h-10 border border-[#EAECF0] dark:border-gray-700 rounded-[8px] text-[#0C111D] dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800"
          aria-label="Notifications"
        >
          <BellIcon className="w-5 h-5" />
          {unreadCount > 0 && (
            <span className="absolute -top-1 -right-1 flex items-center justify-center w-4 h-4 rounded-full bg-red-500 text-white text-[10px] font-semibold leading-none">
              {unreadCount > 9 ? "9+" : unreadCount}
            </span>
          )}
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent
        className="min-w-96 bg-white border border-[#EAECF0] p-1 rounded-lg text-gray-900 shadow-lg"
        side="bottom"
        align="end"
        sideOffset={8}
      >
        <div className="flex items-center justify-between px-4 py-3 border-b border-gray-100">
          <div className="flex items-center gap-2">
            <TypographySmall className="font-semibold text-gray-900">
              {t("notifications.title", "Notifications")}
            </TypographySmall>
            {unreadCount > 0 && (
              <Badge className="bg-red-500 text-white text-xs">{unreadCount}</Badge>
            )}
          </div>
          {unreadCount > 0 && (
            <Button
              variant="ghost"
              size="sm"
              className="h-8 text-xs text-gray-600 hover:text-gray-900 hover:bg-gray-100"
              onClick={() => markAllAsRead()}
            >
              <CheckCheckIcon className="h-3 w-3 mr-1" />
              {t("notifications.markAllRead", "Mark all read")}
            </Button>
          )}
        </div>

        <div className="max-h-[400px] overflow-y-auto">
          {isLoading ? (
            <div className="flex items-center justify-center py-8">
              <TypographyMuted className="text-sm text-gray-500">
                {t("notifications.loading", "Loading...")}
              </TypographyMuted>
            </div>
          ) : notifications.length === 0 ? (
            <div className="flex flex-col items-center justify-center py-12 px-4 text-center">
              <div className="p-3 rounded-full bg-gray-100 mb-3">
                <BellIcon className="h-6 w-6 text-gray-400" />
              </div>
              <TypographySmall className="font-medium text-gray-900 mb-1">
                {t("notifications.noNotifications", "No new notifications")}
              </TypographySmall>
              <TypographyMuted className="text-xs text-gray-500">
                {t("notifications.allCaughtUp", "You're all caught up!")}
              </TypographyMuted>
            </div>
          ) : (
            <div className="divide-y divide-gray-100">
              {notifications.map((notification) => (
                <div key={notification.id} className="group">
                  <NotificationItem notification={notification} onMarkAsRead={markAsRead} />
                </div>
              ))}
            </div>
          )}
        </div>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

function TabloInvitesDropdown() {
  const { t } = useTranslation("navigation");
  const navigate = useNavigate();
  const { data: invites = [] } = useReceivedTabloInvites();
  const { mutate: acceptInvite, isPending: isAccepting } = useAcceptTabloInvite();
  const { mutate: dismissInvite, isPending: isDismissing } = useCancelTabloInvite();
  const isActionPending = isAccepting || isDismissing;

  if (invites.length === 0) {
    return null;
  }

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button
          variant="ghost"
          size="sm"
          className="relative h-10 border border-[#EAECF0] dark:border-gray-700 rounded-[8px] text-[#0C111D] dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 px-3"
          aria-label={t("invites.title")}
        >
          {t("invites.title")}
          <span className="absolute -top-1 -right-1 flex items-center justify-center min-w-4 h-4 px-1 rounded-full bg-[#804EEC] text-white text-[10px] font-semibold leading-none">
            {invites.length}
          </span>
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent
        className="min-w-80 bg-white border border-[#EAECF0] p-1 rounded-lg text-gray-900 shadow-lg"
        side="bottom"
        align="end"
        sideOffset={8}
      >
        <div className="px-4 py-3 border-b border-gray-100">
          <TypographySmall className="font-semibold text-gray-900">
            {t("invites.title")}
          </TypographySmall>
        </div>
        <div className="max-h-[340px] overflow-y-auto divide-y divide-gray-100">
          {invites.map((invite) => (
            <div key={invite.id} className="px-4 py-3">
              <TypographySmall className="font-medium text-gray-900">
                {invite.tablo_name}
              </TypographySmall>
              <div className="mt-3 flex items-center gap-2">
                <Button
                  variant="outline"
                  size="sm"
                  disabled={isActionPending}
                  onClick={() => dismissInvite({ tabloId: invite.tablo_id, inviteId: invite.id })}
                >
                  {t("invites.dismiss")}
                </Button>
                <Button
                  size="sm"
                  className="bg-[#804EEC] text-white hover:bg-[#6f3fd4]"
                  disabled={isActionPending}
                  onClick={() => {
                    acceptInvite(
                      { inviteId: invite.id },
                      {
                        onSuccess: ({ tablo_id }) => {
                          navigate(`/tablos/${tablo_id}`);
                        },
                      }
                    );
                  }}
                >
                  {t("invites.accept")}
                </Button>
              </div>
            </div>
          ))}
        </div>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

function ProfileDropdown() {
  const { t } = useTranslation("navigation");
  const user = useUser();
  const { mutate: logout } = useLogout();

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <button
          className="flex items-center gap-2 p-1 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-[8px]"
          aria-label="Profile menu"
        >
          <Avatar className="w-10 h-10">
            <AvatarImage src={user.avatar_url ?? undefined} alt="Avatar" />
            <AvatarFallback className="bg-[#B8EAFF] text-gray-800 font-medium">
              {user.name?.charAt(0).toUpperCase()}
            </AvatarFallback>
          </Avatar>
        </button>
      </DropdownMenuTrigger>
      <DropdownMenuContent
        className="min-w-56 bg-white dark:bg-gray-900 border border-[#EAECF0] dark:border-gray-700 p-1 rounded-lg text-gray-900 dark:text-gray-100 shadow-lg"
        side="bottom"
        align="end"
        sideOffset={8}
      >
        <div className="flex gap-2 p-2">
          <Avatar className="size-8">
            <AvatarImage src={user.avatar_url ?? undefined} alt={user.name ?? "User avatar"} />
            <AvatarFallback className="bg-[#B8EAFF] text-gray-800 font-medium">
              {user.name?.charAt(0).toUpperCase()}
            </AvatarFallback>
          </Avatar>
          <div className="flex flex-col gap-0.5 min-w-0 flex-1">
            <TypographySmall className="font-semibold text-gray-900 dark:text-gray-100 truncate">
              {user.name}
            </TypographySmall>
            <TypographyMuted className="text-xs text-gray-500 dark:text-gray-400 truncate">
              {user.email}
            </TypographyMuted>
          </div>
        </div>

        <DropdownMenuSeparator className="bg-gray-100 dark:bg-gray-700" />

        <Link to="/settings">
          <DropdownMenuItem className="cursor-pointer gap-2 text-gray-700 dark:text-gray-200 focus:bg-gray-100 dark:focus:bg-gray-800">
            <SettingsIcon className="w-4 h-4" />
            {t("userMenu.settings")}
          </DropdownMenuItem>
        </Link>

        <Link to="/availabilities">
          <DropdownMenuItem className="cursor-pointer gap-2 text-gray-700 dark:text-gray-200 focus:bg-gray-100 dark:focus:bg-gray-800">
            <CalendarIcon className="w-4 h-4" />
            {t("userMenu.availabilities")}
          </DropdownMenuItem>
        </Link>

        <DropdownMenuSeparator className="bg-gray-100 dark:bg-gray-700" />

        <DropdownMenuItem
          className="cursor-pointer gap-2 text-red-600 dark:text-red-400 focus:bg-red-50 dark:focus:bg-red-900/30 focus:text-red-600 dark:focus:text-red-300"
          onClick={() => logout()}
        >
          <LogOutIcon className="w-4 h-4" />
          {t("userMenu.logout")}
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

const SEARCH_ROUTES = ["/tablos", "/", "/tasks", "/files"];

export function TopBar() {
  const location = useLocation();
  const [searchParams, setSearchParams] = useSearchParams();
  const searchQuery = searchParams.get("q") ?? "";

  const isSearchRoute = SEARCH_ROUTES.includes(location.pathname);

  const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const newParams = new URLSearchParams(searchParams);
    if (e.target.value) {
      newParams.set("q", e.target.value);
    } else {
      newParams.delete("q");
    }
    setSearchParams(newParams, { replace: true });
  };

  return (
    <header className="h-[75px] flex items-center justify-between px-6 gap-4 border-b border-[#EAECF0] dark:border-gray-700 bg-navbar-background shrink-0">
      <div className="relative flex-1 max-w-sm">
        <SearchIcon className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400 dark:text-gray-500 pointer-events-none" />
        <input
          type="text"
          placeholder="Search..."
          value={isSearchRoute ? searchQuery : ""}
          onChange={isSearchRoute ? handleSearchChange : undefined}
          readOnly={!isSearchRoute}
          className="w-full pl-9 pr-4 py-2 bg-transparent border border-[#EAECF0] dark:border-gray-700 rounded-lg text-sm text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-primary dark:bg-gray-800/50"
        />
      </div>
      <div className="flex items-center gap-3">
        {location.pathname === "/planning" && (
          <div className="hidden md:flex items-center bg-gray-100 dark:bg-gray-800 rounded-lg p-1 gap-0.5">
            <Link
              to="/planning"
              className={`flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors ${
                new URLSearchParams(location.search).get("tab") !== "events"
                  ? "bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 shadow-sm"
                  : "text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200"
              }`}
            >
              <CalendarIcon className="w-4 h-4" />
              Calendrier
            </Link>
            <Link
              to="/planning?tab=events"
              className={`flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors ${
                new URLSearchParams(location.search).get("tab") === "events"
                  ? "bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 shadow-sm"
                  : "text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200"
              }`}
            >
              <CalendarCheckIcon className="w-4 h-4" />
              Événements
            </Link>
          </div>
        )}
        <TabloInvitesDropdown />
        <NotificationDropdown />
        <ProfileDropdown />
      </div>
    </header>
  );
}
