"use client";

import { isApiSuccess } from "@/lib/api-messages";
import * as React from "react";

import { ArrowLeft, AppWindow, KeyRound, PackagePlus, Save } from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { toast } from "sonner";

import { ListPageCard } from "@/app/dashboard/_components";
import { PermissionPicker } from "@/components/admins/rbac/permission-picker";
import { ErrorBanner } from "@/components/shared/error-banner";
import type { PermissionCatalogEntry } from "@/components/admins/rbac/types";
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 { Textarea } from "@/components/ui/textarea";
import type { PermissionModule } from "@/config/rbac-permissions";
import { requestDashboardApi } from "@/lib/dashboard-api-client";
import type { RbacModule } from "../../_lib/app-modules-server-api";

type ModuleFormPageClientProps = {
  initialCatalog: PermissionCatalogEntry[];
  initialErrorMessage: string | null;
  initialModule?: RbacModule | null;
  initialModuleErrorMessage?: string | null;
  requestedModuleName?: string;
};

type ModuleFormState = {
  name: string;
  description: string;
};

type ModuleClientResponse = {
  status?: string;
  message?: string;
  module?: RbacModule;
};

const EMPTY_FORM: ModuleFormState = {
  name: "",
  description: "",
};

export function ModuleFormPageClient({
  initialCatalog,
  initialErrorMessage,
  initialModule = null,
  initialModuleErrorMessage = null,
  requestedModuleName,
}: ModuleFormPageClientProps) {
  const router = useRouter();
  const isEditMode = Boolean(requestedModuleName);
  const [form, setForm] = React.useState<ModuleFormState>(
    initialModule
      ? {
          name: initialModule.name,
          description: initialModule.description,
        }
      : EMPTY_FORM,
  );
  const [selectedPermissions, setSelectedPermissions] = React.useState<string[]>(
    initialModule?.permissions ?? [],
  );
  const [submitting, setSubmitting] = React.useState(false);

  const permissionModules = React.useMemo(
    () => buildPermissionModules(initialCatalog),
    [initialCatalog],
  );

  const selectedPermissionDetails = React.useMemo(() => {
    const byName = new Map(initialCatalog.map((permission) => [permission.name, permission]));
    return selectedPermissions
      .map((name) => byName.get(name))
      .filter((permission): permission is PermissionCatalogEntry => Boolean(permission));
  }, [initialCatalog, selectedPermissions]);

  const loadErrorMessage = initialErrorMessage ?? initialModuleErrorMessage;

  const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    if (!form.name.trim()) {
      toast.error("Module name is required.");
      return;
    }

    if (!selectedPermissions.length) {
      toast.error("Select at least one permission.");
      return;
    }

    setSubmitting(true);

    try {
      const data = await saveModule(isEditMode ? "update" : "create", {
        name: form.name,
        description: form.description,
        permissions: selectedPermissions,
      });

      toast.success(
        data.message ?? `Module "${form.name}" ${isEditMode ? "updated" : "created"}.`,
      );
      router.push("/dashboard/admins/access/app-modules");
    } catch (error) {
      const message =
        error instanceof Error
          ? error.message
          : isEditMode
            ? "Could not update module."
            : "Could not create module.";
      toast.error(message);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <ListPageCard
      icon={AppWindow}
      title={isEditMode ? "Update module" : "Create module"}
      description={
        isEditMode
          ? "Update a backend module and its assigned permissions."
          : "Create a backend module and assign permissions from the catalog."
      }
      breadcrumb={[
        { label: "Admins & Access", href: "/dashboard/admins/users" },
        { label: "App Modules", href: "/dashboard/admins/access/app-modules" },
        { label: isEditMode ? "Update" : "Create" },
      ]}
      actions={
        <Button type="button" variant="outline" size="sm" asChild>
          <Link href="/dashboard/admins/access/app-modules">
            <ArrowLeft className="size-4" />
            Back to modules
          </Link>
        </Button>
      }
    >
      <ErrorBanner message={loadErrorMessage} className="mb-4" />

      <form className="space-y-6" onSubmit={handleSubmit}>
        <div className="grid gap-6 xl:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)]">
          <section className="space-y-4">
            <div className="rounded-2xl border bg-card p-5 shadow-sm">
              <div className="mb-5 flex items-start gap-3">
                <div className="flex size-10 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary">
                  <PackagePlus className="size-5" />
                </div>
                <div>
                  <h3 className="font-semibold text-base">Module details</h3>
                  <p className="text-muted-foreground text-sm">
                    Enter the module fields returned by the backend.
                  </p>
                </div>
              </div>

              <div className="space-y-4">
                <div className="space-y-2">
                  <Label htmlFor="module-name">Module name</Label>
                  <Input
                    id="module-name"
                    value={form.name}
                    onChange={(event) =>
                      setForm((current) => ({ ...current, name: event.target.value }))
                    }
                    placeholder="Customers"
                  />
                </div>
                <div className="space-y-2">
                  <Label htmlFor="module-description">Module description</Label>
                  <Textarea
                    id="module-description"
                    value={form.description}
                    onChange={(event) =>
                      setForm((current) => ({ ...current, description: event.target.value }))
                    }
                    placeholder="Customer management module"
                    rows={5}
                  />
                </div>
              </div>
            </div>

            <div className="rounded-2xl border bg-card p-5 shadow-sm">
              <div className="mb-3 flex flex-wrap items-center justify-between gap-2">
                <div>
                  <p className="font-medium text-sm">Selected permissions</p>
                  <p className="text-muted-foreground text-xs">
                    These permissions will be attached to the module definition.
                  </p>
                </div>
                <Badge variant="secondary">{selectedPermissions.length} selected</Badge>
              </div>
              {selectedPermissionDetails.length ? (
                <div className="max-h-52 overflow-y-auto">
                  <div className="flex flex-wrap gap-2">
                    {selectedPermissionDetails.map((permission) => (
                      <Badge key={permission.name} variant="outline" className="font-mono">
                        {permission.name}
                      </Badge>
                    ))}
                  </div>
                </div>
              ) : (
                <p className="text-muted-foreground text-sm">No permissions selected yet.</p>
              )}
            </div>
          </section>

          <section className="space-y-4 rounded-2xl border bg-card p-5 shadow-sm">
            <div className="flex items-start gap-3">
              <div className="flex size-10 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary">
                <KeyRound className="size-5" />
              </div>
              <div>
                <h3 className="font-semibold text-base">Permission selector</h3>
                <p className="text-muted-foreground text-sm">
                  Search and select permissions from the RBAC catalog.
                </p>
              </div>
            </div>

            {permissionModules.length ? (
              <PermissionPicker
                modules={permissionModules}
                value={selectedPermissions}
                onChange={setSelectedPermissions}
                compact
              />
            ) : (
              <div className="rounded-xl border border-dashed p-8 text-center text-muted-foreground text-sm">
                No permissions are available to build modules.
              </div>
            )}
          </section>
        </div>

        <div className="sticky bottom-0 -mx-4 flex flex-col-reverse gap-2 border-t bg-background/95 px-4 py-4 backdrop-blur sm:flex-row sm:justify-end lg:-mx-6 lg:px-6">
          <Button type="button" variant="outline" asChild disabled={submitting}>
            <Link href="/dashboard/admins/access/app-modules">Cancel</Link>
          </Button>
          <Button type="submit" disabled={submitting || Boolean(loadErrorMessage)}>
            {isEditMode ? <Save className="size-4" /> : <PackagePlus className="size-4" />}
            {submitting
              ? isEditMode
                ? "Updating..."
                : "Creating..."
              : isEditMode
                ? "Update module"
                : "Create module"}
          </Button>
        </div>
      </form>
    </ListPageCard>
  );
}

