"use client";

import { useMemo, useState } from "react";
import { toast } from "sonner";

import type { PortalAppCatalog } from "@/app/dashboard/customers/_lib/portal-routes-server-api";
import { PortalPermissionTree } from "@/components/admins/portal/portal-permission-tree";
import { ErrorBanner } from "@/components/shared/error-banner";
import { Button } from "@/components/ui/button";
import { requestDashboardApi } from "@/lib/dashboard-api-client";
import { isApiSuccess } from "@/lib/api-messages";
import { useChanged } from "@/hooks/use-changed";

type PortalEntitlementsFormProps = {
  customerId: number;
  customerName?: string | null;
  apps: PortalAppCatalog[];
  initialRoutes: string[];
  hasConfiguredEntitlements: boolean;
  initialErrorMessage?: string | null;
};

export function PortalEntitlementsForm({
  customerId,
  apps,
  initialRoutes,
  hasConfiguredEntitlements,
  initialErrorMessage,
}: PortalEntitlementsFormProps) {
  const allRoutes = useMemo(
    () =>
      apps.flatMap((app) =>
        app.groups.flatMap((group) => group.routes.map((route) => route.route)),
      ),
    [apps],
  );

  const resolvedInitialRoutes = useMemo(() => {
    const visible = new Set(allRoutes);
    if (initialRoutes.length > 0) {
      return initialRoutes.filter((route) => visible.has(route));
    }
    if (!hasConfiguredEntitlements) {
      return allRoutes;
    }
    return [];
  }, [allRoutes, hasConfiguredEntitlements, initialRoutes]);

  const [selectedRoutes, setSelectedRoutes] = useState<string[]>(resolvedInitialRoutes);
  const [isSaving, setIsSaving] = useState(false);

  // Reset the selection when we switch customer or the server sends new routes.
  // Both hooks must run every render, so evaluate them before branching.
  const customerChanged = useChanged(customerId);
  const routesChanged = useChanged(resolvedInitialRoutes);
  if (customerChanged || routesChanged) {
    setSelectedRoutes(resolvedInitialRoutes);
  }

  async function handleSave() {
    setIsSaving(true);
    try {
      const data = await requestDashboardApi<{ status?: string; message?: string }>({
        url: "/dashboard/admins/portal/entitlements/submit",
        method: "POST",
        body: { customerId, routes: selectedRoutes },
        fallbackError: "Portal route entitlements could not be saved.",
        validate: (payload) => isApiSuccess(payload),
      });
      toast.success(data.message ?? "Portal route entitlements updated.");
    } catch (error) {
      toast.error(
        error instanceof Error ? error.message : "Portal route entitlements could not be saved.",
      );
    } finally {
      setIsSaving(false);
    }
  }

  if (initialErrorMessage) {
    return <ErrorBanner message={initialErrorMessage} />;
  }

  return (
    <div className="flex flex-col gap-3">
      <PortalPermissionTree
        apps={apps}
        selectedRoutes={selectedRoutes}
        onSelectedRoutesChange={setSelectedRoutes}
      />
      <div className="flex items-center justify-end gap-2 border-t pt-3">
        <Button type="button" size="sm" onClick={() => void handleSave()} disabled={isSaving}>
          {isSaving ? "Saving…" : "Save entitlements"}
        </Button>
      </div>
    </div>
  );
}
