"use client";

import { useMemo, useState } from "react";
import { Pencil, Plus, Trash2 } from "lucide-react";
import { toast } from "sonner";

import type {
  PortalAccessGroupRow,
  PortalRouteCatalogApp,
} from "@/app/dashboard/admins/portal/_lib/portal-access-server-api";
import { PortalPermissionTree } from "@/components/admins/portal/portal-permission-tree";
import { ErrorBanner } from "@/components/shared/error-banner";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { isApiSuccess } from "@/lib/api-messages";
import { requestDashboardApi } from "@/lib/dashboard-api-client";

type PortalRolesPageClientProps = {
  customerId: number;
  initialGroups: PortalAccessGroupRow[];
  appCatalog: PortalRouteCatalogApp[];
  entitledRoutes: string[];
  initialErrorMessage: string | null;
};

type GroupFormState = {
  name: string;
  routes: string[];
};

export function PortalRolesPageClient({
  customerId,
  initialGroups,
  appCatalog,
  entitledRoutes,
  initialErrorMessage,
}: PortalRolesPageClientProps) {
  const [groups, setGroups] = useState(initialGroups);
  const [sheetOpen, setSheetOpen] = useState(false);
  const [editingGroup, setEditingGroup] = useState<PortalAccessGroupRow | null>(null);
  const [form, setForm] = useState<GroupFormState>({ name: "", routes: [] });
  const [saving, setSaving] = useState(false);

  const ceiling = useMemo(() => new Set(entitledRoutes), [entitledRoutes]);

  const filteredApps = useMemo(() => {
    if (ceiling.size === 0) return appCatalog;
    return appCatalog
      .map((app) => ({
        ...app,
        groups: app.groups
          .map((group) => ({
            ...group,
            routes: group.routes.filter((route) => ceiling.has(route.route)),
          }))
          .filter((group) => group.routes.length > 0),
      }))
      .filter((app) => app.groups.length > 0);
  }, [appCatalog, ceiling]);

  function openCreate() {
    setEditingGroup(null);
    setForm({ name: "", routes: [] });
    setSheetOpen(true);
  }

  function openEdit(group: PortalAccessGroupRow) {
    setEditingGroup(group);
    setForm({ name: group.name, routes: group.routes ?? [] });
    setSheetOpen(true);
  }

  async function handleSave() {
    if (!form.name.trim()) {
      toast.error("Role name is required.");
      return;
    }

    setSaving(true);
    try {
      const url = editingGroup
        ? "/dashboard/admins/portal/groups/update"
        : "/dashboard/admins/portal/groups/create";
      const data = await requestDashboardApi<{ status?: string; message?: string; data?: PortalAccessGroupRow }>({
        url,
        method: "POST",
        body: {
          customerId,
          groupId: editingGroup?.id,
          name: form.name.trim(),
          routes: form.routes,
        },
        fallbackError: "Could not save portal role.",
        validate: (payload) => isApiSuccess(payload),
      });

      toast.success(data.message ?? "Portal role saved.");
      setSheetOpen(false);
      setEditingGroup(null);

      if (editingGroup) {
        setGroups((current) =>
          current.map((item) =>
            item.id === editingGroup.id
              ? {
                  ...item,
                  name: form.name.trim(),
                  routes_count: form.routes.length,
                  routes: form.routes,
                }
              : item,
          ),
        );
      } else {
        setGroups((current) => [
          ...current,
          {
            id: Date.now(),
            name: form.name.trim(),
            slug: form.name.trim().toLowerCase().replace(/\s+/g, "-"),
            owned_by: null,
            users_count: 0,
            routes_count: form.routes.length,
            routes: form.routes,
          },
        ]);
      }
    } catch (error) {
      toast.error(error instanceof Error ? error.message : "Could not save portal role.");
    } finally {
      setSaving(false);
    }
  }

  async function handleDelete(group: PortalAccessGroupRow) {
    if (!window.confirm(`Delete role "${group.name}"?`)) return;

    try {
      await requestDashboardApi<{ status?: string; message?: string }>({
        url: "/dashboard/admins/portal/groups/delete",
        method: "POST",
        body: { customerId, groupId: group.id },
        fallbackError: "Could not delete portal role.",
        validate: (payload) => isApiSuccess(payload),
      });
      setGroups((current) => current.filter((item) => item.id !== group.id));
      toast.success("Portal role deleted.");
    } catch (error) {
      toast.error(error instanceof Error ? error.message : "Could not delete portal role.");
    }
  }

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

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between gap-3">
        <p className="text-muted-foreground text-sm">
          Create roles with View / Create / Update / Delete per module, within the customer entitlement ceiling.
        </p>
        <Button onClick={openCreate}>
          <Plus />
          New role
        </Button>
      </div>

      <div className="rounded-xl border">
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>Role</TableHead>
              <TableHead>Users</TableHead>
              <TableHead>Routes</TableHead>
              <TableHead className="text-right">Actions</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {groups.length === 0 ? (
              <TableRow>
                <TableCell colSpan={4} className="py-8 text-center text-muted-foreground">
                  No portal roles yet.
                </TableCell>
              </TableRow>
            ) : (
              groups.map((group) => (
                <TableRow key={group.id}>
                  <TableCell className="font-medium">{group.name}</TableCell>
                  <TableCell>{group.users_count}</TableCell>
                  <TableCell>
                    <Badge variant="secondary">{group.routes_count} routes</Badge>
                  </TableCell>
                  <TableCell className="text-right">
                    <div className="flex justify-end gap-2">
                      <Button size="sm" variant="outline" onClick={() => openEdit(group)} disabled={saving}>
                        <Pencil />
                        Edit
                      </Button>
                      <Button size="sm" variant="outline" onClick={() => void handleDelete(group)}>
                        <Trash2 />
                        Delete
                      </Button>
                    </div>
                  </TableCell>
                </TableRow>
              ))
            )}
          </TableBody>
        </Table>
      </div>

      <Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
        <SheetContent className="flex h-full !w-[min(860px,calc(100vw-1rem))] !max-w-none flex-col gap-0 overflow-hidden bg-muted/30 p-0">
          <SheetHeader className="shrink-0 border-b bg-card px-6 py-5 pr-14">
            <SheetTitle>{editingGroup ? "Edit portal role" : "Create portal role"}</SheetTitle>
            <SheetDescription>Routes must be within the customer entitlement ceiling.</SheetDescription>
          </SheetHeader>
          <div className="min-h-0 flex-1 space-y-4 overflow-y-auto px-6 py-6">
            <div className="space-y-2">
              <Label htmlFor="portal-role-name">Role name</Label>
              <Input
                id="portal-role-name"
                value={form.name}
                onChange={(event) => setForm((current) => ({ ...current, name: event.target.value }))}
              />
            </div>
            <PortalPermissionTree
              apps={filteredApps}
              selectedRoutes={form.routes}
              onSelectedRoutesChange={(routes) => setForm((current) => ({ ...current, routes }))}
              preferRolesGroupLabels
            />
          </div>
          <SheetFooter className="shrink-0 border-t bg-card px-6 py-4">
            <Button variant="outline" onClick={() => setSheetOpen(false)} disabled={saving}>
              Cancel
            </Button>
            <Button onClick={() => void handleSave()} disabled={saving}>
              {saving ? "Saving…" : "Save role"}
            </Button>
          </SheetFooter>
        </SheetContent>
      </Sheet>
    </div>
  );
}
