"use client";

import * as React from "react";
import { useUrlPagination } from "@/hooks/use-url-pagination";
import {
  useGetNotificationsQuery,
  useMarkAsReadMutation,
  useMarkAllAsReadMutation,
} from "@/api/rtk/notifications-api";
import { /* useRequestPasswordChangeMutation, */ useUpdateUserMutation, useGetProfileQuery } from "@/api/rtk";
import { useAuthToken } from "@/hooks/use-auth-token"
import type { ApiNotification } from "@/api/notifications/types";
import { cn } from "@/lib/utils";
import {
  Bell,
  CheckCheck,
  Search,
  Settings,
  KeyRound,
  ShieldAlert,
  MessageSquare,
  TrendingUp,
  ChevronLeft,
  ChevronRight,
  Eye,
  EyeOff,
} from "lucide-react";
import { Loading } from "@/components/ui/loading";
import { NoDataFound } from "@/components/ui/no-data-found";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { toast } from "sonner";
import { formatDistanceToNow } from "date-fns";
import { Card } from "@/components/ui/card";
import { sanitizeNoteHtml } from "@/components/deals/deal-note-composer";
import { apiBaseUrl } from "@/api/client";
import { useGetPipelinesQuery } from "@/api/rtk/pipelines-api";
import {
  buildStageNameMap,
  formatNotificationTextWithStageName,
} from "@/lib/notification-message";
import { isVisibleNotification } from "@/lib/is-visible-notification";
import { hasPermission } from "@/lib/permissions";
import { useSession } from "next-auth/react";
import {
  decrementNotificationUnreadCount,
  resetNotificationUnreadCount,
  useNotificationUnreadCount,
} from "@/lib/notification-unread-store";

const TYPE_ICONS: Record<string, React.ReactNode> = {
  security: <ShieldAlert size={16} className="text-amber-500" />,
  info: <Bell size={16} className="text-accent" />,
  success: <CheckCheck size={16} className="text-green-500" />,
  warning: <ShieldAlert size={16} className="text-orange-500" />,
  system: <Settings size={16} className="text-gray-500" />,
  mention: <MessageSquare size={16} className="text-blue-500" />,
  update: <TrendingUp size={16} className="text-accent" />,
  reminder: <Bell size={16} className="text-amber-500" />,
};

function getTypeIcon(type: string) {
  return TYPE_ICONS[type] ?? <Bell size={16} className="text-accent" />;
}

const PAGE_SIZE = 10;

