"use client";

/**
 * Filters for the campaigns page, as a right-hand drawer.
 *
 * Replaces the inline panel that used to sit between the page header and the
 * analytics card — moving it off-page lets the KPI tiles, charts and table read
 * as one block. The applied-filter chips stay on the page (`ActiveFilterChips`)
 * so a narrowed dataset is never silently narrowed.
 *
 * Filters still apply live as controls change; the drawer has no Apply step.
 */

import {
  Badge,
  Button,
  Divider,
  Drawer,
  Group,
  Indicator,
  ScrollArea,
  Stack,
  Text,
} from "@mantine/core";
import { IconFilter, IconRotate, IconX } from "@tabler/icons-react";
import { AnimatePresence } from "framer-motion";
import type { ReactNode } from "react";
import { motion, popChild, useReducedMotion } from "./motion";
import styles from "./promo.module.css";

/** One applied filter, rendered as a removable chip. */
export interface FilterChip {
  key: string;
  label: string;
  /**
   * Omitted for a filter the user cannot change.
   *
   * Some filters are fixed by the caller's role rather than chosen — a report locked to
   * one account type, for instance. Those still have to appear here, because the point
   * of these chips is that a narrowed dataset is never silently narrowed, and a
   * restriction the reader cannot see is the worst version of that. They simply have no
   * remove button, and no reason to offer one.
   */
  onRemove?: () => void;
  /** Shown on hover, to say why a fixed chip cannot be removed. */
  hint?: string;
}

/** Header button that opens the drawer, badged with the active filter count. */
export function FilterTrigger({
  activeCount,
  onClick,
}: {
  activeCount: number;
  onClick: () => void;
}) {
  return (
    <Indicator
      disabled={activeCount === 0}
      label={activeCount}
      size={18}
      offset={4}
    >
      <Button
        variant="default"
        leftSection={<IconFilter size={16} />}
        onClick={onClick}
      >
        Filters
      </Button>
    </Indicator>
  );
}

/** The on-page summary of what's currently filtered. */
export function ActiveFilterChips({
  chips,
  onReset,
}: {
  chips: FilterChip[];
  onReset: () => void;
}) {
  const reduce = useReducedMotion();

  return (
    <AnimatePresence initial={false}>
      {chips.length > 0 && (
        <motion.div
          initial={reduce ? false : { height: 0, opacity: 0 }}
          animate={{ height: "auto", opacity: 1 }}
          exit={{ height: 0, opacity: 0 }}
          transition={{ duration: 0.24, ease: [0.16, 1, 0.3, 1] }}
          style={{ overflow: "hidden" }}
        >
          <Group gap={6} wrap="wrap" mb="md" style={{ rowGap: 6 }}>
            <Text size="xs" c="dimmed" fw={600} mr={2}>
              Filtered by
            </Text>
            <AnimatePresence initial={false} mode="popLayout">
              {chips.map((chip) => (
                <motion.span
                  key={chip.key}
                  layout={!reduce}
                  variants={popChild}
                  initial={reduce ? false : "hidden"}
                  animate="show"
                  exit="exit"
                  className={styles.pill}
                  title={chip.hint}
                >
                  {chip.label}
                  {/* A fixed chip gets no close button rather than a disabled one: a
                      dead control invites clicking, and there is nothing to undo. */}
                  {chip.onRemove && (
                    <button
                      type="button"
                      className={styles.pillClose}
                      aria-label={`Remove filter ${chip.label}`}
                      onClick={chip.onRemove}
                    >
                      <IconX size={12} stroke={3} />
                    </button>
                  )}
                </motion.span>
              ))}
            </AnimatePresence>
            <Button
              variant="subtle"
              color="gray"
              size="compact-xs"
              leftSection={<IconRotate size={12} />}
              onClick={onReset}
            >
              Clear all
            </Button>
          </Group>
        </motion.div>
      )}
    </AnimatePresence>
  );
}

/** A labelled group of controls inside the drawer. */
export function FilterSection({
  icon,
  title,
  description,
  children,
  withDivider = true,
}: {
  icon: ReactNode;
  title: string;
  description?: string;
  children: ReactNode;
  withDivider?: boolean;
}) {
  return (
    <>
      <Stack gap="xs">
        <Group gap={8} align="center" wrap="nowrap">
          <span className={styles.sectionIcon}>{icon}</span>
          <Stack gap={0}>
            <Text size="sm" fw={700}>
              {title}
            </Text>
            {description && (
              <Text size="xs" c="dimmed">
                {description}
              </Text>
            )}
          </Stack>
        </Group>
        <Stack gap="sm">{children}</Stack>
      </Stack>
      {withDivider && <Divider my="xs" />}
    </>
  );
}

export function FilterDrawer({
  opened,
  onClose,
  activeCount,
  onReset,
  children,
}: {
  opened: boolean;
  onClose: () => void;
  activeCount: number;
  onReset: () => void;
  children: ReactNode;
}) {
  return (
    <Drawer
      opened={opened}
      onClose={onClose}
      position="right"
      size={500}
      padding="lg"
      overlayProps={{ backgroundOpacity: 0.35, blur: 3 }}
      scrollAreaComponent={ScrollArea.Autosize}
      title={
        <Group gap="sm" align="center">
          <IconFilter size={17} />
          <Text fw={700} size="lg">
            Filters
          </Text>
          {activeCount > 0 && (
            <Badge variant="filled" size="sm" radius="sm">
              {activeCount} active
            </Badge>
          )}
        </Group>
      }
    >
      <Stack gap="md">
        {children}

        <Group justify="space-between" mt="xs">
          <Button
            variant="subtle"
            color="gray"
            leftSection={<IconRotate size={15} />}
            onClick={onReset}
            disabled={activeCount === 0}
          >
            Reset all
          </Button>
          {/* Filters are live, so this only dismisses the drawer. */}
          <Button onClick={onClose}>Done</Button>
        </Group>
      </Stack>
    </Drawer>
  );
}