async function saveModule(
  action: "create" | "update",
  payload: {
    name: string;
    description: string;
    permissions: string[];
  },
) {
  return requestDashboardApi<ModuleClientResponse>({
    url: `/dashboard/admins/access/app-modules/${action}`,
    method: "POST",
    body: {
      name: payload.name,
      description: payload.description,
      permissions: payload.permissions,
    },
    fallbackError: `Could not ${action} module.`,
    validate: (data) => isApiSuccess(data),
  });
}

function buildPermissionModules(catalog: PermissionCatalogEntry[]): PermissionModule[] {
  const modules = new Map<string, PermissionModule>();

  catalog.forEach((permission) => {
    const appKey = permission.appKey?.trim() || "backend";
    const appLabel = permission.appLabel?.trim() || "Backend";
    const moduleKey = permission.moduleKey || "uncategorized";
    const mapKey = `${appKey}:${moduleKey}`;

    if (!modules.has(mapKey)) {
      modules.set(mapKey, {
        key: mapKey,
        label: `${appLabel} / ${permission.moduleLabel || moduleKey}`,
        description: permission.moduleDescription || `Permissions for ${appLabel}`,
        permissions: [],
      });
    }

    modules.get(mapKey)?.permissions.push({
      name: permission.name,
      label: permission.label,
      description: permission.description,
      highRisk: Boolean(permission.highRisk),
      workflowTier: normalizeWorkflowTier(permission.workflowTier),
    });
  });

  return Array.from(modules.values()).sort((a, b) => a.label.localeCompare(b.label));
}

function normalizeWorkflowTier(value: PermissionCatalogEntry["workflowTier"]) {
  return value === "suggest" || value === "review" ? value : undefined;
}
