"use client";

import { useMemo } from "react";

import { Checkbox } from "@/components/ui/checkbox";
import { AdminNoResourceState, AdminTableNoResourceRow } from "@/components/admin/admin-no-resource-state";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";
import { ADMIN_PERMISSION_PACKAGES } from "@/lib/admin-permission-packages";
import type { AdminPermissionCatalogData } from "@/types/api/admin-user";

type PackageSelectorProps = {
  catalog: AdminPermissionCatalogData | null;
  selectedSlugs: string[];
  onChange: (next: string[]) => void;
  resolveGroupLabel: (key: string, fallback: string) => string;
  resolvePackageLabel: (key: string, fallback: string) => string;
  selectableSlugs?: string[] | null;
  helperText?: string;
  summaryText?: string;
  emptyText: string;
  heightClassName?: string;
};

type RenderGroup = {
  key: string;
  label: string;
  packages: Array<{ key: string; label: string; slugs: string[] }>;
};

const PACKAGE_LEVEL_ORDER: Record<string, number> = {
  view: 10,
  node_view: 10,
  role_view: 11,
  user_view: 12,
  review: 20,
  export: 20,
  manage: 30,
  node_manage: 30,
  role_manage: 31,
  user_manage: 32,
  config: 30,
  control: 30,
  reopen: 32,
  special: 40,
};

