import { useCoreFetcher } from "@/lib/features/useCoreFetcher";
import type {
  AdminFeature,
  AdminRoleDetailed,
} from "@/lib/features/users/roles/types";
import {
  Button,
  Checkbox,
  Flex,
  Grid,
  Group,
  Stack,
  Table,
  Text,
  Textarea,
  TextInput,
  Title,
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { zod4Resolver } from "mantine-form-zod-resolver";
import { toast } from "sonner";
import z from "zod";

const privilegeSchema = z.object({
  featureId: z.string().min(1, "Missing Feature"),
  create: z.boolean(),
  read: z.boolean(),
  update: z.boolean(),
  delete: z.boolean(),
});

const schema = z.object({
  name: z.string().min(2, { error: "Role Name is required" }),
  description: z.string().min(2, { error: "Description is required" }),
  privileges: z.array(privilegeSchema),
  //   privileges: z
  //     .array(
  //       z.object({
  //         featureId: z.string().min(1, "Missing Feature"),
  //         create: z.boolean(),
  //         read: z.boolean(),
  //         update: z.boolean(),
  //         delete: z.boolean(),
  //       }),
  //     )
  //     .optional(),
});

type SchemaType = z.infer<typeof schema>;
type PrivilegeKey = "create" | "read" | "update" | "delete";

const PRIVILEGE_KEYS: PrivilegeKey[] = ["create", "read", "update", "delete"];

// Features that only support a subset of privileges (the rest are meaningless
// and disabled in the UI). Dashboard is view-only; Campaign Reports is
// view (read) + export (update).
const FEATURE_PRIVILEGES: Record<string, PrivilegeKey[]> = {
  dashboard: ["read"],
  "campaign-reports": ["read", "update"],
};

const allowedPrivileges = (slug?: string): PrivilegeKey[] =>
  FEATURE_PRIVILEGES[slug ?? ""] ?? PRIVILEGE_KEYS;

const RoleForm: React.FC<{
  adminRole?: AdminRoleDetailed;
  adminFeatures: AdminFeature[];
}> = ({ adminRole, adminFeatures }) => {
  const form = useForm<SchemaType>({
    initialValues: {
      name: adminRole?.name ?? "",
      description: adminRole?.description ?? "",
      privileges: adminFeatures.map((feature) => {
        const existing = adminRole?.privileges?.find(
          (p) => p.console_feature_id === feature.id,
        );
        return {
          featureId: feature.id,
          create: existing?.create ?? false,
          read: existing?.read ?? false,
          update: existing?.update ?? false,
          delete: existing?.delete ?? false,
        };
      }),
    },
    validate: zod4Resolver(schema),
  });

  const { trigger: createTrigger, isLoading: createLoading } = useCoreFetcher(
    "create-admin-role",
    "post",
    {
      onSuccess: () => {
        toast.success("Role created successfully");
        form.reset();
      },
      onError: (error) => {
        toast.error((error as Error)?.message ?? "Failed to create role");
      },
    },
  );
  const { trigger: updateTrigger, isLoading: updateLoading } = useCoreFetcher(
    "update-admin-role",
    "put",
    {
      onSuccess: () => {
        toast.success("Role updated successfully");
      },
      onError: (error) => {
        toast.error((error as Error)?.message ?? "Failed to updated role");
      },
    },
  );

  const handleSubmit = async () => {
    const result = form.validate();
    if (!result.hasErrors) {
      const parsed = schema.safeParse(form.values);
      if (parsed.success) {
        if (adminRole?.id) {
          await updateTrigger(parsed.data);
        } else {
          await createTrigger(parsed.data);
        }
      }
    }
  };

  // Checks if all privileges for every feature are enabled. Features with a
  // restricted privilege set count as "fully selected" once those are on.
  const isAllSelected = form.values.privileges.every((p, index) =>
    allowedPrivileges(adminFeatures[index]?.slug).every((key) => p[key]),
  );

  const handleSelectAll = () => {
    const newValue = !isAllSelected;
    form.setFieldValue(
      "privileges",
      form.values.privileges.map((p, index) => {
        const slug = adminFeatures[index]?.slug;
        const allowed = allowedPrivileges(slug);
        const restricted = Boolean(FEATURE_PRIVILEGES[slug ?? ""]);
        const set = (key: PrivilegeKey) =>
          allowed.includes(key) ? newValue : false;
        return {
          ...p,
          create: set("create"),
          read: set("read"),
          update: set("update"),
          delete: set("delete"),
          publish: restricted ? false : newValue,
        };
      }),
    );
  };

  const handlePrivilegeChange = (
    index: number,
    key: PrivilegeKey,
    checked: boolean,
  ) => {
    form.setFieldValue(`privileges.${index}.${key}`, checked);
  };

  return (
    <Stack bg={"grey.0"} mih={"100vh"} p={"sm"}>
      <form>
        <Stack gap={20} bg={"white.0"} p={"sm"} bdrs={"sm"}>
          <Title order={6}>Role Details</Title>
          <Grid columns={6} gutter={"lg"}>
            <Grid.Col span={3}>
              <TextInput
                label="Role Name"
                placeholder="Enter Role name"
                key={form.key("name")}
                {...form.getInputProps("name")}
              />
            </Grid.Col>
            <Grid.Col span={6}>
              <Textarea
                rows={5}
                label="Description"
                placeholder="Enter Description"
                key={form.key("description")}
                {...form.getInputProps("description")}
              />
            </Grid.Col>
            <Grid.Col span={6}>
              <Stack gap={8}>
                <Flex justify="space-between" align="center">
                  <Title order={6}>Permissions</Title>
                  <Group
                    gap={6}
                    style={{ cursor: "pointer" }}
                    onClick={handleSelectAll}
                  >
                    <Text size="sm" c={isAllSelected ? "blue.9" : "dimmed"}>
                      Select All
                    </Text>
                    <Checkbox
                      checked={isAllSelected}
                      onChange={handleSelectAll}
                      size="xs"
                      styles={{ input: { cursor: "pointer" } }}
                    />
                  </Group>
                </Flex>

                <Table
                  withTableBorder
                  withColumnBorders={false}
                  withRowBorders
                  highlightOnHover
                  styles={{
                    thead: { backgroundColor: "var(--mantine-color-gray-0)" },
                    th: {
                      fontWeight: 500,
                      fontSize: "var(--mantine-font-size-sm)",
                    },
                  }}
                >
                  <Table.Thead>
                    <Table.Tr>
                      <Table.Th w="30%">Permissions</Table.Th>
                      {PRIVILEGE_KEYS.map((key) => (
                        <Table.Th key={key} tt="capitalize">
                          {key.charAt(0).toUpperCase() + key.slice(1)}
                        </Table.Th>
                      ))}
                    </Table.Tr>
                  </Table.Thead>
                  <Table.Tbody>
                    {adminFeatures.map((feature, index) => (
                      <Table.Tr key={feature.id}>
                        <Table.Td>
                          <Text size="sm">{feature.name}</Text>
                        </Table.Td>
                        {PRIVILEGE_KEYS.map((key) => {
                          const isDisabled = !allowedPrivileges(
                            feature.slug,
                          ).includes(key);
                          return (
                            <Table.Td key={key}>
                              <Checkbox
                                checked={
                                  form?.values?.privileges[index]?.[key] ??
                                  false
                                }
                                disabled={isDisabled}
                                onChange={(e) =>
                                  handlePrivilegeChange(
                                    index,
                                    key,
                                    e.currentTarget.checked,
                                  )
                                }
                                size="sm"
                                styles={{
                                  input: {
                                    cursor: isDisabled
                                      ? "not-allowed"
                                      : "pointer",
                                  },
                                }}
                              />
                            </Table.Td>
                          );
                        })}
                      </Table.Tr>
                    ))}
                  </Table.Tbody>
                </Table>
              </Stack>
            </Grid.Col>
          </Grid>
        </Stack>
        <Flex justify={"end"} mt={20}>
          <Button
            variant="filled"
            bg="blue.1"
            c="blue.9"
            loading={createLoading || updateLoading}
            onClick={handleSubmit}
          >
            Save
          </Button>
        </Flex>
      </form>
    </Stack>
  );
};

export default RoleForm;
