"use client";

import { Fragment } from "react";

import { Checkbox } from "@/components/ui/checkbox";
import {
  actionButtonsForRow,
  buildModuleRows,
  groupPortalAppsForDisplay,
  partitionPermissionItems,
  routesForModuleRow,
  type ModulePermissionRow,
  type PermissionCatalogRoute,
} from "@/lib/portal-permission-catalog";
import { cn } from "@/lib/utils";

export type PortalPermissionApp = {
  app: string;
  label: string;
  description: string;
  groups: Array<{
    label: string;
    routes: PermissionCatalogRoute[];
  }>;
};

type PortalPermissionTreeProps = {
  apps: PortalPermissionApp[];
  selectedRoutes: string[];
  onSelectedRoutesChange: (routes: string[]) => void;
  preferRolesGroupLabels?: boolean;
  readOnly?: boolean;
};

export function PortalPermissionTree({
  apps,
  selectedRoutes,
  onSelectedRoutesChange,
  preferRolesGroupLabels = false,
  readOnly = false,
}: PortalPermissionTreeProps) {
  const displayApps = groupPortalAppsForDisplay(apps);

  function toggleRoute(route: string, checked: boolean) {
    if (readOnly) return;
    onSelectedRoutesChange(
      checked
        ? [...new Set([...selectedRoutes, route])]
        : selectedRoutes.filter((value) => value !== route),
    );
  }

  function toggleRoutes(routes: string[], checked: boolean) {
    if (readOnly) return;
    onSelectedRoutesChange(
      checked
        ? [...new Set([...selectedRoutes, ...routes])]
        : selectedRoutes.filter((route) => !routes.includes(route)),
    );
  }

  function toggleApp(app: PortalPermissionApp, checked: boolean) {
    const appRoutes = app.groups.flatMap((group) => group.routes.map((route) => route.route));
    toggleRoutes(appRoutes, checked);
  }

  function isAppFullySelected(app: PortalPermissionApp) {
    const appRoutes = app.groups.flatMap((group) => group.routes.map((route) => route.route));
    return appRoutes.length > 0 && appRoutes.every((route) => selectedRoutes.includes(route));
  }

  function isRowFullySelected(row: ModulePermissionRow) {
    const routes = routesForModuleRow(row);
    return routes.length > 0 && routes.every((route) => selectedRoutes.includes(route));
  }

  function isNavGroupFullySelected(rows: ModulePermissionRow[]) {
    const routes = rows.flatMap((row) => routesForModuleRow(row));
    return routes.length > 0 && routes.every((route) => selectedRoutes.includes(route));
  }

  function renderModuleRow(row: ModulePermissionRow, options?: { fullWidth?: boolean }) {
    const actions = actionButtonsForRow(row);
    const hasGranular = actions.some((action) =>
      ["view", "create", "update", "delete"].includes(action.key),
    );
    const fullWidth = options?.fullWidth === true;

    if (!hasGranular || actions.length <= 1) {
      return actions.map((action) => {
        const checked = selectedRoutes.includes(action.route.route);
        return (
          <label
            key={action.route.route}
            className={cn(
              "flex min-w-0 items-start gap-2 rounded-md border border-transparent px-2 py-1.5 text-sm hover:border-border hover:bg-card",
              fullWidth && "sm:col-span-2",
              readOnly && "pointer-events-none opacity-80",
            )}
          >
            <Checkbox
              className="mt-0.5"
              checked={checked}
              disabled={readOnly}
              onCheckedChange={(value) => toggleRoute(action.route.route, value === true)}
            />
            <span className="min-w-0 leading-snug">
              <span className="font-medium">{row.label}</span>
              {row.description || action.route.description ? (
                <span className="mt-0.5 block text-[11px] text-muted-foreground">
                  {row.description || action.route.description}
                </span>
              ) : null}
            </span>
          </label>
        );
      });
    }

    return (
      <div
        key={row.key}
        className={cn("rounded-md border bg-card px-2.5 py-2", fullWidth && "sm:col-span-2")}
      >
        <label className={cn("flex items-start gap-2 text-sm", readOnly && "pointer-events-none")}>
          <Checkbox
            className="mt-0.5"
            checked={isRowFullySelected(row)}
            disabled={readOnly}
            onCheckedChange={(value) => toggleRoutes(routesForModuleRow(row), value === true)}
          />
          <span className="min-w-0 leading-snug">
            <span className="font-medium">{row.label}</span>
            {row.description ? (
              <span className="mt-0.5 block text-[11px] text-muted-foreground">{row.description}</span>
            ) : null}
          </span>
        </label>
        <div
          className={cn(
            "mt-1.5 grid gap-x-3 gap-y-1.5 pl-6",
            fullWidth ? "grid-cols-2 sm:grid-cols-3 lg:grid-cols-4" : "grid-cols-2 sm:grid-cols-4",
          )}
        >
          {actions.map((action) => {
            const checked = selectedRoutes.includes(action.route.route);
            return (
              <label
                key={action.route.route}
                className={cn(
                  "inline-flex min-w-0 items-center gap-1.5 text-xs font-medium",
                  readOnly && "pointer-events-none",
                )}
              >
                <Checkbox
                  checked={checked}
                  disabled={readOnly}
                  onCheckedChange={(value) => toggleRoute(action.route.route, value === true)}
                />
                <span className={fullWidth ? "leading-snug" : "truncate"}>{action.label}</span>
              </label>
            );
          })}
        </div>
      </div>
    );
  }

  return (
    <div className="space-y-3 rounded-xl border bg-card p-3 sm:p-4">
      {displayApps.map((app, appIndex) => {
        const merged = {
          label: "Permissions",
          routes: app.groups.flatMap((group) => group.routes) as PermissionCatalogRoute[],
        };
        const moduleRows = buildModuleRows(merged, preferRolesGroupLabels);
        const permissionItems = partitionPermissionItems(moduleRows);

        return (
          <Fragment key={app.app}>
            {appIndex > 0 ? <div className="border-t" /> : null}
            <div className="space-y-2">
              <div className="flex items-start gap-2.5">
                <Checkbox
                  className="mt-0.5"
                  checked={isAppFullySelected(app)}
                  disabled={readOnly}
                  onCheckedChange={(value) => toggleApp(app, value === true)}
                />
                <div className="min-w-0">
                  <p className="font-medium leading-none">{app.label}</p>
                  {app.description ? (
                    <p className="mt-1 text-xs text-muted-foreground">{app.description}</p>
                  ) : null}
                </div>
              </div>

              <div className="rounded-lg border bg-muted/20 p-2 sm:ml-6 sm:p-2.5">
                <div className="grid grid-cols-1 gap-1.5 sm:grid-cols-2">
                  {permissionItems.map((item) => {
                    if (item.type === "nav_group") {
                      return (
                        <div
                          key={`nav-group-${item.key}`}
                          className="space-y-1.5 rounded-md border bg-card px-2.5 py-2 sm:col-span-2"
                        >
                          <label
                            className={cn(
                              "flex items-start gap-2 text-sm",
                              readOnly && "pointer-events-none",
                            )}
                          >
                            <Checkbox
                              className="mt-0.5"
                              checked={isNavGroupFullySelected(item.rows)}
                              disabled={readOnly}
                              onCheckedChange={(value) =>
                                toggleRoutes(
                                  item.rows.flatMap((row) => routesForModuleRow(row)),
                                  value === true,
                                )
                              }
                            />
                            <span>
                              <span className="font-medium">{item.label}</span>
                              <span className="block text-[11px] text-muted-foreground">
                                Modules nested under this group
                              </span>
                            </span>
                          </label>
                          <div className="grid grid-cols-1 gap-1.5 pl-6 sm:grid-cols-2">
                            {item.rows.map((row) => (
                              <Fragment key={row.key}>{renderModuleRow(row)}</Fragment>
                            ))}
                          </div>
                        </div>
                      );
                    }

                    return (
                      <Fragment key={item.row.key}>
                        {renderModuleRow(item.row, {
                          fullWidth: item.row.key === "order_blotter",
                        })}
                      </Fragment>
                    );
                  })}
                </div>
              </div>
            </div>
          </Fragment>
        );
      })}
    </div>
  );
}