export function AdminPermissionPackageSelector({
  catalog,
  selectedSlugs,
  onChange,
  resolveGroupLabel,
  resolvePackageLabel,
  selectableSlugs = null,
  helperText,
  summaryText,
  emptyText,
  heightClassName = "h-[52vh]",
}: PackageSelectorProps): React.ReactElement {
  const selectedSet = useMemo(() => new Set(selectedSlugs), [selectedSlugs]);
  const catalogSlugSet = useMemo(
    () => new Set((catalog?.permissions ?? []).map((permission) => permission.slug)),
    [catalog],
  );
  const allowedSet = useMemo(
    () => (selectableSlugs ? new Set(selectableSlugs) : null),
    [selectableSlugs],
  );

  const groups = useMemo<RenderGroup[]>(() => {
    const defs = catalog?.permission_menu_groups ?? [];
    const out: RenderGroup[] = [];
    for (const group of defs) {
      const bundles = ADMIN_PERMISSION_PACKAGES[group.key] ?? [];
      if (bundles.length === 0) {
        continue;
      }
      const renderedPackages = bundles
        .map((bundle) => {
          const slugs = bundle.slugs.filter((slug) => {
            if (!catalogSlugSet.has(slug)) {
              return false;
            }
            if (allowedSet && !allowedSet.has(slug)) {
              return false;
            }
            return true;
          });
          return {
            key: bundle.key,
            label: resolvePackageLabel(bundle.key, bundle.label),
            slugs,
          };
        })
        .filter((bundle) => bundle.slugs.length > 0);
      if (renderedPackages.length === 0) {
        continue;
      }
      out.push({
        key: group.key,
        label: resolveGroupLabel(group.key, group.label),
        packages: renderedPackages,
      });
    }
    return out;
  }, [allowedSet, catalog, catalogSlugSet, resolveGroupLabel, resolvePackageLabel]);

  const bundleCount = useMemo(
    () => groups.reduce((sum, group) => sum + group.packages.length, 0),
    [groups],
  );

  if (groups.length === 0 || bundleCount === 0) {
    return (
      <div className="rounded-xl border border-dashed p-4">
        <AdminNoResourceState compact className="py-4" />
      </div>
    );
  }

  const toggleBundle = (group: RenderGroup, bundleKey: string, slugs: string[], checked: boolean) => {
    const next = new Set(selectedSet);
    const currentLevel = PACKAGE_LEVEL_ORDER[bundleKey] ?? 10;

    if (checked) {
      const implied = group.packages
        .filter((item) => (PACKAGE_LEVEL_ORDER[item.key] ?? 10) <= currentLevel)
        .flatMap((item) => item.slugs);
      for (const slug of implied.length > 0 ? implied : slugs) {
        next.add(slug);
      }
      for (const item of group.packages) {
        if ((PACKAGE_LEVEL_ORDER[item.key] ?? 10) > currentLevel) {
          for (const slug of item.slugs) {
            next.delete(slug);
          }
        }
      }
    } else {
      for (const slug of slugs) {
        next.delete(slug);
      }
      if (bundleKey === "manage" || bundleKey === "reopen") {
        for (const item of group.packages) {
          if ((PACKAGE_LEVEL_ORDER[item.key] ?? 10) > currentLevel) {
            for (const slug of item.slugs) {
              next.delete(slug);
            }
          }
        }
      }
    }

    onChange(Array.from(next).sort());
  };

  const toggleGroup = (group: RenderGroup, checked: boolean) => {
    const next = new Set(selectedSet);
    if (checked) {
      const viewBundle =
        group.packages.find((item) => item.key === "view") ?? group.packages[0];
      for (const slug of viewBundle?.slugs ?? []) {
        next.add(slug);
      }
    } else {
      for (const slug of group.packages.flatMap((item) => item.slugs)) {
        next.delete(slug);
      }
    }
    onChange(Array.from(next).sort());
  };

  return (
    <div className="space-y-3">
      {helperText || summaryText ? (
        <div className="flex flex-wrap items-center justify-between gap-2 rounded-xl border bg-muted/20 px-3 py-2 text-xs text-muted-foreground">
          <span>{helperText}</span>
          <span>{summaryText}</span>
        </div>
      ) : null}
      <div className={cn("relative w-full overflow-auto rounded-xl border border-border/60 bg-card", heightClassName)}>
        <table className="w-full min-w-full border-collapse text-sm">
          <thead className="sticky top-0 z-10 bg-muted/80 backdrop-blur-md border-b border-border/50">
            <tr>
              <th style={{ textAlign: "left" }} className="w-[180px] h-11 px-4 font-semibold text-foreground">模块</th>
              <th style={{ textAlign: "left" }} className="h-11 px-4 font-semibold text-foreground">具体权限</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-border/50">
            {groups.map((group) => {
              const groupAllSlugs = group.packages.flatMap((p) => p.slugs);
              const groupSelectedCount = groupAllSlugs.filter((slug) => selectedSet.has(slug)).length;
              const groupChecked = groupSelectedCount === groupAllSlugs.length && groupAllSlugs.length > 0;

              return (
                <tr key={group.key} className="hover:bg-muted/10 transition-colors">
                  <td style={{ textAlign: "left" }} className="align-top py-4 pl-4">
                    <label 
                      style={{ display: "flex", justifyContent: "flex-start" }}
                      className="cursor-pointer items-center gap-2 font-medium w-full"
                    >
                      <Checkbox
                        checked={groupChecked}
                        onCheckedChange={(value) =>
                          toggleGroup(group, value === true)
                        }
                      />
                      <span>{group.label}</span>
                    </label>
                  </td>
                  <td style={{ textAlign: "left" }} className="py-4 pl-4">
                    <div 
                      style={{ display: "flex", justifyContent: "flex-start" }}
                      className="flex-wrap gap-3 w-full"
                    >
                      {group.packages.map((bundle) => {
                        const checked = bundle.slugs.every((slug) => selectedSet.has(slug));
                        return (
                          <label
                            key={`${group.key}.${bundle.key}`}
                            className={cn(
                              "flex cursor-pointer items-center gap-2 rounded-md border px-3 py-1.5 text-sm transition-colors hover:bg-muted/50",
                              checked && "border-primary/40 bg-primary/5",
                            )}
                          >
                            <Checkbox
                              checked={checked}
                              onCheckedChange={(value) =>
                                toggleBundle(group, bundle.key, bundle.slugs, value === true)
                              }
                            />
                            <span>{bundle.label}</span>
                          </label>
                        );
                      })}
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}
