import { useState } from "react";
import { Button, Input, useNavigate } from "@tailor-platform/app-shell";
import { useMutation, useQuery } from "urql";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { graphql } from "@/graphql";
import { useToast } from "@/hooks/use-toast";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import { Label } from "@/components/ui/label";
import { groupPermissions, isAutoAssigned, type PermissionGroup } from "@/lib/permission-groups";

const PermissionsForCreateQuery = graphql(`
  query PermissionsForCreateRole {
    permissions {
      edges {
        node {
          id
          key
          description
        }
      }
    }
  }
`);

const CreateRoleMutation = graphql(`
  mutation CreateRole($name: String!, $description: String) {
    createRole(name: $name, description: $description) {
      id
      name
      description
    }
  }
`);

const AssignPermissionMutation = graphql(`
  mutation AssignPermissionOnCreate($roleId: String!, $permissionId: String!) {
    assignPermissionToRole(roleId: $roleId, permissionId: $permissionId) {
      roleId
      permissionId
    }
  }
`);

const formSchema = z.object({
  name: z.string().min(1, "Name is required"),
  description: z.string().optional(),
});

type FormValues = z.infer<typeof formSchema>;

export const CreateRoleForm = () => {
  const navigate = useNavigate();
  const toast = useToast();
  const [, createRole] = useMutation(CreateRoleMutation);
  const [, assignPermission] = useMutation(AssignPermissionMutation);
  const [{ data: permissionsData }] = useQuery({ query: PermissionsForCreateQuery });
  const [selectedPermissions, setSelectedPermissions] = useState<Set<string>>(() => new Set());
  const [submitting, setSubmitting] = useState(false);

  const allPermissions = permissionsData?.permissions.edges.map((edge) => edge.node) ?? [];
  const permissionGroups = groupPermissions(allPermissions);

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      name: "",
      description: "",
    },
  });

  const isGroupSelected = (group: PermissionGroup) =>
    group.permissions.every((p) => selectedPermissions.has(p.id));

  const toggleGroup = (group: PermissionGroup) => {
    setSelectedPermissions((prev) => {
      const next = new Set(prev);
      const allSelected = group.permissions.every((p) => next.has(p.id));
      for (const p of group.permissions) {
        if (allSelected) next.delete(p.id);
        else next.add(p.id);
      }
      return next;
    });
  };

  const onSubmit = async (values: FormValues) => {
    if (selectedPermissions.size === 0) {
      toast.error("At least one permission must be selected");
      return;
    }

    setSubmitting(true);
    const createResult = await createRole(values, { additionalTypenames: ["Role"] });
    if (createResult.error) {
      toast.error(createResult.error);
      setSubmitting(false);
      return;
    }

    const roleId = createResult.data?.createRole?.id;
    if (!roleId) {
      setSubmitting(false);
      return;
    }

    // Include user-selected + auto-assigned permissions
    const autoAssignedIds = allPermissions.filter(isAutoAssigned).map((p) => p.id);
    const allPermissionIds = [...selectedPermissions, ...autoAssignedIds];
    for (const permissionId of allPermissionIds) {
      const assignResult = await assignPermission(
        { roleId, permissionId },
        { additionalTypenames: ["RolePermission"] },
      );
      if (assignResult.error) {
        toast.error(assignResult.error);
        setSubmitting(false);
        return;
      }
    }

    setSubmitting(false);
    toast.success("Role created successfully");
    void navigate("..");
  };

  const onCancel = () => {
    void navigate("..");
  };

  return (
    <Form {...form}>
      <form onSubmit={(e) => void form.handleSubmit(onSubmit)(e)} className="max-w-md space-y-4">
        <FormField
          control={form.control}
          name="name"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Name</FormLabel>
              <FormControl>
                <Input placeholder="Enter role name" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="description"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Description</FormLabel>
              <FormControl>
                <Input placeholder="Enter description" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <div className="space-y-2">
          <Label>Permissions</Label>
          <div className="rounded-md border p-3">
            {permissionGroups.length === 0 ? (
              <p className="text-muted-foreground text-sm">Loading permissions...</p>
            ) : (
              <div className="space-y-3">
                {permissionGroups.map((group) => (
                  <label key={group.label} className="flex items-start gap-2 cursor-pointer">
                    <input
                      type="checkbox"
                      checked={isGroupSelected(group)}
                      onChange={() => toggleGroup(group)}
                      className="mt-1 rounded border"
                    />
                    <div>
                      <div className="text-sm font-medium">{group.label}</div>
                      <div className="text-xs text-muted-foreground">{group.description}</div>
                    </div>
                  </label>
                ))}
              </div>
            )}
          </div>
        </div>
        <div className="flex gap-2">
          <Button type="submit" disabled={submitting}>
            {submitting ? "Creating..." : "Create"}
          </Button>
          <Button type="button" variant="outline" onClick={onCancel}>
            Cancel
          </Button>
        </div>
      </form>
    </Form>
  );
};