export default function NotificationsPage() {
  const { token: accessToken } = useAuthToken();
  const { data: session } = useSession();
  const { page, setPage } = useUrlPagination(PAGE_SIZE);
  const [filter, setFilter] = React.useState<"all" | "unread">("all");
  const [search, setSearch] = React.useState("");
  const [setPasswordModal, setSetPasswordModal] = React.useState<{
    open: boolean;
    userId: string;
    userName: string;
    notificationId?: string;
  } | null>(null);
  const [newPassword, setNewPassword] = React.useState("");
  const [showPassword, setShowPassword] = React.useState(false);

  const { data: notificationsData, isLoading, isFetching } = useGetNotificationsQuery(
    { 
      page, 
      limit: PAGE_SIZE,
      isRead: filter === "unread" ? false : undefined
    },
    { skip: !accessToken }
  );

  const unreadCount = useNotificationUnreadCount();
  const [markAsRead] = useMarkAsReadMutation();
  const [markAllAsRead, { isLoading: markingAll }] = useMarkAllAsReadMutation();
  const { data: profile } = useGetProfileQuery(undefined, { skip: !accessToken });
  const permissionSource = (session as { backendUser?: unknown } | null)?.backendUser ?? profile;
  const canUpdateUsers = hasPermission(permissionSource, "UPDATE", "USER");
  const [updateUser, { isLoading: updatingPassword }] = useUpdateUserMutation();


  const { data: pipelines = [] } = useGetPipelinesQuery(undefined, {
    skip: !accessToken,
  });

  const stageNameMap = React.useMemo(
    () =>
      buildStageNameMap(
        pipelines.flatMap((pipeline) =>
          (pipeline.stages ?? []).map((stage) => ({
            id: stage.id,
            name: stage.name,
            subStages: (stage.subStages ?? []).map((subStage) => ({
              id: subStage.id,
              name: subStage.name,
            })),
          })),
        ),
      ),
    [pipelines],
  );

  const visibleNotifications = React.useMemo(
    () => (notificationsData?.notifications ?? []).filter(isVisibleNotification),
    [notificationsData?.notifications],
  );
  const totalPages = notificationsData?.totalPages ?? 1;
  const total = notificationsData?.total ?? 0;
  const filteredNotifications = visibleNotifications.filter((n) => {
    const matchesSearch =
      !search ||
      n.title.toLowerCase().includes(search.toLowerCase()) ||
      n.message.toLowerCase().includes(search.toLowerCase());
    return matchesSearch;
  });

  const handleMarkAllAsRead = async () => {
    try {
      await markAllAsRead().unwrap();
      resetNotificationUnreadCount();
      toast.success("All notifications marked as read");
    } catch {
      toast.error("Failed to mark all as read");
    }
  };

  const handleMarkAsRead = async (id: string) => {
    const notification = visibleNotifications.find(
      (item) => (item.id ?? (item as { _id?: string })._id) === id,
    );
    try {
      await markAsRead(id).unwrap();
      if (notification && !notification.isRead) {
        decrementNotificationUnreadCount();
      }
    } catch {
      // ignore
    }
  };

  // Password change request commented out
  // const handleRequestPasswordChange = async () => {
  //   try {
  //     await requestPasswordChange().unwrap();
  //     toast.success(
  //       "Request submitted. An administrator will update your password shortly."
  //     );
  //   } catch (e) {
  //     toast.error(e instanceof Error ? e.message : "Request failed");
  //   }
  // };

  const handleOpenSetPassword = (notif: ApiNotification) => {
    const custom = notif.metadata?.customData;
    const userId = custom?.requestedByUserId ?? notif.metadata?.entityId;
    if (!userId) return;
    setSetPasswordModal({
      open: true,
      userId,
      userName:
        custom?.requestedByName || custom?.requestedByEmail || "User",
      notificationId: notif.id ?? (notif as { _id?: string })._id,
    });
    setNewPassword("");
  };

  const handleSubmitSetPassword = async () => {
    if (!setPasswordModal || !newPassword.trim() || newPassword.length < 6) {
      toast.error("Password must be at least 6 characters");
      return;
    }
    try {
      await updateUser({
        id: setPasswordModal.userId,
        body: { password: newPassword },
      }).unwrap();
      toast.success("Password updated");
      setNewPassword("");
      setShowPassword(false);
      setSetPasswordModal(null);
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "Failed to update password");
    }
  };

  if (!accessToken) {
    return (
      <div className="flex items-center justify-center py-16">
        <Loading message="Loading..." />
      </div>
    );
  }

  return (
    <div className="flex flex-col  overflow-y-auto pr-1 scrollbar-themed h-full gap-5 p-1 sm:p-2 md:p-4 animate-in fade-in duration-500 overflow-hidden min-h-0">
      <div className="flex flex-col lg:flex-row justify-between items-start lg:items-center gap-4 border-b border-border/60 pb-6">
        <div className="flex flex-col">
          <div className="flex items-center gap-3">
            <h1 className="text-[21px] font-extrabold text-text font-['Lexend'] tracking-tight">
              Notifications
            </h1>
            {unreadCount > 0 && (
              <span className="bg-accent text-white text-[10px] font-bold px-2 py-0.5 rounded-full">
                {unreadCount} New
              </span>
            )}
          </div>
          <p className="text-[12px] text-gray-700 font-normal mt-0.5">
            Stay updated. Manage alerts.
          </p>
        </div>
        <div className="flex items-center gap-2 flex-wrap">
          {/* Password change request commented out
          {!isAdmin && (
            <Button
              variant="outline"
              size="sm"
              onClick={handleRequestPasswordChange}
              disabled={requesting}
            >
              <KeyRound size={14} />
              {requesting ? "Submitting..." : "Request password change"}
            </Button>
          )}
          */}
          <Button
            variant="outline"
            size="sm"
            onClick={handleMarkAllAsRead}
            disabled={markingAll || unreadCount === 0}
          >
            <CheckCheck size={14} />
            Mark all as read
          </Button>
        </div>
      </div>

      <div className="flex flex-col md:flex-row items-center gap-3">
        <div className="flex bg-white/50 p-1 rounded-xl border border-border w-full md:w-auto">
          <Button
            variant={filter === "all" ? "notificationsFilterOn" : "notificationsFilterOff"}
            onClick={() => {
              setFilter("all");
              setPage(1);
            }}
          >
            All
          </Button>
          <Button
            variant={filter === "unread" ? "notificationsFilterOn" : "notificationsFilterOff"}
            onClick={() => {
              setFilter("unread");
              setPage(1);
            }}
          >
            Unread
          </Button>
        </div>
        <div className="relative flex-1 w-full max-w-md">
          <Search size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-700" />
          <Input
            type="search"
            placeholder="Search notifications..."
            className="pl-9 pr-3"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>
      </div>

      <div className="flex-1 min-h-0">
        {isLoading ? (
          <Loading message="Loading notifications..." className="py-16" />
        ) : filteredNotifications.length > 0 ? (
          <>
            <div className="flex flex-col gap-2.5 pb-6">
              {filteredNotifications.map((notif) => {
                const isPasswordRequest =
                  notif.metadata?.category === "password_change_request";
                return (
                  <Card
                    key={notif.id ?? (notif as { _id?: string })._id}
                    className={cn(
                      "p-4 gap-0 transition-all group relative",
                      !notif.isRead && "border-accent/10"
                    )}
                  >
                    <div className="flex items-start gap-4">
                      <div className="relative shrink-0">
                        <div className="size-10 rounded-full bg-accent/10 flex items-center justify-center text-accent">
                          {getTypeIcon(notif.type)}
                        </div>
                      </div>
                      <div className="flex-1 min-w-0 pr-8">
                        <div className="flex items-center gap-2 mb-0.5">
                          <h4
                            className={cn(
                              "text-[14px] font-['Lexend'] truncate",
                              notif.isRead ? "font-semibold" : "font-bold"
                            )}
                          >
                            {formatNotificationTextWithStageName(notif.title, stageNameMap)}
                          </h4>
                          {!notif.isRead && (
                            <div className="size-2 bg-accent rounded-full shrink-0" />
                          )}
                        </div>
                        {/<\/?(\w+)[^>]*>/.test(notif.message ?? "") ? (
                          <div
                            className="text-[12px] text-gray-700 leading-relaxed prose prose-p:my-0.5 prose-img:rounded-lg prose-img:max-h-[120px] prose-img:object-cover [&_img]:max-h-[120px] [&_img]:rounded-lg [&_img]:border [&_img]:border-gray-200"
                            dangerouslySetInnerHTML={{
                              __html: (() => {
                                const formattedMessage = formatNotificationTextWithStageName(
                                  notif.message ?? "",
                                  stageNameMap,
                                );
                                const sanitized = sanitizeNoteHtml(formattedMessage);
                                const base = apiBaseUrl.replace(/\/$/, "");
                                return sanitized.replace(
                                  /src="(\/[^"]+)"/g,
                                  (_, path) => `src="${base}${path}"`
                                );
                              })(),
                            }}
                          />
                        ) : (
                          <p className="text-[12px] text-gray-700 line-clamp-2 leading-relaxed">
                            {formatNotificationTextWithStageName(notif.message, stageNameMap)}
                          </p>
                        )}
                        <div className="flex items-center gap-3 mt-2 flex-wrap">
                          <span className="text-[10px] font-bold uppercase tracking-widest text-gray-500">
                            {notif.createdAt
                              ? formatDistanceToNow(
                                new Date(notif.createdAt),
                                { addSuffix: true }
                              )
                              : ""}
                          </span>
                          {isPasswordRequest && canUpdateUsers && (
                            <Button
                              variant="outlineToolbarMini"
                              onClick={() => handleOpenSetPassword(notif)}
                            >
                              <KeyRound size={12} />
                              Update password
                            </Button>
                          )}
                        </div>
                      </div>
                      <div className="absolute right-4 top-4 flex items-center gap-1 opacity-100">
                        {!notif.isRead && (
                          <Button
                            variant="ghostTableIcon"
                            onClick={() => handleMarkAsRead(notif.id ?? (notif as { _id?: string })._id ?? "")}
                          >
                            <CheckCheck size={14} />
                          </Button>
                        )}
                      </div>
                    </div>
                  </Card>
                );
              })}
            </div>

            {totalPages > 1 && (
              <div className="flex items-center justify-between py-4 px-1">
                <span className="text-[12px] text-gray-500 font-medium">
                  Showing {(page - 1) * PAGE_SIZE + 1}–{Math.min(page * PAGE_SIZE, total)} of {total}
                </span>
                <div className="flex items-center gap-2">
                  <Button
                    variant="outline"
                    size="pagination"
                    onClick={() => setPage((p) => Math.max(1, p - 1))}
                    disabled={page <= 1 || isFetching}
                  >
                    <ChevronLeft size={14} />
                    Previous
                  </Button>
                  <div className="flex items-center gap-1">
                    {Array.from({ length: totalPages }, (_, i) => i + 1)
                      .filter((p) => p === 1 || p === totalPages || Math.abs(p - page) <= 1)
                      .reduce<(number | "ellipsis")[]>((acc, p, idx, arr) => {
                        if (idx > 0 && p - (arr[idx - 1] as number) > 1) acc.push("ellipsis");
                        acc.push(p);
                        return acc;
                      }, [])
                      .map((item, idx) =>
                        item === "ellipsis" ? (
                          <span key={`e-${idx}`} className="px-1 text-[12px] text-gray-400">…</span>
                        ) : (
                          <Button
                            key={item}
                            variant={item === page ? "default" : "ghost"}
                            size="page"
                            onClick={() => setPage(item)}
                            disabled={isFetching}
                          >
                            {item}
                          </Button>
                        )
                      )}
                  </div>
                  <Button
                    variant="outline"
                    size="pagination"
                    onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                    disabled={page >= totalPages || isFetching}
                  >
                    Next
                    <ChevronRight size={14} />
                  </Button>
                </div>
              </div>
            )}
          </>
        ) : (
          <NoDataFound
            message="No notifications"
            description="You are all caught up."
            icon={<Bell className="size-10 text-muted-foreground" />}
          />
        )}
      </div>

      <Dialog
        open={setPasswordModal?.open ?? false}
        onOpenChange={(open) => {
          if (!open) {
            setSetPasswordModal(null);
            setNewPassword("");
            setShowPassword(false);
          }
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Set new password</DialogTitle>
          </DialogHeader>
          {setPasswordModal && (
            <>
              <p className="text-sm text-muted-foreground">
                Set a new password for {setPasswordModal.userName}.
              </p>
              <div className="grid gap-2 py-2">
                <Label htmlFor="new-password">New password</Label>
                <div className="relative">
                  <Input
                    id="new-password"
                    type={showPassword ? "text" : "password"}
                    value={newPassword}
                    onChange={(e) => setNewPassword(e.target.value)}
                    placeholder="Min 6 characters"
                    className="pr-10"
                  />
                  <Button
                    type="button"
                    variant="inputTrailingIcon"
                    onClick={() => setShowPassword((prev) => !prev)}
                    aria-label={showPassword ? "Hide password" : "Show password"}
                  >
                    {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
                  </Button>
                </div>
              </div>
            </>
          )}
          <DialogFooter>
            <Button
              variant="outlineModalAction"
              onClick={() => {
                setSetPasswordModal(null);
                setNewPassword("");
                setShowPassword(false);
              }}
            >
              Cancel
            </Button>
            <Button
              variant="accentDialogPrimary"
              onClick={handleSubmitSetPassword}
              disabled={
                !newPassword.trim() ||
                newPassword.length < 6 ||
                updatingPassword
              }
            >
              {updatingPassword ? "Updating..." : "Update password"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
