import { zodResolver } from "@hookform/resolvers/zod";
import { Button, Field, Form, useNavigate } from "@tailor-platform/app-shell";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { useMutation, useQuery } from "urql";
import { z } from "zod";
import { graphql } from "@/graphql";
import { useToast } from "@/hooks/use-toast";

const AvailablePermissionsQuery = graphql(`
  query AvailablePermissionsForCreateRole {
    availablePermissions {
      scopes {
        scope
        autoAssigned
      }
    }
  }
`);

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

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 [{ data: permissionsData }] = useQuery({ query: AvailablePermissionsQuery });
  const [selectedScopes, setSelectedScopes] = useState<Set<string>>(() => new Set());
  const [submitting, setSubmitting] = useState(false);

  const allScopes = permissionsData?.availablePermissions.scopes ?? [];
  const selectableScopes = allScopes.filter((s) => !s.autoAssigned);

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

  const toggleScope = (scope: string) => {
    setSelectedScopes((prev) => {
      const next = new Set(prev);
      if (next.has(scope)) next.delete(scope);
      else next.add(scope);
      return next;
    });
  };

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

    const permissions = [...selectedScopes];

    setSubmitting(true);
    const result = await createRole({ ...values, permissions }, { additionalTypenames: ["Role"] });
    setSubmitting(false);

    if (result.error) {
      toast.error(result.error);
      return;
    }

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

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

  return (
    <Form
      noValidate
      onSubmit={(e) => void form.handleSubmit(onSubmit)(e)}
      className="max-w-md space-y-4"
    >
      <Controller
        control={form.control}
        name="name"
        render={({ field, fieldState }) => (
          <Field.Root name={field.name} invalid={fieldState.invalid}>
            <Field.Label>Name</Field.Label>
            <Field.Control placeholder="Enter role name" {...field} />
            {fieldState.error && <Field.Error match>{fieldState.error.message}</Field.Error>}
          </Field.Root>
        )}
      />
      <Controller
        control={form.control}
        name="description"
        render={({ field, fieldState }) => (
          <Field.Root name={field.name} invalid={fieldState.invalid}>
            <Field.Label>Description</Field.Label>
            <Field.Control placeholder="Enter description" {...field} />
            {fieldState.error && <Field.Error match>{fieldState.error.message}</Field.Error>}
          </Field.Root>
        )}
      />
      <div className="space-y-2">
        <span className="text-sm font-medium leading-none">Permissions</span>
        <div className="rounded-md border p-3">
          {selectableScopes.length === 0 ? (
            <p className="text-muted-foreground text-sm">Loading permissions...</p>
          ) : (
            <div className="space-y-3">
              {selectableScopes.map((scope) => (
                <label key={scope.scope} className="flex items-start gap-2 cursor-pointer">
                  <input
                    type="checkbox"
                    checked={selectedScopes.has(scope.scope)}
                    onChange={() => toggleScope(scope.scope)}
                    className="mt-1 rounded border"
                  />
                  <div>
                    <div className="text-sm font-medium">{scope.scope}</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>
  );
};
