"use client";

import * as React from "react";

import { useRouter } from "next/navigation";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";

import { FormPageHeader, FormSaveBar } from "@/app/dashboard/_components/form";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";

import { PermissionPicker } from "./permission-picker";
import { roleFormDefaults, roleSchema, type RoleFormValues } from "./schemas/rbac.schema";
import type { RbacModule, Role } from "./types";

type Props = {
  mode: "create" | "edit";
  initialRole?: Role;
  onSubmit: (values: RoleFormValues) => Promise<void>;
  isTemplate?: boolean;
  availableModules?: RbacModule[];
  modulesErrorMessage?: string | null;
};

export function RoleForm({
  mode,
  initialRole,
  onSubmit,
  isTemplate = false,
  availableModules,
  modulesErrorMessage = null,
}: Props) {
  const router = useRouter();
  const [submitting, setSubmitting] = React.useState(false);

  const form = useForm<RoleFormValues>({
    resolver: zodResolver(roleSchema),
    defaultValues: initialRole
      ? {
          name: initialRole.name,
          description: initialRole.description,
          permissions: initialRole.permissions,
          modules: buildInitialSelectedModules(initialRole, availableModules),
        }
      : roleFormDefaults,
  });

  const permissions = form.watch("permissions");
  const selectedModules = form.watch("modules");
  const useModuleSelection = Boolean(availableModules);

  const selectedModuleNames = React.useMemo(
    () => new Set((selectedModules ?? []).map((module) => module.name)),
    [selectedModules],
  );

  const setSelectedModule = (module: RbacModule, checked: boolean) => {
    const currentModules = form.getValues("modules") ?? [];
    const nextModules = checked
      ? [
          ...currentModules.filter((item) => item.name !== module.name),
          { name: module.name, permissions: module.permissions },
        ]
      : currentModules.filter((item) => item.name !== module.name);
    const nextPermissions = [...new Set(nextModules.flatMap((item) => item.permissions))];

    form.setValue("modules", nextModules, { shouldDirty: true, shouldValidate: true });
    form.setValue("permissions", nextPermissions, { shouldDirty: true, shouldValidate: true });
  };

  const handleSubmit = form.handleSubmit(async (values) => {
    setSubmitting(true);
    try {
      await onSubmit(values);
      router.push("/dashboard/admins/access/roles");
    } finally {
      setSubmitting(false);
    }
  });

  return (
    <form onSubmit={handleSubmit} className="space-y-6">
      <FormPageHeader
        title={mode === "create" ? "Create role" : `Edit role: ${initialRole?.name ?? ""}`}
        description="Define a role and assign granular permissions by module."
      />

      <div className="grid gap-4 md:grid-cols-2">
        <div className="space-y-2">
          <Label htmlFor="role-name">Role name</Label>
          <Input
            id="role-name"
            {...form.register("name")}
            disabled={isTemplate}
            placeholder="finance_team"
            className="font-mono"
          />
          {form.formState.errors.name ? (
            <p className="text-destructive text-xs">{form.formState.errors.name.message}</p>
          ) : null}
        </div>
        <div className="space-y-2 md:col-span-2">
          <Label htmlFor="role-description">Description</Label>
          <Textarea
            id="role-description"
            {...form.register("description")}
            rows={2}
            placeholder="Describe what this role is for…"
          />
        </div>
      </div>

      {initialRole ? (
        <p className="text-muted-foreground text-sm">
          Assigned to {initialRole.assignedStaffCount} staff and {initialRole.assignedCustomerCount} customers
        </p>
      ) : null}

      {useModuleSelection ? (
        <div className="space-y-3">
          <div>
            <Label>Modules</Label>
            <p className="mt-1 text-muted-foreground text-sm">
              Select modules from the database. The role permissions are built from selected modules.
            </p>
          </div>
          {modulesErrorMessage ? (
            <div className="rounded-xl border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-amber-700 text-sm dark:text-amber-300">
              {modulesErrorMessage}
            </div>
          ) : null}
          {availableModules?.length ? (
            <div className="grid gap-3 md:grid-cols-2">
              {availableModules.map((module) => {
                const checked = selectedModuleNames.has(module.name);

                return (
                  <label
                    key={module.name}
                    className="flex cursor-pointer gap-3 rounded-2xl border bg-card p-4 shadow-xs transition-colors hover:bg-muted/40"
                  >
                    <Checkbox
                      checked={checked}
                      onCheckedChange={(value) => setSelectedModule(module, value === true)}
                      className="mt-1"
                    />
                    <div className="min-w-0 flex-1">
                      <div className="flex flex-wrap items-center gap-2">
                        <span className="font-medium text-sm">{module.name}</span>
                        <Badge variant="secondary">
                          {module.permissionCount || module.permissions.length} permissions
                        </Badge>
                      </div>
                      {module.description ? (
                        <p className="mt-1 text-muted-foreground text-sm">{module.description}</p>
                      ) : null}
                      <div className="mt-3 flex flex-wrap gap-2">
                        {module.permissions.map((permission) => (
                          <Badge key={permission} variant="outline" className="font-mono">
                            {permission}
                          </Badge>
                        ))}
                      </div>
                    </div>
                  </label>
                );
              })}
            </div>
          ) : (
            <div className="rounded-xl border border-dashed p-6 text-center text-muted-foreground text-sm">
              No modules are available.
            </div>
          )}
          {form.formState.errors.permissions ? (
            <p className="text-destructive text-xs">{form.formState.errors.permissions.message}</p>
          ) : null}
        </div>
      ) : (
        <div className="space-y-2">
          <Label>Permissions</Label>
          <PermissionPicker
            value={permissions}
            onChange={(next) => form.setValue("permissions", next, { shouldValidate: true })}
            readOnly={false}
          />
          {form.formState.errors.permissions ? (
            <p className="text-destructive text-xs">{form.formState.errors.permissions.message}</p>
          ) : null}
        </div>
      )}

      <FormSaveBar
        isSaving={submitting}
        cancelHref="/dashboard/admins/access/roles"
      />
    </form>
  );
}

function buildInitialSelectedModules(
  role: Role,
  availableModules?: RbacModule[],
): RoleFormValues["modules"] {
  if (!availableModules?.length) return undefined;

  const roleModuleNames = new Set(role.modules ?? []);
  const rolePermissions = new Set(role.permissions);

  return availableModules
    .filter((module) => {
      if (roleModuleNames.has(module.name)) return true;
      return module.permissions.some((permission) => rolePermissions.has(permission));
    })
    .map((module) => ({
      name: module.name,
      permissions: module.permissions.filter((permission) => rolePermissions.has(permission)),
    }))
    .filter((module) => module.permissions.length > 0);
}
