"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 { FRONTEND_ROUTES } from "@/config/frontend-routes";
import { submitDashboardForm } from "@/lib/dashboard-mutations.client";
import { useChanged } from "@/hooks/use-changed";

type CustomerPortalRoutesFormProps = {
  customerId: number;
  customerName?: string | null;
  apps: PortalAppCatalog[];
  initialRoutes: string[];
  hasConfiguredEntitlements: boolean;
  preferRolesGroupLabels?: boolean;
  initialErrorMessage?: string | null;
  onSuccess?: () => void;
};

export function CustomerPortalRoutesForm({
  customerId,
  apps,
  initialRoutes,
  hasConfiguredEntitlements,
  preferRolesGroupLabels = false,
  initialErrorMessage,
  onSuccess,
}: CustomerPortalRoutesFormProps) {
  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 message = await submitDashboardForm({
        mode: "update",
        id: customerId,
        values: { routes: selectedRoutes },
        createUrl: FRONTEND_ROUTES.customers.portalRoutesSubmit,
        updateUrl: FRONTEND_ROUTES.customers.portalRoutesSubmit,
        messages: {
          createFail: "Portal route entitlements could not be saved.",
          updateFail: "Portal route entitlements could not be saved.",
          createSuccess: "Portal route entitlements updated.",
          updateSuccess: "Portal route entitlements updated.",
        },
      });
      toast.success(message);
      onSuccess?.();
    } 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}
        preferRolesGroupLabels={preferRolesGroupLabels}
      />
      <div className="flex items-center justify-end gap-2 border-t pt-3">
        <Button type="button" variant="outline" size="sm" onClick={() => onSuccess?.()} disabled={isSaving}>
          Cancel
        </Button>
        <Button type="button" size="sm" onClick={() => void handleSave()} disabled={isSaving}>
          Save entitlements
        </Button>
      </div>
    </div>
  );
}
