"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Table } from "@heroui/react";
import {
	createOrganizationApi,
	normalizeEmailRow,
	normalizeInvitation,
	normalizeMember,
	normalizeOrganization,
	safeStringify,
	slugify,
	type ApiCallResult,
	type EmailRow,
	type Invitation,
	type Member,
	type Organization,
} from "athena-auth-js";
import { authClient } from "../lib/auth-client";
import { Badge } from "./ui/badge";
import { Button } from "./ui/button";
import { SharedBackButton } from "./shared-back-button";
import {
	Card,
	CardContent,
	CardDescription,
	CardHeader,
	CardTitle,
} from "./ui/card";
import { Combobox, type ComboOption } from "./ui/combobox";
import { Input } from "./ui/input";
import { Label } from "./ui/label";
import { SessionOrganizationSwitcher } from "./organization/session-organization-switcher";
import {
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
} from "./ui/select";

type RowItem = { id: string; action: string; status: string; detail: string };
type ApiKeyRow = {
	id: string;
	name: string;
	prefix?: string;
	enabled?: boolean;
	expiresAt?: string | null;
	createdAt?: string | null;
};

const roleOptions = ["member", "admin", "owner"];

type OrganizationLabProps = {
	initialInvitationId?: string | null;
};

export function OrganizationLab({ initialInvitationId }: OrganizationLabProps) {
	const organizationApi = useMemo(() => createOrganizationApi(), []);
	const authApi = organizationApi.call;

	const {
		data: sessionData,
		isPending: sessionPending,
		error: sessionError,
		refetch: refetchSession,
	} = authClient.useSession();

	const [organizations, setOrganizations] = useState<Organization[]>([]);
	const [selectedOrganizationId, setSelectedOrganizationId] = useState("");
	const [members, setMembers] = useState<Member[]>([]);
	const [organizationInvitations, setOrganizationInvitations] = useState<
		Invitation[]
	>([]);
	const [userInvitations, setUserInvitations] = useState<Invitation[]>([]);
	const [coupledEmails, setCoupledEmails] = useState<EmailRow[]>([]);
	const [rows, setRows] = useState<RowItem[]>([]);
	const [apiKeys, setApiKeys] = useState<ApiKeyRow[]>([]);
	const [newApiKeyName, setNewApiKeyName] = useState("Demo Integration Key");
	const [newApiKeyRawValue, setNewApiKeyRawValue] = useState<string | null>(
		null,
	);
	const [suppressApiKeyPolling, setSuppressApiKeyPolling] = useState(false);
	const [loading, setLoading] = useState(false);
	const [emailEvidenceLoading, setEmailEvidenceLoading] = useState(false);
	const [apiKeyLoading, setApiKeyLoading] = useState(false);
	const [apiCoverageLoading, setApiCoverageLoading] = useState(false);
	const [notice, setNotice] = useState<string | null>(null);
	const [error, setError] = useState<string | null>(null);
	const [selectedOrganizationAuto, setSelectedOrganizationAuto] =
		useState(true);

	const [createName, setCreateName] = useState("");
	const [createSlug, setCreateSlug] = useState("");
	const [createSlugTouched, setCreateSlugTouched] = useState(false);
	const [inviteEmail, setInviteEmail] = useState("");
	const [inviteRole, setInviteRole] = useState("member");
	const [inviteCallbackUrl, setInviteCallbackUrl] = useState("");
	const [emailEvidenceRecipient, setEmailEvidenceRecipient] = useState("");
	const [roleDraftByMember, setRoleDraftByMember] = useState<
		Record<string, string>
	>({});
	const invitationAutoAcceptAttempted = useRef(false);
	const emailEvidenceAutoRefreshTimer = useRef<ReturnType<
		typeof setTimeout
	> | null>(null);
	const selectedOrganizationIdRef = useRef("");
	const selectedOrganizationAutoRef = useRef(true);
	const activeOrganizationIdFromSessionRef = useRef("");

	const sessionRecord = (sessionData?.session ?? {}) as unknown as Record<
		string,
		unknown
	>;
	const sessionUserRecord = (sessionData?.user ?? {}) as unknown as Record<
		string,
		unknown
	>;
	const activeOrganizationIdFromSession =
		sessionRecord.activeOrganizationId ??
		sessionRecord.active_organization_id ??
		sessionRecord.organization_id ??
		sessionRecord.organizationId;
	const sessionEmailVerified =
		"emailVerified" in sessionUserRecord
			? Boolean(sessionUserRecord.emailVerified)
			: null;
	const sessionUserId =
		typeof sessionUserRecord.id === "string"
			? (sessionUserRecord.id as string)
			: "";
	const sessionUserRole =
		typeof sessionUserRecord.role === "string"
			? (sessionUserRecord.role as string)
			: null;

	const selectedOrganization = useMemo(
		() =>
			organizations.find((org) => org.id === selectedOrganizationId) ?? null,
		[organizations, selectedOrganizationId],
	);

	const orgOptions: ComboOption[] = useMemo(
		() =>
			organizations.map((org) => ({
				value: org.id,
				label: `${org.name} (${org.slug})`,
			})),
		[organizations],
	);

	const inviteEmailOptions: ComboOption[] = useMemo(() => {
		const values = new Set<string>();
		const result: ComboOption[] = [];
		for (const invitation of userInvitations) {
			if (!values.has(invitation.email)) {
				values.add(invitation.email);
				result.push({ value: invitation.email, label: invitation.email });
			}
		}
		return result;
	}, [userInvitations]);

	const selectedOrgMatchesActiveSessionOrg =
		typeof activeOrganizationIdFromSession === "string" &&
		activeOrganizationIdFromSession === selectedOrganizationId;
	const currentUserMembership = useMemo(() => {
		if (!sessionUserId) return null;
		return members.find((member) => member.userId === sessionUserId) ?? null;
	}, [members, sessionUserId]);
	const currentUserRole = currentUserMembership?.role ?? null;
	const canManageSelectedOrg =
		selectedOrgMatchesActiveSessionOrg &&
		(currentUserRole === "owner" || currentUserRole === "admin");
	const inviteGuardReason = !selectedOrganizationId
		? "Select an organization first."
		: !selectedOrgMatchesActiveSessionOrg
			? "Set this organization as active in session before inviting."
			: !currentUserRole
				? "Current user is not a member of the selected organization."
				: currentUserRole === "member"
					? "Members cannot invite users. Requires admin or owner role."
					: null;
	const isPendingInvitationStatus = (status: string) =>
		status.trim().toLowerCase() === "pending";

  const appendRow = useCallback((action: string, status: string, detail: unknown) => {
    const line = `${safeStringify(detail)}`;
    setRows((previous) =>
      [
        { id: crypto.randomUUID(), action, status, detail: line },
        ...previous,
      ].slice(0, 15),
    );
  }, []);

  const setActionError = useCallback((message: string) => {
    setError(message);
    setNotice(null);
  }, []);

  const setActionNotice = useCallback((message: string) => {
    setNotice(message);
    setError(null);
  }, []);

  const loadOrganizations = useCallback(async () => {
		const result = await organizationApi.listOrganizations();
		appendRow("organization/list", result.ok ? "ok" : "error", {
			status: result.status,
			message: result.message,
			athenaTime: result.athenaTime,
			proxyTime: result.proxyTime,
		});
		if (!result.ok) {
			throw new Error(result.message);
		}
		const list = Array.isArray(result.body) ? result.body : [];
		const parsed = list
			.map(normalizeOrganization)
			.filter((value): value is Organization => value !== null);
		setOrganizations(parsed);
		const currentSelectedOrganizationId = selectedOrganizationIdRef.current;
		const currentActiveOrganizationId =
			activeOrganizationIdFromSessionRef.current;
		const currentAutoSelection = selectedOrganizationAutoRef.current;
		const selectedOrganizationStillExists = parsed.some(
			(org) => org.id === currentSelectedOrganizationId,
		);

		if (!currentSelectedOrganizationId || !selectedOrganizationStillExists) {
			const preferred = currentActiveOrganizationId
				? parsed.find((org) => org.id === currentActiveOrganizationId)
				: null;
			const next = preferred?.id ?? parsed[0]?.id ?? "";
			if (next !== currentSelectedOrganizationId) {
				selectedOrganizationIdRef.current = next;
				setSelectedOrganizationId(next);
			}
			setSelectedOrganizationAuto(true);
			return;
		}

		if (
			currentAutoSelection &&
			currentActiveOrganizationId &&
			parsed.some((org) => org.id === currentActiveOrganizationId) &&
			currentSelectedOrganizationId !== currentActiveOrganizationId
		) {
			selectedOrganizationIdRef.current = currentActiveOrganizationId;
			setSelectedOrganizationId(currentActiveOrganizationId);
      setSelectedOrganizationAuto(true);
    }
  }, [appendRow, organizationApi]);

  const loadUserInvitations = useCallback(async () => {
		const result = await organizationApi.listUserInvitations();
		appendRow(
			"organization/list-user-invitations",
			result.ok ? "ok" : "error",
			{
				status: result.status,
				message: result.message,
				athenaTime: result.athenaTime,
				proxyTime: result.proxyTime,
			},
		);
		if (!result.ok) {
			throw new Error(result.message);
		}
		const list = Array.isArray(result.body) ? result.body : [];
		const parsed = list
			.map(normalizeInvitation)
			.filter((value): value is Invitation => value !== null);
    setUserInvitations(parsed);
  }, [appendRow, organizationApi]);

  const loadOrganizationDetails = useCallback(async (organizationId: string) => {
		if (!organizationId) {
			setMembers([]);
			setOrganizationInvitations([]);
			return;
		}
		const [membersResult, invitationsResult] = await Promise.all([
			organizationApi.listMembers(organizationId),
			organizationApi.listInvitations(organizationId),
		]);
		appendRow("organization/list-members", membersResult.ok ? "ok" : "error", {
			status: membersResult.status,
			message: membersResult.message,
			athenaTime: membersResult.athenaTime,
			proxyTime: membersResult.proxyTime,
		});
		appendRow(
			"organization/list-invitations",
			invitationsResult.ok ? "ok" : "error",
			{
				status: invitationsResult.status,
				message: invitationsResult.message,
				athenaTime: invitationsResult.athenaTime,
				proxyTime: invitationsResult.proxyTime,
			},
		);
		if (!membersResult.ok) throw new Error(membersResult.message);
		if (!invitationsResult.ok) throw new Error(invitationsResult.message);

		const membersBody =
			membersResult.body &&
			typeof membersResult.body === "object" &&
			Array.isArray((membersResult.body as Record<string, unknown>).members)
				? ((membersResult.body as Record<string, unknown>).members as unknown[])
				: Array.isArray(membersResult.body)
					? (membersResult.body as unknown[])
					: [];
		const invitationsBody = Array.isArray(invitationsResult.body)
			? invitationsResult.body
			: [];

		const nextMembers = membersBody
			.map(normalizeMember)
			.filter((value): value is Member => value !== null);
		const nextInvitations = invitationsBody
			.map(normalizeInvitation)
			.filter((value): value is Invitation => value !== null);

		setMembers(nextMembers);
		setOrganizationInvitations(nextInvitations);
		setRoleDraftByMember((previous) => {
			const next: Record<string, string> = { ...previous };
			for (const member of nextMembers) {
				if (!next[member.id]) {
					next[member.id] = member.role;
				}
			}
      return next;
    });
  }, [appendRow, organizationApi]);

  const loadApiKeys = useCallback(async (silent = false, fromPolling = false) => {
		if (fromPolling && suppressApiKeyPolling) {
			return;
		}
		if (!silent) {
			setApiKeyLoading(true);
			setError(null);
			setNotice(null);
		}
		try {
			const result = await authApi("/api-key/list", { method: "GET" });
			appendRow("api-key/list", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
				body: result.body,
				athenaTime: result.athenaTime,
				proxyTime: result.proxyTime,
			});
			if (!result.ok && fromPolling && result.status >= 500) {
				setSuppressApiKeyPolling(true);
				setApiKeys([]);
				return;
			}
			if (!result.ok) {
				throw new Error(result.message);
			}
			if (fromPolling && suppressApiKeyPolling) {
				setSuppressApiKeyPolling(false);
			}
			const body = result.body;
			const list = Array.isArray(body)
				? body
				: body &&
						typeof body === "object" &&
						Array.isArray((body as Record<string, unknown>).keys)
					? ((body as Record<string, unknown>).keys as unknown[])
					: [];
			const parsed = list
				.map((item): ApiKeyRow | null => {
					if (!item || typeof item !== "object") return null;
					const record = item as Record<string, unknown>;
					if (typeof record.id !== "string") return null;
					return {
						id: record.id,
						name: typeof record.name === "string" ? record.name : "(unnamed)",
						prefix:
							typeof record.prefix === "string" ? record.prefix : undefined,
						enabled:
							typeof record.enabled === "boolean" ? record.enabled : undefined,
						createdAt:
							typeof record.createdAt === "string"
								? record.createdAt
								: typeof record.created_at === "string"
									? record.created_at
									: null,
						expiresAt:
							typeof record.expiresAt === "string"
								? record.expiresAt
								: typeof record.expires_at === "string"
									? record.expires_at
									: null,
					};
				})
				.filter((value): value is ApiKeyRow => value !== null);
			setApiKeys(parsed);
		} catch (apiKeyError) {
			if (!silent) {
				setActionError(
					apiKeyError instanceof Error
						? apiKeyError.message
						: "Failed to load API keys",
				);
			}
			setApiKeys([]);
    } finally {
      if (!silent) setApiKeyLoading(false);
    }
  }, [appendRow, authApi, setActionError, suppressApiKeyPolling]);

  const runApiCoverageProbe = async () => {
		setApiCoverageLoading(true);
		setError(null);
		setNotice(null);
		try {
			const probes: Array<{
				label: string;
				path: string;
				init?: RequestInit;
			}> = [
				{ label: "get-session", path: "/get-session", init: { method: "GET" } },
				{
					label: "list-sessions",
					path: "/list-sessions",
					init: { method: "GET" },
				},
				{
					label: "list-accounts",
					path: "/list-accounts",
					init: { method: "GET" },
				},
				{
					label: "passkey/list-user-passkeys",
					path: "/passkey/list-user-passkeys",
					init: { method: "GET" },
				},
				{
					label: "api-key/list",
					path: "/api-key/list",
					init: { method: "GET" },
				},
			];

			if (selectedOrganizationId) {
				const encoded = encodeURIComponent(selectedOrganizationId);
				probes.push(
					{
						label: "organization/get-full-organization",
						path: `/organization/get-full-organization?organizationId=${encoded}`,
						init: { method: "GET" },
					},
					{
						label: "organization/get-active-member",
						path: `/organization/get-active-member?organizationId=${encoded}`,
						init: { method: "GET" },
					},
				);
			}

			const results = await Promise.all(
				probes.map(async (probe) => {
					const result = await authApi(probe.path, probe.init);
					appendRow(`probe/${probe.label}`, result.ok ? "ok" : "error", {
						status: result.status,
						message: result.message,
						athenaTime: result.athenaTime,
						proxyTime: result.proxyTime,
					});
					return result;
				}),
			);

			const okCount = results.filter((result) => result.ok).length;
			setActionNotice(
				`API probe finished: ${okCount}/${results.length} endpoints OK.`,
			);
		} catch (probeError) {
			setActionError(
				probeError instanceof Error
					? probeError.message
					: "Failed to run API probe",
			);
		} finally {
			setApiCoverageLoading(false);
		}
	};

  const refreshAll = useCallback(async () => {
    setLoading(true);
    setError(null);
    setNotice(null);
    try {
      await Promise.all([
        loadOrganizations(),
        loadUserInvitations(),
        loadApiKeys(true, true),
        refetchSession(),
      ]);
      const organizationId = selectedOrganizationIdRef.current;
      if (organizationId) {
        await loadOrganizationDetails(organizationId);
      }
      setActionNotice("Organization data refreshed.");
    } catch (refreshError) {
      setActionError(
        refreshError instanceof Error
          ? refreshError.message
          : "Failed to refresh organization data",
      );
    } finally {
      setLoading(false);
    }
  }, [
    loadApiKeys,
    loadOrganizationDetails,
    loadOrganizations,
    loadUserInvitations,
    refetchSession,
    setActionError,
    setActionNotice,
  ]);

  const acceptInvitation = useCallback(
    async (invitationId: string, expectedOrganizationId?: string) => {
      setLoading(true);
      setError(null);
      setNotice(null);
      try {
        const result = await organizationApi.acceptInvitation(invitationId);
        appendRow("organization/accept-invitation", result.ok ? "ok" : "error", {
          status: result.status,
          message: result.message,
          body: result.body,
        });
        if (!result.ok) throw new Error(result.message);

        const bodyRecord =
          result.body && typeof result.body === "object"
            ? (result.body as Record<string, unknown>)
            : null;
        const invitationRecord =
          bodyRecord?.invitation && typeof bodyRecord.invitation === "object"
            ? (bodyRecord.invitation as Record<string, unknown>)
            : null;
        const acceptedOrganizationId =
          (typeof invitationRecord?.organizationId === "string"
            ? invitationRecord.organizationId
            : typeof invitationRecord?.organization_id === "string"
              ? invitationRecord.organization_id
              : undefined) ?? expectedOrganizationId;

        await Promise.all([loadUserInvitations(), loadOrganizations()]);

        const targetOrganizationId =
          acceptedOrganizationId || selectedOrganizationId;
        if (targetOrganizationId) {
          const setActiveResult =
            await organizationApi.setActiveOrganization(targetOrganizationId);
          appendRow(
            "organization/set-active (post-accept)",
            setActiveResult.ok ? "ok" : "error",
            {
              status: setActiveResult.status,
              message: setActiveResult.message,
              body: setActiveResult.body,
            },
          );
          if (!setActiveResult.ok) {
            throw new Error(setActiveResult.message);
          }
          setSelectedOrganizationId(targetOrganizationId);
          setSelectedOrganizationAuto(false);
          await Promise.all([
            refetchSession(),
            loadOrganizationDetails(targetOrganizationId),
          ]);
        }
        setActionNotice("Invitation accepted.");
      } catch (acceptErrorValue) {
        setActionError(
          acceptErrorValue instanceof Error
            ? acceptErrorValue.message
            : "Failed to accept invitation",
        );
      } finally {
        setLoading(false);
      }
    },
    [
      appendRow,
      loadOrganizationDetails,
      loadOrganizations,
      loadUserInvitations,
      organizationApi,
      refetchSession,
      selectedOrganizationId,
      setActionError,
      setActionNotice,
    ],
  );

	useEffect(() => {
		selectedOrganizationIdRef.current = selectedOrganizationId;
	}, [selectedOrganizationId]);

	useEffect(() => {
		selectedOrganizationAutoRef.current = selectedOrganizationAuto;
	}, [selectedOrganizationAuto]);

	useEffect(() => {
		activeOrganizationIdFromSessionRef.current =
			typeof activeOrganizationIdFromSession === "string"
				? activeOrganizationIdFromSession
				: "";
	}, [activeOrganizationIdFromSession]);

	useEffect(() => {
		if (typeof window === "undefined") return;
		if (inviteCallbackUrl) return;
		setInviteCallbackUrl(`${window.location.origin}/organizations`);
	}, [inviteCallbackUrl]);

  useEffect(() => {
    void refreshAll();
  }, [refreshAll]);

  useEffect(() => {
    const onVisible = () => {
      if (!document.hidden) {
        void refreshAll();
      }
    };
    const interval = window.setInterval(() => {
      void refreshAll();
    }, 30000);
    document.addEventListener("visibilitychange", onVisible);
    return () => {
      window.clearInterval(interval);
      document.removeEventListener("visibilitychange", onVisible);
    };
  }, [refreshAll]);

	useEffect(() => {
		if (!initialInvitationId || invitationAutoAcceptAttempted.current) return;
		if (sessionPending) return;
		if (!sessionData) {
			setActionNotice(
				"Invitation link detected. Sign in or sign up with the invited email, then open this link again.",
			);
			return;
		}
		invitationAutoAcceptAttempted.current = true;
		void acceptInvitation(initialInvitationId);
	}, [
		acceptInvitation,
		initialInvitationId,
		sessionData,
		sessionPending,
		setActionNotice,
	]);

	useEffect(() => {
		if (!selectedOrganizationId) return;
		void (async () => {
			try {
				await loadOrganizationDetails(selectedOrganizationId);
			} catch (loadError) {
				setActionError(
					loadError instanceof Error
						? loadError.message
						: "Failed to load organization details",
				);
			}
		})();
	}, [loadOrganizationDetails, selectedOrganizationId, setActionError]);

	const createOrganization = async (event: React.FormEvent) => {
		event.preventDefault();
		if (!createName.trim()) {
			setActionError("Organization name is required.");
			return;
		}
		if (!createSlug.trim()) {
			setActionError("Organization slug is required.");
			return;
		}
		setLoading(true);
		setError(null);
		setNotice(null);
		try {
			const slugCheck = await authApi("/organization/check-slug", {
				method: "POST",
				body: JSON.stringify({ slug: createSlug.trim() }),
			});
			appendRow("organization/check-slug", slugCheck.ok ? "ok" : "error", {
				status: slugCheck.status,
				message: slugCheck.message,
				body: slugCheck.body,
			});
			if (!slugCheck.ok) {
				throw new Error(slugCheck.message);
			}
			const slugBody = slugCheck.body as Record<string, unknown>;
			if (slugBody && slugBody.status === false) {
				throw new Error("Slug already taken.");
			}

			const result = await organizationApi.createOrganization({
				name: createName.trim(),
				slug: createSlug.trim(),
			});
			appendRow("organization/create", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
				body: result.body,
			});
			if (!result.ok) throw new Error(result.message);

			const created = normalizeOrganization(result.body);
			await loadOrganizations();
			if (created?.id) {
				setSelectedOrganizationId(created.id);
				setSelectedOrganizationAuto(false);
			}
			setCreateName("");
			setCreateSlug("");
			setCreateSlugTouched(false);
			setActionNotice("Organization created.");
		} catch (createError) {
			setActionError(
				createError instanceof Error
					? createError.message
					: "Failed to create organization",
			);
		} finally {
			setLoading(false);
		}
	};

	const setActiveOrganization = async (organizationId: string) => {
		setLoading(true);
		setError(null);
		setNotice(null);
		try {
			const result =
				await organizationApi.setActiveOrganization(organizationId);
			appendRow("organization/set-active", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
				body: result.body,
			});
			if (!result.ok) throw new Error(result.message);
			setSelectedOrganizationId(organizationId);
			setSelectedOrganizationAuto(false);
			await Promise.all([
				refetchSession(),
				loadOrganizations(),
				loadUserInvitations(),
				loadOrganizationDetails(organizationId),
			]);
			setActionNotice("Active organization updated.");
		} catch (setErrorValue) {
			setActionError(
				setErrorValue instanceof Error
					? setErrorValue.message
					: "Failed to set active organization",
			);
		} finally {
			setLoading(false);
		}
	};

	const inviteMember = async (event: React.FormEvent) => {
		event.preventDefault();
		if (!canManageSelectedOrg) {
			setActionError(
				inviteGuardReason || "Invite action blocked by preflight guard.",
			);
			return;
		}
		if (!selectedOrganizationId) {
			setActionError("Select an organization first.");
			return;
		}
		if (!inviteEmail.trim()) {
			setActionError("Invite email is required.");
			return;
		}
		const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
		if (!emailRegex.test(inviteEmail.trim())) {
			setActionError("Invite email must be valid.");
			return;
		}
		setLoading(true);
		setError(null);
		setNotice(null);
		try {
			const result = await organizationApi.inviteMember({
				organizationId: selectedOrganizationId,
				email: inviteEmail.trim(),
				role: inviteRole,
				callbackURL: inviteCallbackUrl.trim() || undefined,
			});
			appendRow("organization/invite-member", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
				body: result.body,
			});
			if (!result.ok) throw new Error(result.message);
			setEmailEvidenceRecipient(inviteEmail.trim());
			await loadOrganizationDetails(selectedOrganizationId);
			setActionNotice(
				"Invitation created and email delivery was attempted through the configured adapter.",
			);
		} catch (inviteErrorValue) {
			setActionError(
				inviteErrorValue instanceof Error
					? inviteErrorValue.message
					: "Failed to invite member",
			);
		} finally {
			setLoading(false);
		}
	};

	const rejectInvitation = async (invitationId: string) => {
		setLoading(true);
		setError(null);
		setNotice(null);
		try {
			const result = await organizationApi.rejectInvitation(invitationId);
			appendRow("organization/reject-invitation", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
				body: result.body,
			});
			if (!result.ok) throw new Error(result.message);
			await loadUserInvitations();
			setActionNotice("Invitation declined.");
		} catch (rejectErrorValue) {
			setActionError(
				rejectErrorValue instanceof Error
					? rejectErrorValue.message
					: "Failed to reject invitation",
			);
		} finally {
			setLoading(false);
		}
	};

	const cancelInvitation = async (invitationId: string) => {
		if (!canManageSelectedOrg) {
			setActionError(
				inviteGuardReason || "Cancel action blocked by preflight guard.",
			);
			return;
		}
		const invitation = organizationInvitations.find(
			(item) => item.id === invitationId,
		);
		if (!invitation) {
			setActionError("Invitation not found in current organization list.");
			return;
		}
		if (!isPendingInvitationStatus(invitation.status)) {
			setActionError(
				`Only pending invitations can be canceled. Current status: ${invitation.status}.`,
			);
			return;
		}
		setLoading(true);
		setError(null);
		setNotice(null);
		try {
			const result = await organizationApi.cancelInvitation(invitationId);
			appendRow("organization/cancel-invitation", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
				body: result.body,
			});
			if (!result.ok) throw new Error(result.message);
			if (selectedOrganizationId) {
				await Promise.all([
					loadOrganizationDetails(selectedOrganizationId),
					loadUserInvitations(),
					loadOrganizations(),
					refetchSession(),
				]);
			} else {
				await Promise.all([
					loadUserInvitations(),
					loadOrganizations(),
					refetchSession(),
				]);
			}
			setActionNotice("Invitation canceled.");
		} catch (cancelErrorValue) {
			setActionError(
				cancelErrorValue instanceof Error
					? cancelErrorValue.message
					: "Failed to cancel invitation",
			);
		} finally {
			setLoading(false);
		}
	};

	const updateMemberRole = async (memberId: string) => {
		if (!canManageSelectedOrg) {
			setActionError(
				inviteGuardReason || "Role update blocked by preflight guard.",
			);
			return;
		}
		if (!selectedOrganizationId) {
			setActionError("Select an organization first.");
			return;
		}
		const role = roleDraftByMember[memberId];
		if (!role) {
			setActionError("Select a role first.");
			return;
		}
		setLoading(true);
		setError(null);
		setNotice(null);
		try {
			const result = await organizationApi.updateMemberRole({
				memberId,
				role,
				organizationId: selectedOrganizationId,
			});
			appendRow("organization/update-member-role", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
				body: result.body,
			});
			if (!result.ok) throw new Error(result.message);
			await loadOrganizationDetails(selectedOrganizationId);
			setActionNotice("Member role updated.");
		} catch (roleError) {
			setActionError(
				roleError instanceof Error
					? roleError.message
					: "Failed to update member role",
			);
		} finally {
			setLoading(false);
		}
	};

	const removeMember = async (memberId: string) => {
		if (!canManageSelectedOrg) {
			setActionError(
				inviteGuardReason || "Remove action blocked by preflight guard.",
			);
			return;
		}
		if (!selectedOrganizationId) {
			setActionError("Select an organization first.");
			return;
		}
		const targetMember = members.find((member) => member.id === memberId);
		if (targetMember?.role?.includes("owner")) {
			setActionError(
				"Owners cannot be removed as members. Delete the organization instead.",
			);
			return;
		}
		setLoading(true);
		setError(null);
		setNotice(null);
		try {
			const result = await organizationApi.removeMember({
				memberId,
				organizationId: selectedOrganizationId,
			});
			appendRow("organization/remove-member", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
				body: result.body,
			});
			if (!result.ok) throw new Error(result.message);
			await loadOrganizationDetails(selectedOrganizationId);
			setActionNotice("Member removed.");
		} catch (removeErrorValue) {
			setActionError(
				removeErrorValue instanceof Error
					? removeErrorValue.message
					: "Failed to remove member",
			);
		} finally {
			setLoading(false);
		}
	};

	const loadCoupledEmails = useCallback(
		async (silent = false) => {
			setEmailEvidenceLoading(true);
			if (!silent) {
				setError(null);
				setNotice(null);
			}
			try {
				const endpoints = [
					...(sessionUserRole === "admin"
						? ["/admin/email/list?limit=250&offset=0"]
						: []),
					"/email/list?limit=250&offset=0",
				];
				let chosen: ApiCallResult | null = null;
				let endpointUsed = "";
				for (const endpoint of endpoints) {
					const result = await organizationApi.listEmailRows(endpoint);
					appendRow(`email-source ${endpoint}`, result.ok ? "ok" : "error", {
						status: result.status,
						message: result.message,
						athenaTime: result.athenaTime,
						proxyTime: result.proxyTime,
					});
					if (result.ok) {
						chosen = result;
						endpointUsed = endpoint;
						break;
					}
				}
				if (!chosen) {
					throw new Error(
						"No email listing endpoint is available for this session.",
					);
				}
				const body = chosen.body as Record<string, unknown>;
				const list = Array.isArray(body?.emails)
					? (body.emails as unknown[])
					: [];
				const parsed = list
					.map(normalizeEmailRow)
					.filter((value): value is EmailRow => value !== null);
				const invitationIds = new Set(
					[...organizationInvitations, ...userInvitations].map((invitation) =>
						invitation.id.toLowerCase(),
					),
				);
				const invitationRecipients = new Set(
					[...organizationInvitations, ...userInvitations]
						.map((invitation) => invitation.email.toLowerCase())
						.filter(Boolean),
				);
				const emailHint = emailEvidenceRecipient.trim().toLowerCase();
				const selectedOrgIdLower = selectedOrganizationId.toLowerCase();
				const filtered = parsed.filter((email) => {
					const recipient = email.recipientEmail.toLowerCase();
					const subject = email.subject.toLowerCase();
					const metadataText = safeStringify(email.metadata).toLowerCase();
					if (emailHint && recipient === emailHint) return true;
					if (invitationRecipients.has(recipient)) return true;
					if (subject.includes("invite")) return true;
					if (selectedOrgIdLower && metadataText.includes(selectedOrgIdLower))
						return true;
					for (const invitationId of invitationIds) {
						if (
							metadataText.includes(invitationId) ||
							subject.includes(invitationId)
						)
							return true;
					}
					return false;
				});
				setCoupledEmails(filtered);
				if (!silent) {
					setActionNotice(
						`Loaded ${parsed.length} emails from ${endpointUsed}. Coupled invitation evidence rows: ${filtered.length}.`,
					);
				}
			} catch (loadEmailError) {
				if (!silent) {
					setActionError(
						loadEmailError instanceof Error
							? loadEmailError.message
							: "Failed to load invitation emails",
					);
				}
				setCoupledEmails([]);
			} finally {
				setEmailEvidenceLoading(false);
			}
		},
		[
			appendRow,
			emailEvidenceRecipient,
			organizationApi,
			organizationInvitations,
			selectedOrganizationId,
			sessionUserRole,
			setActionError,
			setActionNotice,
			userInvitations,
		],
	);

	useEffect(() => {
		if (emailEvidenceAutoRefreshTimer.current) {
			clearTimeout(emailEvidenceAutoRefreshTimer.current);
		}
		emailEvidenceAutoRefreshTimer.current = setTimeout(() => {
			void loadCoupledEmails(true);
		}, 400);
		return () => {
			if (emailEvidenceAutoRefreshTimer.current) {
				clearTimeout(emailEvidenceAutoRefreshTimer.current);
			}
		};
	}, [loadCoupledEmails]);

	const createApiKey = async (event: React.FormEvent) => {
		event.preventDefault();
		const name = newApiKeyName.trim();
		if (!name) {
			setActionError("API key name is required.");
			return;
		}
		setApiKeyLoading(true);
		setError(null);
		setNotice(null);
		try {
			const result = await authApi("/api-key/create", {
				method: "POST",
				body: JSON.stringify({ name }),
			});
			appendRow("api-key/create", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
			});
			if (!result.ok) throw new Error(result.message);
			const body = result.body as Record<string, unknown>;
			const raw =
				typeof body?.key === "string"
					? body.key
					: body?.apiKey &&
							typeof body.apiKey === "object" &&
							typeof (body.apiKey as Record<string, unknown>).key === "string"
						? ((body.apiKey as Record<string, unknown>).key as string)
						: null;
			setNewApiKeyRawValue(raw);
			await loadApiKeys(true);
			setActionNotice("API key created.");
		} catch (apiKeyError) {
			setActionError(
				apiKeyError instanceof Error
					? apiKeyError.message
					: "Failed to create API key",
			);
		} finally {
			setApiKeyLoading(false);
		}
	};

	const deleteApiKey = async (id: string) => {
		setApiKeyLoading(true);
		setError(null);
		setNotice(null);
		try {
			const result = await authApi("/api-key/delete", {
				method: "POST",
				body: JSON.stringify({ id }),
			});
			appendRow("api-key/delete", result.ok ? "ok" : "error", {
				status: result.status,
				message: result.message,
			});
			if (!result.ok) throw new Error(result.message);
			await loadApiKeys(true);
			setActionNotice("API key deleted.");
		} catch (apiKeyError) {
			setActionError(
				apiKeyError instanceof Error
					? apiKeyError.message
					: "Failed to delete API key",
			);
		} finally {
			setApiKeyLoading(false);
		}
	};

	const orgRows = organizations.length
		? organizations
		: [{ id: "empty", name: "-", slug: "-", createdAt: "-" }];
	const memberRows = members.length
		? members
		: [
				{
					id: "empty",
					organizationId: "-",
					userId: "-",
					role: "-",
					createdAt: "-",
					user: { email: "-", name: "-" },
				},
			];
	const orgInvitationRows = organizationInvitations.length
		? organizationInvitations
		: [
				{
					id: "empty",
					organizationId: "-",
					email: "-",
					role: "-",
					status: "-",
					createdAt: "-",
					expiresAt: "-",
				},
			];
	const userInvitationRows = userInvitations.length
		? userInvitations
		: [
				{
					id: "empty",
					organizationId: "-",
					email: "-",
					role: "-",
					status: "-",
					createdAt: "-",
					expiresAt: "-",
				},
			];
	const emailRows = coupledEmails.length
		? coupledEmails
		: [
				{
					id: "empty",
					recipientEmail: "-",
					subject: "No invitation-coupled emails found",
					fromAddress: "-",
					provider: "-",
					createdAt: "-",
					metadata: null,
				},
			];
	const apiKeyRows = apiKeys.length
		? apiKeys
		: [
				{
					id: "empty",
					name: "No API keys",
					prefix: "-",
					enabled: undefined,
					createdAt: "-",
					expiresAt: "-",
				},
			];

	return (
		<main className="mx-auto w-full max-w-[1600px] px-4 py-6 md:px-6">
			<Card>
				<CardHeader className="space-y-4">
					<div className="flex flex-wrap items-center justify-between gap-2">
						<SharedBackButton fallbackHref="/login" />
						<Badge variant={loading ? "warning" : "secondary"}>
							auto refresh: {loading ? "syncing" : "on (30s + focus)"}
						</Badge>
					</div>
					<div>
						<CardTitle className="text-2xl">Organizations Lab</CardTitle>
						<CardDescription className="mt-1 max-w-3xl">
							End-to-end org flow tester: create orgs, invite members,
							accept/decline invitations, manage members, and inspect invitation
							email evidence.
						</CardDescription>
					</div>
				</CardHeader>
				<CardContent className="grid gap-5">
					<div className="flex flex-wrap gap-2 text-xs">
						<Badge
							variant={
								sessionPending
									? "secondary"
									: sessionError
										? "destructive"
										: sessionData
											? "success"
											: "warning"
							}
						>
							session:{" "}
							{sessionPending
								? "loading"
								: sessionError
									? "error"
									: sessionData
										? "ready"
										: "unauthenticated"}
						</Badge>
						<Badge variant="secondary">
							organizations: {organizations.length}
						</Badge>
						<Badge variant="secondary">members: {members.length}</Badge>
						<Badge variant="secondary">
							org invitations: {organizationInvitations.length}
						</Badge>
						<Badge variant="secondary">
							my invitations: {userInvitations.length}
						</Badge>
						<Badge
							variant={
								sessionEmailVerified === null
									? "secondary"
									: sessionEmailVerified
										? "success"
										: "warning"
							}
						>
							email verified:{" "}
							{sessionEmailVerified === null
								? "unknown"
								: sessionEmailVerified
									? "true"
									: "false"}
						</Badge>
						<Badge variant="secondary">
							active org:{" "}
							{typeof activeOrganizationIdFromSession === "string"
								? activeOrganizationIdFromSession
								: "none"}
						</Badge>
					</div>

					{error ? (
						<p className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700">
							{error}
						</p>
					) : null}
					{notice ? (
						<p className="rounded-lg border border-emerald-200 bg-emerald-50 px-3 py-2 text-sm text-emerald-700">
							{notice}
						</p>
					) : null}

					<SessionOrganizationSwitcher
						activeOrganizationId={
							typeof activeOrganizationIdFromSession === "string"
								? activeOrganizationIdFromSession
								: null
						}
						onSessionRefresh={async () => {
							await refreshAll();
						}}
					/>

					<section className="grid gap-3 rounded-2xl border border-slate-200 bg-white p-5">
						<div className="flex flex-wrap items-center justify-between gap-2">
							<h3 className="text-sm font-semibold">
								Action preflight debugger
							</h3>
							<div className="flex items-center gap-2">
								<Badge variant={apiCoverageLoading ? "warning" : "secondary"}>
									{apiCoverageLoading ? "probing api..." : "api coverage"}
								</Badge>
								<Button
									type="button"
									size="sm"
									variant="secondary"
									disabled={apiCoverageLoading}
									onClick={() => void runApiCoverageProbe()}
								>
									Probe API
								</Button>
							</div>
						</div>
						<div className="grid gap-2 text-xs md:grid-cols-2">
							<div className="rounded-md border border-slate-200 p-3">
								<div className="font-medium">Selected org</div>
								<div>{selectedOrganizationId || "(none)"}</div>
							</div>
							<div className="rounded-md border border-slate-200 p-3">
								<div className="font-medium">Active org in session</div>
								<div>
									{typeof activeOrganizationIdFromSession === "string"
										? activeOrganizationIdFromSession
										: "(none)"}
								</div>
							</div>
							<div className="rounded-md border border-slate-200 p-3">
								<div className="font-medium">
									Current user role in selected org
								</div>
								<div>{currentUserRole || "(not a member or unresolved)"}</div>
							</div>
							<div className="rounded-md border border-slate-200 p-3">
								<div className="font-medium">Invite / manage members</div>
								<div>{canManageSelectedOrg ? "enabled" : "disabled"}</div>
							</div>
						</div>
						{!canManageSelectedOrg ? (
							<p className="rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-800">
								{inviteGuardReason || "Action disabled by preflight guard."}
							</p>
						) : null}
					</section>

					<section className="grid gap-4 rounded-2xl border border-slate-200 bg-white p-5">
						<h3 className="text-sm font-semibold">Create organization</h3>
						<form
							className="grid gap-3 md:grid-cols-4 md:items-end"
							onSubmit={createOrganization}
						>
							<div className="grid gap-2">
								<Label htmlFor="org-name">Name</Label>
								<Input
									id="org-name"
									value={createName}
									onChange={(event) => {
										const nextName = event.target.value;
										setCreateName(nextName);
										if (!createSlugTouched) {
											setCreateSlug(slugify(nextName));
										}
									}}
									placeholder="Acme Inc"
								/>
							</div>
							<div className="grid gap-2">
								<Label htmlFor="org-slug">Slug</Label>
								<Input
									id="org-slug"
									value={createSlug}
									onChange={(event) => {
										setCreateSlugTouched(true);
										setCreateSlug(slugify(event.target.value));
									}}
									placeholder="acme-inc"
								/>
							</div>
							<div className="md:col-span-2">
								<div className="grid gap-2">
									<Label>Current org selector</Label>
									<Combobox
										value={selectedOrganizationId}
										onChange={(value) => {
											setSelectedOrganizationAuto(false);
											setSelectedOrganizationId(value);
										}}
										options={orgOptions}
										placeholder="Select organization"
									/>
								</div>
								<div className="mt-2 grid gap-2 md:max-w-[220px]">
									<Label className="opacity-0">Action</Label>
									<Button type="submit" disabled={loading} className="w-full">
										Create organization
									</Button>
								</div>
							</div>
						</form>
					</section>

					<section className="grid gap-4 rounded-2xl border border-slate-200 bg-white p-5">
						<h3 className="text-sm font-semibold">Invite member</h3>
						<form
							className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_220px]"
							onSubmit={inviteMember}
						>
							<div className="grid gap-3">
								<div className="grid gap-2">
									<Label>Organization</Label>
									<Combobox
										value={selectedOrganizationId}
										onChange={(value) => {
											setSelectedOrganizationAuto(false);
											setSelectedOrganizationId(value);
										}}
										options={orgOptions}
										placeholder="Select organization"
									/>
								</div>
								<div className="grid gap-2">
									<Label>Invite email</Label>
									<Combobox
										value={inviteEmail}
										onChange={setInviteEmail}
										options={inviteEmailOptions}
										placeholder="Pick known invitee or type below"
									/>
									<Input
										value={inviteEmail}
										onChange={(event) => setInviteEmail(event.target.value)}
										placeholder="member@example.com"
									/>
								</div>
								<div className="grid gap-2">
									<Label htmlFor="invite-callback-url">
										Invitation callback URL
									</Label>
									<Input
										id="invite-callback-url"
										value={inviteCallbackUrl}
										onChange={(event) =>
											setInviteCallbackUrl(event.target.value)
										}
										placeholder="http://localhost:3001/organizations"
									/>
								</div>
							</div>
							<div className="flex flex-col gap-3">
								<div className="flex flex-col">
									<Label>Role</Label>
									<Select value={inviteRole} onValueChange={setInviteRole}>
										<SelectTrigger>
											<SelectValue />
										</SelectTrigger>
										<SelectContent>
											{roleOptions.map((role) => (
												<SelectItem key={role} value={role}>
													{role}
												</SelectItem>
											))}
										</SelectContent>
									</Select>
								</div>
								<div className="flex flex-col">
									<Label className="opacity-0">Action</Label>
									<Button
										type="submit"
										disabled={loading || !canManageSelectedOrg}
										title={inviteGuardReason ?? undefined}
										className="w-full"
									>
										Invite member
									</Button>
								</div>
							</div>
						</form>
						{!canManageSelectedOrg ? (
							<p className="text-xs text-slate-600">
								Invite disabled: {inviteGuardReason}
							</p>
						) : null}
					</section>

					<section className="grid gap-3 rounded-2xl border border-slate-200 bg-white p-5">
						<div className="flex flex-wrap items-center justify-between gap-2">
							<h3 className="text-sm font-semibold">
								Invitation-linked email evidence
							</h3>
							<Badge variant={emailEvidenceLoading ? "warning" : "secondary"}>
								{emailEvidenceLoading
									? "updating evidence..."
									: "auto evidence refresh enabled"}
							</Badge>
						</div>
						<div className="grid gap-2 md:max-w-md">
							<Label htmlFor="invite-email-evidence">
								Recipient filter (optional)
							</Label>
							<Input
								id="invite-email-evidence"
								value={emailEvidenceRecipient}
								onChange={(event) =>
									setEmailEvidenceRecipient(event.target.value)
								}
								placeholder="member@example.com"
							/>
						</div>
						<Table>
							<Table.Content aria-label="Invitation email evidence">
								<Table.Header>
									<Table.Column id="created" key="created" isRowHeader>
										Created
									</Table.Column>
									<Table.Column id="recipient" key="recipient">
										Recipient
									</Table.Column>
									<Table.Column id="subject" key="subject">
										Subject
									</Table.Column>
									<Table.Column id="provider" key="provider">
										Provider
									</Table.Column>
									<Table.Column id="metadata" key="metadata">
										Metadata
									</Table.Column>
								</Table.Header>
								<Table.Body items={emailRows}>
									{(item) => (
										<Table.Row key={item.id} id={item.id}>
											<Table.Cell>{item.createdAt}</Table.Cell>
											<Table.Cell>{item.recipientEmail}</Table.Cell>
											<Table.Cell>{item.subject}</Table.Cell>
											<Table.Cell>{item.provider}</Table.Cell>
											<Table.Cell className="max-w-[380px] truncate">
												{item.metadata ? safeStringify(item.metadata) : "-"}
											</Table.Cell>
										</Table.Row>
									)}
								</Table.Body>
							</Table.Content>
						</Table>
					</section>

					<section className="grid gap-4 xl:grid-cols-2">
						<Card>
							<CardHeader>
								<CardTitle className="text-base">Organizations</CardTitle>
								<CardDescription>
									Use the action button to set active organization and sync page
									context.
								</CardDescription>
							</CardHeader>
							<CardContent>
								<Table>
									<Table.Content aria-label="Organizations">
										<Table.Header>
											<Table.Column id="name" key="name" isRowHeader>
												Name
											</Table.Column>
											<Table.Column id="slug" key="slug">
												Slug
											</Table.Column>
											<Table.Column id="id" key="id">
												ID
											</Table.Column>
											<Table.Column id="actions" key="actions">
												Actions
											</Table.Column>
										</Table.Header>
										<Table.Body items={orgRows}>
											{(item) => (
												<Table.Row key={item.id} id={item.id}>
													<Table.Cell>{item.name}</Table.Cell>
													<Table.Cell>{item.slug}</Table.Cell>
													<Table.Cell className="max-w-[260px] truncate">
														{item.id}
													</Table.Cell>
													<Table.Cell>
														{item.id !== "empty" ? (
															<div className="flex flex-wrap gap-2">
																<Button
																	type="button"
																	variant={
																		typeof activeOrganizationIdFromSession ===
																			"string" &&
																		activeOrganizationIdFromSession === item.id
																			? "default"
																			: "secondary"
																	}
																	size="sm"
																	disabled={loading}
																	onClick={() =>
																		void setActiveOrganization(item.id)
																	}
																>
																	{typeof activeOrganizationIdFromSession ===
																		"string" &&
																	activeOrganizationIdFromSession === item.id
																		? "Active"
																		: "Use organization"}
																</Button>
															</div>
														) : (
															"-"
														)}
													</Table.Cell>
												</Table.Row>
											)}
										</Table.Body>
									</Table.Content>
								</Table>
							</CardContent>
						</Card>

						<Card>
							<CardHeader>
								<CardTitle className="text-base">
									Members ({selectedOrganization?.name ?? "none selected"})
								</CardTitle>
								<CardDescription>
									Update role or remove members from selected organization.
								</CardDescription>
							</CardHeader>
							<CardContent>
								<Table>
									<Table.Content aria-label="Organization members">
										<Table.Header>
											<Table.Column id="member" key="member" isRowHeader>
												Member
											</Table.Column>
											<Table.Column id="role" key="role">
												Role
											</Table.Column>
											<Table.Column id="member_id" key="member_id">
												Member ID
											</Table.Column>
											<Table.Column id="actions" key="actions">
												Actions
											</Table.Column>
										</Table.Header>
										<Table.Body items={memberRows}>
											{(item) => (
												<Table.Row key={item.id} id={item.id}>
													<Table.Cell>
														<div className="flex flex-col">
															<span>
																{item.user?.name ||
																	item.user?.email ||
																	item.userId}
															</span>
															<span className="text-xs text-slate-500">
																{item.user?.email || "-"}
															</span>
														</div>
													</Table.Cell>
													<Table.Cell>
														{item.id !== "empty" ? (
															<Select
																value={roleDraftByMember[item.id] ?? item.role}
																onValueChange={(value) =>
																	setRoleDraftByMember((previous) => ({
																		...previous,
																		[item.id]: value,
																	}))
																}
															>
																<SelectTrigger className="w-[140px]">
																	<SelectValue />
																</SelectTrigger>
																<SelectContent>
																	{roleOptions.map((role) => (
																		<SelectItem key={role} value={role}>
																			{role}
																		</SelectItem>
																	))}
																</SelectContent>
															</Select>
														) : (
															"-"
														)}
													</Table.Cell>
													<Table.Cell className="max-w-[220px] truncate">
														{item.id}
													</Table.Cell>
													<Table.Cell>
														{item.id !== "empty" ? (
															<div className="flex flex-wrap gap-2">
																<Button
																	type="button"
																	size="sm"
																	variant="secondary"
																	disabled={loading || !canManageSelectedOrg}
																	title={inviteGuardReason ?? undefined}
																	onClick={() => void updateMemberRole(item.id)}
																>
																	Update role
																</Button>
																<Button
																	type="button"
																	size="sm"
																	variant="destructive"
																	disabled={
																		item.role.includes("owner") ||
																		loading ||
																		!canManageSelectedOrg
																	}
																	title={
																		item.role.includes("owner")
																			? "Owners cannot be removed."
																			: (inviteGuardReason ?? undefined)
																	}
																	onClick={() => void removeMember(item.id)}
																>
																	Remove
																</Button>
															</div>
														) : (
															"-"
														)}
													</Table.Cell>
												</Table.Row>
											)}
										</Table.Body>
									</Table.Content>
								</Table>
							</CardContent>
						</Card>
					</section>

					<section className="grid gap-4 xl:grid-cols-2">
						<Card>
							<CardHeader>
								<CardTitle className="text-base">
									Organization invitations ({organizationInvitations.length})
								</CardTitle>
								<CardDescription>
									Pending and historical invitations for selected organization.
								</CardDescription>
							</CardHeader>
							<CardContent>
								<Table>
									<Table.Content aria-label="Organization invitations">
										<Table.Header>
											<Table.Column id="invitee" key="invitee" isRowHeader>
												Invitee
											</Table.Column>
											<Table.Column id="role" key="role">
												Role
											</Table.Column>
											<Table.Column id="status" key="status">
												Status
											</Table.Column>
											<Table.Column id="id" key="id">
												Invitation ID
											</Table.Column>
											<Table.Column id="actions" key="actions">
												Actions
											</Table.Column>
										</Table.Header>
										<Table.Body items={orgInvitationRows}>
											{(item) => {
												const isPending = isPendingInvitationStatus(
													item.status,
												);
												const cancelDisabledReason = !isPending
													? `Only pending invitations can be canceled (current: ${item.status}).`
													: (inviteGuardReason ?? undefined);
												return (
													<Table.Row key={item.id} id={item.id}>
														<Table.Cell>{item.email}</Table.Cell>
														<Table.Cell>{item.role}</Table.Cell>
														<Table.Cell>{item.status}</Table.Cell>
														<Table.Cell className="max-w-[220px] truncate">
															{item.id}
														</Table.Cell>
														<Table.Cell>
															{item.id !== "empty" ? (
																<Button
																	type="button"
																	size="sm"
																	variant="destructive"
																	disabled={
																		loading ||
																		!canManageSelectedOrg ||
																		!isPending
																	}
																	title={cancelDisabledReason}
																	onClick={() => void cancelInvitation(item.id)}
																>
																	Cancel
																</Button>
															) : (
																"-"
															)}
														</Table.Cell>
													</Table.Row>
												);
											}}
										</Table.Body>
									</Table.Content>
								</Table>
							</CardContent>
						</Card>

						<Card>
							<CardHeader>
								<CardTitle className="text-base">
									My pending invitations ({userInvitations.length})
								</CardTitle>
								<CardDescription>
									Accept or decline invitations for your authenticated user.
								</CardDescription>
							</CardHeader>
							<CardContent>
								<Table>
									<Table.Content aria-label="My invitations">
										<Table.Header>
											<Table.Column id="invitee" key="invitee" isRowHeader>
												Email
											</Table.Column>
											<Table.Column id="organization" key="organization">
												Organization ID
											</Table.Column>
											<Table.Column id="role" key="role">
												Role
											</Table.Column>
											<Table.Column id="id" key="id">
												Invitation ID
											</Table.Column>
											<Table.Column id="actions" key="actions">
												Actions
											</Table.Column>
										</Table.Header>
										<Table.Body items={userInvitationRows}>
											{(item) => (
												<Table.Row key={item.id} id={item.id}>
													<Table.Cell>{item.email}</Table.Cell>
													<Table.Cell className="max-w-[220px] truncate">
														{item.organizationId}
													</Table.Cell>
													<Table.Cell>{item.role}</Table.Cell>
													<Table.Cell className="max-w-[220px] truncate">
														{item.id}
													</Table.Cell>
													<Table.Cell>
														{item.id !== "empty" ? (
															<div className="flex flex-wrap gap-2">
																<Button
																	type="button"
																	size="sm"
																	disabled={loading}
																	onClick={() =>
																		void acceptInvitation(
																			item.id,
																			item.organizationId,
																		)
																	}
																>
																	Accept
																</Button>
																<Button
																	type="button"
																	size="sm"
																	variant="outline"
																	disabled={loading}
																	onClick={() => void rejectInvitation(item.id)}
																>
																	Decline
																</Button>
															</div>
														) : (
															"-"
														)}
													</Table.Cell>
												</Table.Row>
											)}
										</Table.Body>
									</Table.Content>
								</Table>
							</CardContent>
						</Card>
					</section>

					<section className="grid gap-4 rounded-2xl border border-slate-200 bg-white p-5">
						<div className="flex flex-wrap items-center justify-between gap-2">
							<h3 className="text-sm font-semibold">API keys (current user)</h3>
							<Badge variant={apiKeyLoading ? "warning" : "secondary"}>
								{apiKeyLoading ? "syncing keys..." : `${apiKeys.length} keys`}
							</Badge>
						</div>
						<form
							className="grid gap-2 md:grid-cols-[1fr_auto]"
							onSubmit={createApiKey}
						>
							<Input
								value={newApiKeyName}
								onChange={(event) => setNewApiKeyName(event.target.value)}
								placeholder="Key name"
							/>
							<Button type="submit" disabled={apiKeyLoading}>
								Create API key
							</Button>
						</form>
						{newApiKeyRawValue ? (
							<p className="rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900">
								New API key value (copy now, it may not be shown again):{" "}
								{newApiKeyRawValue}
							</p>
						) : null}
						<Table>
							<Table.Content aria-label="API keys">
								<Table.Header>
									<Table.Column id="name" key="name" isRowHeader>
										Name
									</Table.Column>
									<Table.Column id="prefix" key="prefix">
										Prefix
									</Table.Column>
									<Table.Column id="state" key="state">
										State
									</Table.Column>
									<Table.Column id="expires" key="expires">
										Expires
									</Table.Column>
									<Table.Column id="actions" key="actions">
										Actions
									</Table.Column>
								</Table.Header>
								<Table.Body items={apiKeyRows}>
									{(item) => (
										<Table.Row key={item.id} id={item.id}>
											<Table.Cell>{item.name}</Table.Cell>
											<Table.Cell>{item.prefix || "-"}</Table.Cell>
											<Table.Cell>
												{typeof item.enabled === "boolean"
													? item.enabled
														? "enabled"
														: "disabled"
													: "-"}
											</Table.Cell>
											<Table.Cell>{item.expiresAt || "-"}</Table.Cell>
											<Table.Cell>
												{item.id !== "empty" ? (
													<Button
														type="button"
														size="sm"
														variant="destructive"
														disabled={apiKeyLoading}
														onClick={() => void deleteApiKey(item.id)}
													>
														Delete
													</Button>
												) : (
													"-"
												)}
											</Table.Cell>
										</Table.Row>
									)}
								</Table.Body>
							</Table.Content>
						</Table>
					</section>

					<section className="grid gap-2 rounded-2xl border border-slate-200 bg-white p-5">
						<h3 className="text-sm font-semibold">Request history</h3>
						<Table>
							<Table.Content aria-label="Organization request history">
								<Table.Header>
									<Table.Column id="action" key="action" isRowHeader>
										Action
									</Table.Column>
									<Table.Column id="status" key="status">
										Status
									</Table.Column>
									<Table.Column id="detail" key="detail">
										Detail
									</Table.Column>
								</Table.Header>
								<Table.Body
									items={
										rows.length
											? rows
											: [
													{
														id: "empty",
														action: "-",
														status: "empty",
														detail: "No org requests yet",
													},
												]
									}
								>
									{(item) => (
										<Table.Row key={item.id} id={item.id}>
											<Table.Cell>{item.action}</Table.Cell>
											<Table.Cell>{item.status}</Table.Cell>
											<Table.Cell className="max-w-[920px] truncate">
												{item.detail}
											</Table.Cell>
										</Table.Row>
									)}
								</Table.Body>
							</Table.Content>
						</Table>
					</section>
				</CardContent>
			</Card>
		</main>
	);
}
