import { RichTextComp } from "@/components/Richtext";
import {
  Box,
  Button,
  Collapse,
  Drawer,
  Flex,
  Grid,
  Group,
  Image,
  Menu,
  NativeSelect,
  NumberInput,
  Popover,
  Stack,
  Switch,
  Text,
  TextInput,
  Title,
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { useDisclosure } from "@mantine/hooks";
import {
  IconCarouselHorizontal,
  IconCirclePlus,
  IconExternalLink,
  IconLayoutBottombarExpandFilled,
  IconPlus,
  IconTrash,
} from "@tabler/icons-react";
import { zod4Resolver } from "mantine-form-zod-resolver";
import React, { useEffect, useMemo, useState } from "react";
import z from "zod";

const ExternalRedirectCTA = z
  .object({
    type: z.literal("external_redirect"),
    mode: z.enum(["direct", "sso", "mc_sso"]).optional(),
    label: z.string().min(1, "CTA label is required"),
    url: z.string().url("Invalid URL").optional(),
  })
  .refine(
    (data) => {
      if (data.mode !== "mc_sso") {
        return !!data.url && data.url.length > 0;
      }
      return true;
    },
    {
      error: "URL is required when mode is not MC SSO",
      path: ["url"],
    },
  );

const AppRoutingCTA = z.object({
  type: z.literal("app_routing"),
  label: z.string().min(1, "CTA label is required"),
  route: z.string().min(1, "Route name is required"),
  url: z.string().optional(),
});

const AppOverlayCTA = z.object({
  type: z.literal("app_overlay"),
  label: z.string().min(1, "CTA label is required"),
  identifier: z.string().min(1, "Overlay identifier is required"),
});

const CTA = z.discriminatedUnion("type", [
  ExternalRedirectCTA,
  AppRoutingCTA,
  AppOverlayCTA,
]);

const AlertVariant = z.object({
  type: z.string(),
  disposable: z.boolean(),
  content: z.string(),
  ctas: z.array(CTA),
});

export const schema = z.object({
  restriction_type: z.string().min(1, "Restriction type is required"),
  alert_variants: z.array(AlertVariant),
  block_booking_completion: z.number().min(0).default(1),
});

type CTAType = z.infer<typeof CTA>;
type AlertVariantType = z.infer<typeof AlertVariant>;
type SchemaType = z.infer<typeof schema>;

const CallToActionOptions = [
  {
    label: "External Redirection",
    value: "external_redirect" as const,
    Icon: IconExternalLink,
  },
  {
    label: "In-App Routing",
    value: "app_routing" as const,
    Icon: IconCarouselHorizontal,
  },
  {
    label: "App Overlay",
    value: "app_overlay" as const,
    Icon: IconLayoutBottombarExpandFilled,
  },
];

const AlertVariants = [
  {
    label: "App Bottom Sheet",
    value: "app-bottom-sheet",
    Icon: (
      <Image
        src={"/vectors/bottom-sheet.svg"}
        alt="App Bottom Sheet"
        w={50}
        h={"auto"}
      />
    ),
  },
  {
    label: "App Pop-Up",
    value: "app-pop-up",
    Icon: (
      <Image src={"/vectors/pop-up.svg"} alt="App Pop-Up" w={50} h={"auto"} />
    ),
  },
];

interface CTASetupProps {
  form: ReturnType<typeof useForm<SchemaType>>;
  alertIndex: number;
  ctaIndex: number;
}

const ExternalRedirectSetup: React.FC<CTASetupProps> = ({
  form,
  alertIndex,
  ctaIndex,
}) => {
  const [showUrlField, setShowUrlField] = useState(true);
  const base = `alert_variants.${alertIndex}.ctas.${ctaIndex}`;
  const modesData = [
    { label: "Direct", value: "direct" },
    { label: "SSO", value: "sso" },
  ];
  if (form.values.restriction_type === "management_charges_due") {
    modesData.push({ label: "MC SSO", value: "mc_sso" });
  }

  useEffect(() => {
    const cta = form.values.alert_variants[alertIndex].ctas[ctaIndex];
    if (cta && cta?.type === "external_redirect" && cta?.mode === "mc_sso") {
      setShowUrlField(false);
      form.setFieldValue(`${base}.url`, undefined);
    } else {
      setShowUrlField(true);
    }
  }, [form.values.alert_variants[alertIndex]]);
  return (
    <Grid gutter={8}>
      <Grid.Col span={2}>
        <NativeSelect
          label="Mode"
          data={modesData}
          {...form.getInputProps(`${base}.mode`)}
        />
      </Grid.Col>
      <Grid.Col span={4}>
        <TextInput
          label="CTA Label"
          placeholder="Enter CTA Label"
          {...form.getInputProps(`${base}.label`)}
        />
      </Grid.Col>
      {showUrlField && (
        <Grid.Col span={6}>
          <TextInput
            label="Redirection URL"
            placeholder="https://example.com"
            {...form.getInputProps(`${base}.url`)}
          />
        </Grid.Col>
      )}
    </Grid>
  );
};

const AppOverlaySetup: React.FC<CTASetupProps> = ({
  form,
  alertIndex,
  ctaIndex,
}) => {
  const base = `alert_variants.${alertIndex}.ctas.${ctaIndex}`;
  return (
    <Grid gutter={8}>
      <Grid.Col span={4}>
        <TextInput
          label="CTA Label"
          placeholder="Enter CTA Label"
          {...form.getInputProps(`${base}.label`)}
        />
      </Grid.Col>
      <Grid.Col span={8}>
        <TextInput
          label="Overlay Identifier"
          placeholder="Enter Overlay Identifier"
          {...form.getInputProps(`${base}.identifier`)}
        />
      </Grid.Col>
    </Grid>
  );
};

const InAppRoutingSetup: React.FC<CTASetupProps> = ({
  form,
  alertIndex,
  ctaIndex,
}) => {
  const base = `alert_variants.${alertIndex}.ctas.${ctaIndex}`;
  return (
    <Grid gutter={8}>
      <Grid.Col span={4}>
        <TextInput
          label="CTA Label"
          placeholder="Enter CTA Label"
          {...form.getInputProps(`${base}.label`)}
        />
      </Grid.Col>
      <Grid.Col span={4}>
        <TextInput
          label="Route Name"
          placeholder="Enter Route Name"
          {...form.getInputProps(`${base}.route`)}
        />
      </Grid.Col>
      <Grid.Col span={4}>
        <TextInput
          label="Url (Optional)"
          placeholder="url"
          {...form.getInputProps(`${base}.url`)}
        />
      </Grid.Col>
    </Grid>
  );
};

interface AppAlertPromptProps {
  index: number;
  form: ReturnType<typeof useForm<SchemaType>>;
  title: string;
  onRemoveAlertPrompt: () => void;
}

const AppAlertPrompt: React.FC<AppAlertPromptProps> = ({
  index,
  form,
  title,
  onRemoveAlertPrompt,
}) => {
  const baseAlert = `alert_variants.${index}`;
  const ctas: CTAType[] = form.values.alert_variants?.[index]?.ctas ?? [];
  const [opened, { toggle }] = useDisclosure(false);

  return (
    <Box
      bg={"grey.0"}
      py={6}
      px={12}
      bdrs={"sm"}
      style={{ border: "1px solid var(--mantine-color-grey-2)" }}
    >
      <Grid gutter={1}>
        <Grid.Col span={11}>
          <Button
            variant="transparent"
            onClick={toggle}
            size="compact-sm"
            w={"100%"}
            c={"grey.7"}
            justify="space-between"
          >
            <Text fw={500} fz={"sm"}>
              {title}
            </Text>
          </Button>
        </Grid.Col>
        <Grid.Col span={1}>
          <Button
            variant="subtle"
            onClick={onRemoveAlertPrompt}
            size="compact-sm"
            w={"100%"}
            c={"grey.7"}
          >
            <IconTrash size={14} />
          </Button>
        </Grid.Col>
      </Grid>

      <Collapse in={opened} mt={12}>
        <Stack>
          <Stack gap={4}>
            <Text fw={"bold"} fz={"sm"}>
              Alert Content
            </Text>

            <RichTextComp
              content={form.values.alert_variants[index]?.content ?? ""}
              onChange={(value) =>
                form.setFieldValue(`${baseAlert}.content`, value ?? "")
              }
            />
          </Stack>

          <Stack gap={20}>
            <Flex align="center">
              <Text fw={"bold"} fz={"sm"}>
                Call To Actions
              </Text>

              <Menu>
                <Menu.Target>
                  <Button
                    ml={14}
                    bg={"grey.1"}
                    c={"grey.8"}
                    p={2}
                    w={24}
                    h={24}
                  >
                    <IconPlus size={14} />
                  </Button>
                </Menu.Target>

                <Menu.Dropdown>
                  <Menu.Label>CTA Type</Menu.Label>
                  {CallToActionOptions.map(({ label, value }) => (
                    <Menu.Item
                      key={value}
                      onClick={() => {
                        const newCta: CTAType =
                          value === "external_redirect"
                            ? {
                                type: "external_redirect",
                                mode: "direct",
                                label: "",
                                url: "",
                              }
                            : value === "app_routing"
                              ? {
                                  type: "app_routing",
                                  label: "",
                                  route: "",
                                  url: "",
                                }
                              : {
                                  type: "app_overlay",
                                  label: "",
                                  identifier: "",
                                };

                        const existing =
                          form.values.alert_variants[index]?.ctas ?? [];
                        form.setFieldValue(`${baseAlert}.ctas`, [
                          ...existing,
                          newCta,
                        ]);
                      }}
                    >
                      <Flex align={"center"} gap={8}>
                        <Text>{label}</Text>
                      </Flex>
                    </Menu.Item>
                  ))}
                </Menu.Dropdown>
              </Menu>
            </Flex>

            <Stack gap={12}>
              {ctas.map((cta, ctaIndex) => {
                const CTAVariant = CallToActionOptions.find(
                  (cop) => cop.value === cta.type,
                );
                if (!CTAVariant) return null;
                const { label } = CTAVariant;
                return (
                  <Stack
                    key={ctaIndex}
                    bdrs={"sm"}
                    bd={"1px solid grey.2"}
                    px={12}
                    py={10}
                    bg={"white.0"}
                  >
                    <Group justify="space-between" align="center">
                      <Text fz={11} fw={700} c={"grey.4"}>
                        {label}
                      </Text>
                      <Button
                        variant="subtle"
                        size="compact-xs"
                        onClick={() => {
                          const updated =
                            form.values.alert_variants[index].ctas?.filter(
                              (_, i) => i !== ctaIndex,
                            ) ?? [];
                          form.setFieldValue(`${baseAlert}.ctas`, updated);
                        }}
                      >
                        <IconTrash size={14} />
                      </Button>
                    </Group>
                    {cta.type === "external_redirect" && (
                      <ExternalRedirectSetup
                        form={form}
                        alertIndex={index}
                        ctaIndex={ctaIndex}
                      />
                    )}
                    {cta.type === "app_routing" && (
                      <InAppRoutingSetup
                        form={form}
                        alertIndex={index}
                        ctaIndex={ctaIndex}
                      />
                    )}
                    {cta.type === "app_overlay" && (
                      <AppOverlaySetup
                        form={form}
                        alertIndex={index}
                        ctaIndex={ctaIndex}
                      />
                    )}
                  </Stack>
                );
              })}
            </Stack>
          </Stack>

          <Flex gap={8} align="center">
            <Text fw={"bold"} fz={"sm"}>
              Is Disposable?
            </Text>
            <Switch
              {...form.getInputProps(`${baseAlert}.disposable`, {
                type: "checkbox",
              })}
              checked={form.values.alert_variants[index]?.disposable ?? true}
              onChange={(e) =>
                form.setFieldValue(
                  `${baseAlert}.disposable`,
                  e.currentTarget.checked,
                )
              }
            />
          </Flex>
        </Stack>
      </Collapse>
    </Box>
  );
};

const AlertSetupComp: React.FC<{
  usedSetups: string[];
  onSetupSelect: (value: string) => void;
}> = ({ onSetupSelect, usedSetups }) => {
  const availableSetups = useMemo(() => {
    return AlertVariants.filter((av) => !usedSetups.includes(av.value));
  }, [usedSetups]);

  return (
    <Popover width={300} shadow="md" withArrow>
      <Popover.Target>
        <Button variant="subtle" p={0} w={"max-content"} h={"max-content"}>
          <Stack
            w={140}
            h={70}
            justify="center"
            align="center"
            bg={"grey.1"}
            c={"dark.3"}
            bdrs={"sm"}
            bd={`1px dashed grey.4`}
            gap={2}
          >
            <IconCirclePlus size={16} />
            <Text>Add Alert Prompt</Text>
          </Stack>
        </Button>
      </Popover.Target>

      <Popover.Dropdown>
        <Flex align={"center"} justify={"center"} gap={8}>
          {availableSetups.map(({ label, value, Icon }) => (
            <Button
              key={value}
              variant="subtle"
              onClick={() => onSetupSelect(value)}
              w={"max-content"}
              h={"max-content"}
            >
              <Stack align="center" justify="center" gap={4}>
                {Icon}
                <Text fz={12}>{label}</Text>
              </Stack>
            </Button>
          ))}
        </Flex>
      </Popover.Dropdown>
    </Popover>
  );
};

export const AccessRestrictionSettings: React.FC<{
  policy: {
    policy_type: string;
    access_type: string;
  };
  openDrawer: boolean;
  onDrawerClose: () => void;
  onSave: (value: Record<string, unknown>) => void;
  value?: Record<string, unknown> | null;
}> = ({ policy, openDrawer, onDrawerClose, onSave, value }) => {
  const form = useForm<SchemaType>({
    initialValues: {
      restriction_type: (value?.restriction_type as string) ?? "general",
      // alert_variants: (value?.alert_variants as AlertVariantType[]) ?? [],
      alert_variants: value?.alert_variants
        ? ((Array.isArray(value.alert_variants)
            ? value.alert_variants
            : [value.alert_variants]) as AlertVariantType[])
        : [],
      block_booking_completion:
        policy.access_type === "BLOCK_BOOKING_COMPLETION" ? 72 : 0,
    },
    validate: zod4Resolver(schema),
  });

  const handleSubmit = () => {
    const result = form.validate();
    if (!result.hasErrors) {
      const parsed = schema.safeParse(form.values);
      if (parsed.success) {
        onSave(parsed.data);
        onDrawerClose();
      }
    }
  };

  return (
    <Drawer
      position="right"
      opened={openDrawer}
      onClose={onDrawerClose}
      size={"lg"}
      overlayProps={{ backgroundOpacity: 0.5, blur: 4 }}
    >
      <Stack gap={20}>
        <Title order={6}>{policy.policy_type} Restrictions Settings</Title>

        <Stack gap={18}>
          <Grid>
            <Grid.Col span={6}>
              <NativeSelect
                label={"Restriction Reason"}
                data={[
                  { label: "General", value: "general" },
                  {
                    label: "Management Charges Due",
                    value: "management_charges_due",
                  },
                ]}
                key={form.key("restriction_type")}
                {...form.getInputProps("restriction_type")}
              />
            </Grid.Col>
            {policy.access_type === "BLOCK_BOOKING_COMPLETION" && (
              <Grid.Col span={6}>
                <NumberInput
                  suffix="Hrs"
                  label={"Booking Completion Block Period"}
                  key={form.key("block_booking_completion")}
                  {...form.getInputProps("block_booking_completion")}
                />
              </Grid.Col>
            )}
          </Grid>

          <Stack>
            {form.values.alert_variants.map((av, i) => {
              const variant = AlertVariants.find((v) => v.value === av.type);
              const label = variant?.label ?? av.type;
              return (
                <AppAlertPrompt
                  key={i}
                  index={i}
                  form={form}
                  title={label}
                  onRemoveAlertPrompt={() => {
                    const updated = form.values.alert_variants.filter(
                      (_, idx) => idx !== i,
                    );
                    form.setFieldValue("alert_variants", updated);
                  }}
                />
              );
            })}
          </Stack>

          {form.values.alert_variants.length === 0 && (
            <Flex justify={"center"} align={"center"}>
              <AlertSetupComp
                usedSetups={form.values.alert_variants.map((av) => av.type)}
                onSetupSelect={(value) => {
                  // push a new alert variant — default disposable true
                  form.setFieldValue("alert_variants", [
                    ...form.values.alert_variants,
                    {
                      type: value,
                      disposable: true,
                      content: "",
                      ctas: [],
                    },
                  ]);
                }}
              />
            </Flex>
          )}
        </Stack>

        <Group mt={8}>
          <Button onClick={handleSubmit} size="compact-md" fw={400}>
            Save
          </Button>
          <Button
            variant="outline"
            size="compact-md"
            fw={400}
            onClick={onDrawerClose}
          >
            Cancel
          </Button>
        </Group>
      </Stack>
    </Drawer>
  );
};

export default AccessRestrictionSettings;
