"use client";

import * as React from "react";
import { format } from "date-fns";
import { useSession } from "next-auth/react";
import {
  useGetAdminSessionsQuery,
  useRevokeAdminSessionMutation,
  type AdminSessionRow,
} from "@/api/rtk/admin-sessions-api";
import { useGetProfileQuery } from "@/api/rtk/auth-api";
import { useAuthToken } from "@/hooks/use-auth-token";
import { hasPermission, type PermissionSource } from "@/lib/permissions";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  AlertDialog,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Loading } from "@/components/ui/loading";
import { toast } from "sonner";
import {
  ChevronLeft,
  ChevronRight,
  MapPin,
  MonitorSmartphone,
  ShieldAlert,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { mountSessionPresenceSocketSubscription } from "@/lib/session-presence-store";
import { useSessionPresenceOnline } from "@/hooks/use-session-presence-online";

function ActiveSessionPresence({
  sessionId,
  dbOnline,
}: {
  sessionId: string;
  dbOnline: boolean;
}) {
  const live = useSessionPresenceOnline(sessionId);
  const online = live || dbOnline;
  return (
    <span
      className={cn(
        "inline-flex items-center gap-1.5 text-xs font-medium",
        online ? "text-emerald-700" : "text-muted-foreground",
      )}
    >
      <span
        className={cn(
          "size-2 rounded-full shrink-0",
          online
            ? "bg-emerald-500 shadow-[0_0_0_3px_rgba(16,185,129,0.25)]"
            : "bg-muted-foreground/40",
        )}
        aria-hidden
      />
      {online ? "Online" : "Offline"}
    </span>
  );
}

export default function LoginSessionsPage() {
  const { token } = useAuthToken();
  const { data: session } = useSession();
  const { data: profile } = useGetProfileQuery(undefined, { skip: !token });
  const permissionSource: PermissionSource =
    (session as { backendUser?: PermissionSource } | null)?.backendUser ??
    profile ??
    null;

  const canRead = hasPermission(permissionSource, "READ", "LOGIN_SESSION");
  const canRevoke = hasPermission(permissionSource, "UPDATE", "LOGIN_SESSION");

  const [page, setPage] = React.useState(1);
  const [includeRevoked, setIncludeRevoked] = React.useState(false);
  const [revokeId, setRevokeId] = React.useState<string | null>(null);

  const { data, isLoading, isError, refetch } = useGetAdminSessionsQuery(
    { page, limit: 25, includeRevoked },
    { skip: !canRead || !token },
  );

  const [revokeSession, { isLoading: revoking }] =
    useRevokeAdminSessionMutation();

  const handleRevoke = async () => {
    if (!revokeId) return;
    try {
      const res = await revokeSession(revokeId).unwrap();
      toast.success(res.message ?? "Session revoked");
      setRevokeId(null);
      void refetch();
    } catch {
      toast.error("Could not revoke session");
    }
  };

  React.useEffect(() => {
    if (!canRead) return;
    return mountSessionPresenceSocketSubscription();
  }, [canRead]);

  if (!canRead) {
    return (
      <AccessRestrictedShell>
        <ShieldAlert className="size-12 text-muted-foreground" />
        <h1 className="text-lg font-semibold font-['Lexend']">
          Access restricted
        </h1>
        <p className="text-sm text-muted-foreground max-w-md">
          You need READ permission on Login sessions to view this page.
        </p>
      </AccessRestrictedShell>
    );
  }

  if (isLoading) {
    return (
      <Loading
        layout="page"
        message="Loading sessions…"
        className="min-h-[40vh]"
      />
    );
  }

  if (isError || !data) {
    return (
      <div className="p-8 text-center text-destructive text-sm">
        Failed to load sessions. Try again later.
      </div>
    );
  }

  const rows = data.data;
  const { totalPages } = data;

  return (
    <div className="flex flex-col gap-6 p-4 md:p-6 animate-in fade-in duration-300">
      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
        <div className="flex items-start gap-3">
          <div className="size-11 rounded-2xl bg-accent/10 flex items-center justify-center shrink-0">
            <MonitorSmartphone className="size-5 text-accent" />
          </div>
          <div>
            <h1 className="text-xl font-bold font-['Lexend'] tracking-tight">
              Login sessions
            </h1>
            <p className="text-sm text-muted-foreground mt-0.5">
              Active JWT sessions per device. Revoke a row to sign that client
              out on the next API request. Presence is stored as{" "}
              <code className="text-xs bg-muted/60 px-1 rounded">
                Session.isOnline
              </code>{" "}
              when the notifications socket connects or the tab closes.
            </p>
          </div>
        </div>
        <div className="flex items-center gap-3">
          <div className="flex items-center gap-2">
            <Switch
              id="include-revoked"
              checked={includeRevoked}
              onCheckedChange={(v) => {
                setIncludeRevoked(v);
                setPage(1);
              }}
            />
            <Label
              htmlFor="include-revoked"
              className="text-sm font-medium cursor-pointer"
            >
              Show revoked / expired
            </Label>
          </div>
        </div>
      </div>

      <div className="rounded-2xl border border-border/60 bg-card shadow-sm overflow-hidden">
        <Table>
          <TableHeader>
            <TableRow className="hover:bg-transparent">
              <TableHead className="font-['Lexend']">User</TableHead>
              <TableHead className="font-['Lexend']">Device</TableHead>
              <TableHead className="font-['Lexend'] min-w-[140px]">IP</TableHead>
              <TableHead className="font-['Lexend']">Location</TableHead>
              <TableHead className="font-['Lexend']">Started</TableHead>
              <TableHead className="font-['Lexend']">Expires</TableHead>
              <TableHead className="font-['Lexend']">Status</TableHead>
              <TableHead className="font-['Lexend']">Presence</TableHead>
              <TableHead className="text-right font-['Lexend']">Actions</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {rows.length === 0 ? (
              <TableRow>
                <TableCell
                  colSpan={9}
                  className="text-center py-12 text-muted-foreground"
                >
                  No sessions match this view.
                </TableCell>
              </TableRow>
            ) : (
              rows.map((row) => (
                <SessionTableRow
                  key={row.id}
                  row={row}
                  canRevoke={canRevoke}
                  revoking={revoking}
                  onRevokeClick={() => setRevokeId(row.id)}
                />
              ))
            )}
          </TableBody>
        </Table>
      </div>

      {totalPages > 1 && (
        <div className="flex items-center justify-center gap-4">
          <Button
            type="button"
            variant="outline"
            size="sm"
            disabled={page <= 1}
            onClick={() => setPage((p) => Math.max(1, p - 1))}
          >
            <ChevronLeft className="size-4" />
          </Button>
          <span className="text-sm text-muted-foreground tabular-nums">
            Page {page} of {totalPages}
          </span>
          <Button
            type="button"
            variant="outline"
            size="sm"
            disabled={page >= totalPages}
            onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
          >
            <ChevronRight className="size-4" />
          </Button>
        </div>
      )}

      <AlertDialog open={Boolean(revokeId)} onOpenChange={() => setRevokeId(null)}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Revoke this session?</AlertDialogTitle>
            <AlertDialogDescription>
              The user will be signed out on that device when their access token
              is checked (usually within seconds). This does not change their
              password.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <Button
              type="button"
              variant="destructive"
              disabled={revoking}
              className="bg-destructive text-white shadow-sm hover:opacity-90 disabled:opacity-70 disabled:text-white"
              onClick={() => void handleRevoke()}
            >
              {revoking ? "Revoking…" : "Revoke session"}
            </Button>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}

function AccessRestrictedShell({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex flex-col items-center justify-center min-h-[50vh] gap-4 p-8 text-center">
      {children}
    </div>
  );
}

function SessionTableRow({
  row,
  canRevoke,
  revoking,
  onRevokeClick,
}: {
  row: AdminSessionRow;
  canRevoke: boolean;
  revoking: boolean;
  onRevokeClick: () => void;
}) {
  return (
    <TableRow>
      <TableCell>
        <div className="flex flex-col gap-0.5">
          <span className="font-medium text-sm">
            {row.user?.name ?? "—"}
          </span>
          <span className="text-xs text-muted-foreground">
            {row.user?.email ?? row.userId ?? "—"}
          </span>
        </div>
      </TableCell>
      <TableCell className="max-w-[200px]">
        <span
          className="text-sm truncate block"
          title={row.deviceName ?? row.userAgent ?? ""}
        >
          {row.deviceName || row.userAgent || "Unknown device"}
        </span>
      </TableCell>
      <TableCell>
        <div className="flex flex-col gap-1">
          <code className="text-xs bg-muted/60 px-2 py-0.5 rounded-md w-fit">
            {row.ip ?? "—"}
          </code>
          {row.browserReportedIp ? (
            <div className="flex flex-col gap-0.5">
              <span className="text-[10px] uppercase tracking-wide text-muted-foreground">
                Browser IP
              </span>
              <code
                className="text-xs bg-accent/10 text-accent px-2 py-0.5 rounded-md w-fit max-w-[160px] truncate"
                title="WAN IP from client probe (ipify)"
              >
                {row.browserReportedIp}
              </code>
            </div>
          ) : null}
        </div>
      </TableCell>
      <TableCell className="max-w-[220px]">
        {row.location ? (
          <span
            className="flex items-start gap-1.5 text-sm text-muted-foreground"
            title={row.location}
          >
            <MapPin className="size-3.5 shrink-0 mt-0.5 text-muted-foreground/70" />
            <span className="line-clamp-2 leading-snug">{row.location}</span>
          </span>
        ) : (
          <span className="text-sm text-muted-foreground/60">—</span>
        )}
      </TableCell>
      <TableCell className="text-sm text-muted-foreground whitespace-nowrap">
        {format(new Date(row.createdAt), "MMM d, yyyy · h:mm a")}
      </TableCell>
      <TableCell className="text-sm text-muted-foreground whitespace-nowrap">
        {row.expiresAt
          ? format(new Date(row.expiresAt), "MMM d, yyyy · h:mm a")
          : "—"}
      </TableCell>
      <TableCell>
        <span
          className={cn(
            "text-xs font-semibold uppercase tracking-wide px-2 py-0.5 rounded-lg",
            row.isActive
              ? "bg-emerald-50 text-emerald-800 border border-emerald-100"
              : "bg-muted text-muted-foreground",
          )}
        >
          {row.isActive ? "Active" : "Inactive"}
        </span>
      </TableCell>
      <TableCell>
        {row.isActive ? (
          <ActiveSessionPresence
            sessionId={row.id}
            dbOnline={Boolean(row.isOnline)}
          />
        ) : (
          <span className="text-xs text-muted-foreground/70">—</span>
        )}
      </TableCell>
      <TableCell className="text-right">
        {row.isActive && canRevoke ? (
          <Button
            type="button"
            variant="outline"
            size="sm"
            className="min-w-[5.25rem] border-destructive/35 font-semibold text-destructive hover:bg-destructive/10 hover:text-destructive"
            disabled={revoking}
            onClick={onRevokeClick}
          >
            Revoke
          </Button>
        ) : (
          <span className="inline-block text-xs font-medium text-muted-foreground tabular-nums">
            —
          </span>
        )}
      </TableCell>
    </TableRow>
  );
}
